Previous MVC event series (2): HttpRuntime detailed analysis (I)

Source: Internet
Author: User

Article content

As mentioned in the previous chapter, asp.net runs in HttpRuntime, but it may not be clear how the CLR enters HttpRuntime. This section describes the important steps of net4. First look:

 

First, the CLR loads a very important class AppManagerAppDomainFactory during initialization and loading. What is the purpose of this class? First, this class inherits the IAppManagerAppDomainFactory interface, which has a Create method that can be called by COM. The Code is as follows:

 [ComImport, Guid("02998279-7175-4d59-aa5a-fb8e44d4ca9d"), System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown)]    public interface IAppManagerAppDomainFactory { #if !FEATURE_PAL // FEATURE_PAL does not enable COM         [return: MarshalAs(UnmanagedType.Interface)]#else // !FEATURE_PAL         Object Create(String appId, String appPath);#endif // !FEATURE_PAL        Object Create([In, MarshalAs(UnmanagedType.BStr)] String appId,                       [In, MarshalAs(UnmanagedType.BStr)] String appPath);          void Stop();    } 

 

Let's take a closer look at how this AppManagerAppDomainFactory implements this interface. First, this class obtains an ApplicationManager instance in the default constructor for use in the Create method. The Code is as follows:

[SecurityPermission(SecurityAction.Demand, Unrestricted=true)]public AppManagerAppDomainFactory() {    _appManager = ApplicationManager.GetApplicationManager();    _appManager.Open();} 

 

Return to the Create method of the implementation interface, let's look at the three most important lines of code:

ISAPIApplicationHost appHost = new ISAPIApplicationHost(appId, appPath, false /*validatePhysicalPath*/); ISAPIRuntime isapiRuntime = (ISAPIRuntime)_appManager.CreateObjectInternal(appId, typeof(ISAPIRuntime), appHost,        false /*failIfExists*/, null /*hostingParameters*/);isapiRuntime.StartProcessing();

 

The main function of the code is to get the ISAPIRuntime instance through the CreateObjectInternal operation of ApplicationManager, and then let the unmanaged code call. Therefore, the CreateObjectInternal method plays a vital role here: Creating AppDomain, creating HostingEnvironment, and other operations.

 

First, let's take a look at the constructor of AppManagerAppDomainFactory. The ApplicationManager. GetApplicationManager () method called in it is a singleton implementation. The Code is as follows:

public static ApplicationManager GetApplicationManager() {    if (_theAppManager == null) {        lock (_applicationManagerStaticLock) {            if (_theAppManager == null) {                if (HostingEnvironment.IsHosted)                    _theAppManager = HostingEnvironment.GetApplicationManager();                 if (_theAppManager == null)                    _theAppManager = new ApplicationManager();            }        }    }     return _theAppManager;}

 

From the code point of view, you may wonder why the static method GetApplicationManager () is called to obtain the ApplicationManager instance when the HostingEnvironment attribute IsHosted is true, this is because ApplicationManager will automatically pass this to the HostingEnvironment object instance when creating and initializing the HostingEnvironment object in subsequent steps (this will be detailed later ).

 

Let's look back at the CreateObjectInternal method of the ApplicationManager instance. Some code is as follows:

// get hosting environmentHostingEnvironment env = GetAppDomainWithHostingEnvironment(appId, appHost, hostingParameters); // create the managed object in the worker app domain// When marshaling Type, the AppDomain must have FileIoPermission to the assembly, which is not// always the case, so we marshal the assembly qualified name insteadObjectHandle h = env.CreateWellKnownObjectInstance(type.AssemblyQualifiedName, failIfExists);return (h != null) ? h.Unwrap() as IRegisteredObject : null;

 

The Code shows that you first need to get the HostingEnvironment instance, and then return the ISAPIRuntime instance required by the Create method through the CreateWellKnownObjectInstance method of the instance. Then we should be able to think That GetAppDomainWithHostingEnvironment has two functions: first, get the AppDomain, and second, get the HostingEnvironment instance to see if the code is as expected. First, let's look at the Code:

private HostingEnvironment GetAppDomainWithHostingEnvironment(String appId, IApplicationHost appHost, HostingEnvironmentParameters hostingParameters) {    LockableAppDomainContext ac = GetLockableAppDomainContext (appId);     lock (ac) {        HostingEnvironment env = ac.HostEnv;         if (env != null) {            try {                env.IsUnloaded();            } catch(AppDomainUnloadedException) {                env = null;            }        }        if (env == null) {            env = CreateAppDomainWithHostingEnvironmentAndReportErrors(appId, appHost, hostingParameters);            ac.HostEnv = env;            Interlocked.Increment(ref _accessibleHostingEnvCount);        }        return env;    } }

 

The Code tells us that we will first check whether there will be an existing AddDomain and the corresponding HostingEnvironment instance. If there is any returned result, a new one will be created. After a call, we finally came to a private method CreateAppDomainWithHostingEnvironment. In this 300-line Private method, there were something we had been confused for a long time.

First, there will be code on the trust level, such as running on FullTrust or MiddleTrust. Here there will be corresponding code processing, because the focus of this code analysis is not here, so the specific code is not detailed. Let's look at the code snippet we need to know:

// Create the app domain AppDomain appDomain = null; // many codes are omitted here if (isLegacyCas) {appDomain = AppDomain. createDomain (domainId, # if FEATURE_PAL // FEATURE_PAL: hack to avoid non-supported hosting features null, # else // outputs (), # endif // FEATURE_PALsetup );} else {appDomain = AppDomain. createDomain (domainId, # if FEATURE_PAL // FEATURE_PAL: hack to avoid non-supported hosting features null, # else // FEATURE_PAL reset (), # endif // FEATURE_PAL setup, permissionSet, fullTrustAssemblies/* fully trusted assemblies list: null means only trust GAC assemblies */);}

 

The Code shows that this is where the AppDomain was created in the legend. All subsequent things, such as HttpRuntime, and HttpContext, are based on this AppDomain. This is why HttpContext cannot be shared across multiple sites, the reason for security exists in AppDomain.

Continue to look at the following code lines after creating the AppDomain:

Type hostType = typeof (HostingEnvironment); String module = hostType. module. assembly. fullName; String typeName = hostType. fullName; ObjectHandle h = null; // a lot of code h = Activator is omitted here. createInstance (appDomain, module, typeName); // The HostingEnvironment env = (h! = Null )? H. unwrap () as HostingEnvironment: null; // many codes are omitted here. if (appDomainStartupConfigurationException = null) {env. initialize (this, appHost, configMapPathFactory, hostingParameters, policyLevel);} else {env. initialize (this, appHost, configMapPathFactory, hostingParameters, policyLevel, appDomainStartupConfigurationException);} return env;

 

This is where the HostingEnvironment instance is created. After the instance is created, the Initialize method will be called to Initialize the instance and the object instance will be returned. (note that the first parameter of this method is this, that is, the ApplicationManager instance itself explains why the static method GetApplicationManager () of HostingEnvironment can be used to obtain the ApplicationManager instance ).

 

With this code, we can simply understand how to obtain the ISAPIRuntime instance to prepare for entering HttpRuntime. However, I'm still curious about what the Initialize Initialization Method of HostingEnvironment has done. Let's take a look.

OK. An important line of code is displayed:

// initiaze HTTP-independent featuresHttpRuntime.InitializeHostingFeatures(hostingFlags, policyLevel, appDomainCreationException);

 

This Code enters the static HttpRuntime method, and then calls the HostingInt Method for initialization. One line of code is also required, as shown below:

// Initialize the build managerBuildManager.InitializeBuildManager();

 

The InitializeBuildManager method of BuildManager calls its own Initialize method to Initialize other work, including compiling all. NET source code in the App_Code directory. We know from the above series that there is only one HostringEnvironment in an AppDomain, so the Initialize of this BuildManager is only executed once, this ensures that compilation is not a problem (the source code comment also says so ).

 

In addition, when initialization fails in the HostingInit method, there is a special line of code in the catch:

_hostingInitFailed = true;

 

This means that when the HostingEnvironment fails to be created, the HostingInitFailed of HttpRuntime will be assigned True. The concepts of preapplicationstartmethodattriator discussed later and the WebActivator entry have a relationship with this value. We will not discuss it here, but will discuss it later.

 

Return to the Create method of AppManagerAppDomainFactory. After the ISAPIRuntime instance is obtained and the StartProcessing method is run, an ObjectHandle object is returned to the unmanaged code, including the ISAPIRuntime instance. The Code is as follows:

return new ObjectHandle(isapiRuntime);

 

What should I do after the unmanaged code accepts the ObjectHandle object? Let's take a look at the further analysis in the next article.

Synchronization and recommendation

This article has been synchronized to the Directory Index: the previous MVC Series

The previous MVC series of articles, including original articles, translations, reposts, and other types of articles. If they are useful to you, we recommend that you support them to give uncle the motivation to write.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.