Overview
The HttpApplication object is not familiar with ASP. NET development. In ASP. NET development, it is often unavoidable to execute some operations in HttpApplication, such as using ASP. net mvc framework, the following routing Rule Configuration Code cannot be avoided in the Application_Start event:
protected void Application_Start(){ RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); RouteTable.Routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = "" } // Parameter defaults );}
If this is the only one, it seems that there is no problem, but if you use a workflow in the application at the same time, you cannot avoid the code when starting the workflow running in Application_Start:
Protected void Application_Start () {// register the routing rule RouteTable. routes. ignoreRoute ("{resource }. axd/{* pathInfo} "); RouteTable. routes. mapRoute ("Default", // Route name "{controller}/{action}/{id}", // URL with parameters new {controller = "Home ", action = "Index", id = ""} // Parameter defaults); // start the workflow WorkflowRuntime workflowRuntime = new WorkflowRuntime ("workflowServicesConfig"); ExternalDataExchangeService quota = new quota (); workflowRuntime. addService (externalDataExchangeService); workflowRuntime. startRuntime ();}
Imagine that now we only have ASP. net mvc routing rule configuration and start of WF runtime. If a DI framework is used in an application, such as Microsoft Unity, isn't it possible to avoid such container initialization code?
Protected void Application_Start () {// register the routing rule RouteTable. routes. ignoreRoute ("{resource }. axd/{* pathInfo} "); RouteTable. routes. mapRoute ("Default", // Route name "{controller}/{action}/{id}", // URL with parameters new {controller = "Home ", action = "Index", id = ""} // Parameter defaults); // start the workflow WorkflowRuntime workflowRuntime = new WorkflowRuntime ("workflowServicesConfig"); ExternalDataExchangeService quota = new quota (); workflowRuntime. addService (externalDataExchangeService); workflowRuntime. startRuntime (); // initialize DI container IContainerContext repositoryContainer = ContainerManager. getContainer ("repositoryContainer"); repositoryContainer. initialize ();}
Let's look at the code in the Application_Start event, including ASP. net mvc, WF, and Unity. I don't know what else will happen in the future? These codes, which were originally unrelated to each other, are now heap together at the same time. When every part (or every framework) changes, it will involve modifications to the Code in Application_Start, apparently violates the OCP principle. Is there a mechanism to make these unrelated modules independent from each other, and does not affect HttpApplication when their respective modules change? In this case, we need to expand HttpApplication to provide an extension point so that programs in other modules can be appended to HttpApplication.
Scalable Object Mode
We know that WCF provides a perfect extension mechanism, which provides extension points in almost every step of service execution, such as ServiceHostBase, OperationContext, InstanceContext, and IContextChannel, all these objects belong to extensible objects, and all of them obtain the set used for all Extensions through the Extensions attribute. Can we use this method to expand HttpApplication? The answer is yes. After reading MSDN, you will know that. the ServiceModel namespace provides the following interfaces: IExtensibleObject, IExtension, and IExtensionCollection, which are the three most important interfaces in the Extensible object mode.
IExtensibleObject naturally defines an extensible object, that is, who we want to extend. Its definition is very simple. It only provides a read-only attribute Extensions to provide a set of all extension objects, the following code is used:
public interface IExtensibleObject<T> where T : IExtensibleObject<T>{ IExtensionCollection<T> Extensions { get; }}
IExtension defines the contract of the extension object so that the object can expand another object by aggregating (another object here refers to the extended Host IExtensibleObject mentioned above ), two very important methods Attach and Detach are defined in IExtension to provide aggregation or disaggregation notifications.
public interface IExtension<T> where T : IExtensibleObject<T>{ void Attach(T owner); void Detach(T owner);}
When an extended object IExtension is attached to an extended object's extended set, its Attach method is called. Otherwise, if an extended object is removed from the set, its Detach method is called. This can be verified by Reflector, as shown in the following code:
protected override void InsertItem(int index, IExtension<T> item){ lock (base.SyncRoot) { item.Attach(this.owner); base.InsertItem(index, item); }}protected override void RemoveItem(int index){ lock (base.SyncRoot) { base.Items[index].Detach(this.owner); base.RemoveItem(index); }}
The last interface is IExtensionCollection, which is a collection of IExtension objects.
Expand HttpApplication
Next, let's take a look at how to use the Extensible object mode to expand HttpApplication. First, define the Extensible object, let ExtensibleHttpApplication derive from HttpApplication, and implement the IExtensibleObject interface, the generic parameter type is its own, as shown in the following code:
public class ExtensibleHttpApplication : HttpApplication, IExtensibleObject<ExtensibleHttpApplication>{ private IExtensionCollection<ExtensibleHttpApplication> _extensions; public ExtensibleHttpApplication() { this._extensions = new ExtensionCollection<ExtensibleHttpApplication>(this); } public IExtensionCollection<ExtensibleHttpApplication> Extensions { get { return this._extensions; } }}
With an extensible HttpApplication, You need to implement any function in the HttpApplication, And you can append it to the ExtensibleHttpApplication as an extension, for example, implementing ASP. net mvc routing, you can define an extension object as shown in the following code:
public class MvcHttpApplication : IExtension<ExtensibleHttpApplication>{ public void Attach(ExtensibleHttpApplication owner) { RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); RouteTable.Routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = "" } // Parameter defaults ); } public void Detach(ExtensibleHttpApplication owner) { //nothing }}
Similarly, if you want to start Workflow in HttpApplication, you can define an extension object for Workflow, as shown in the following sample code:
public class WorkflowHttpApplication : IExtension<ExtensibleHttpApplication>{ private WorkflowRuntime workflowRuntime; public void Attach(ExtensibleHttpApplication owner) { workflowRuntime = new WorkflowRuntime("workflowServicesConfig"); ExternalDataExchangeService externalDataExchangeService = new ExternalDataExchangeService(); workflowRuntime.AddService(externalDataExchangeService); workflowRuntime.StartRuntime(); } public void Detach(ExtensibleHttpApplication owner) { workflowRuntime.StopRuntime(); }}
We have defined the corresponding extension object. You only need to append the extension object to the ExtensibleHttpApplication in the corresponding HttpApplication. modify the code in Global. asax as follows:
public class MvcApplication : ExtensibleHttpApplication{ protected void Application_Start() { this.Extensions.Add(new MvcHttpApplication()); this.Extensions.Add(new WorkflowHttpApplication()); }}
Does the Code look more elegant now? If you want to add other Execution Code in Application_Start, you only need to write the corresponding Extension object and add it to the Extension set. Some may ask, do you still need to modify the code in Application_Start for every new code added? Don't forget, you can solve this problem through configuration. In WCF, the extension can also be implemented through configuration, isn't it? Similarly, if we need to release some objects in the Application_End event, we can directly remove it from the extension set, and then we will call its Detach method.
Summary
This article describes how to use the Extensible Object Mode extended HttpApplication provided in WCF. In fact, the Extensible object mode can be extended far beyond this. any object we want to extend to or a custom type in the. NET class library can be extended using the Extensible object mode.
Special thanks: Jesse Qu
Note 1: Due to TerryLee's recent busy with other transactions and having no time to worry about the Blog, a large number of comments and emails failed to reply. Please forgive me.
Note 2: The book Silverlight 2 Journey to perfection, written by TerryLee, will be available soon at the end of this month. For details, visit the official website http://www.dotneteye.cn/silverlight.