SPApplicationPool - Never forget that Application pools created in IIS directly cannot be used with the SharePoint object model.

The usual and the slowest way of changing the apppool association of a SharePoint webapplication is :

A)From Central Admin, delete the web application w/o deleting the Content DataBase.

B)Create a new web application with the same properties (most importantly URL..and then other properties mentioned below) as the original web application.

C)After the web application is created, go to the “Content Databases” section of that web application and:

-Remove the new Content DB created by the web application provisioning process.

-Attach the original content DataBase.

Of course, after this other properties that come as part of manual web.config changes, AAM settings, Solutions and web-application level Feature settings need to be manually re-associated with the new webapplication.

This post is about the faster way of changing apppool associations of SharePoint webapplication, and the things one need to take care while driving in the fast lane.

So, one of my customer who provided hosting service to its own customer’s in turn, had zillions of webapplications (not going into the best practices bit here) and wanted to change the app-pool associations of many of these).They were aware that if they change this manually in IIS, SharePoint config is still unaware of the changes and things could come to a standstill the next time they run PSCONFIG for a patch update.

So, they created an app-pool manually in IIS called “Charlie” (because they wanted to base it on an already existing template) and used below code (without the highlighted part and hence this post) to update the app-pool . They tested it in Dev environment, and making sure it worked, created an .exe and ran it in Production.

<Sample-Code>

             SPFarm farm = SPFarm.Local;
            SPWebService service = farm.Services.GetValue<SPWebService>();
            SPApplicationPool appPool = service.ApplicationPools["Charlie"];

            SPSite site = new SPSite("https://<root-site-url>");
            SPWebApplication webApp = site.WebApplication;
            if (webApp != null && appPool !=null )
            {
                try
                {
                    webApp.ApplicationPool = appPool;
                    webApp.Update();
                    webApp.ProvisionGlobally();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }

</Sample-Code>

This code above evidently gave Object reference not set to an instance of an object

At webApp.Update() because appPool object was null. Because it couldn’t find the newbie “Charlie” application pool in the SharePoint config database.

Of course, we did ignore the fact that application pools created in IIS directly cannot be used with the SharePoint object model and below are examples of the harm it did :

The main site at https://<root-site-url was not browsable, with :

[NullReferenceException: Object reference not set to an instance of an object.]

Microsoft.SharePoint.Library.SPRequestInternalClass.PreInitServer(String bstrAbsoluteRequestUrl, String bstrServerRelativeUrl, Int32 lZone, Guid gApplicationId, Guid gSiteId, Guid gDatabaseId, String bstrDatabaseServer, String bstrDatabaseName, String bstrDatabaseUsername, String bstrDatabasePassword, Boolean fHostHeaderIsSiteName) +0

Microsoft.SharePoint.Library.SPRequest.PreInitServer(String bstrAbsoluteRequestUrl, String bstrServerRelativeUrl, Int32 lZone, Guid gApplicationId, Guid gSiteId, Guid gDatabaseId, String bstrDatabaseServer, String bstrDatabaseName, String bstrDatabaseUsername, String bstrDatabasePassword, Boolean fHostHeaderIsSiteName) +346

Microsoft.SharePoint.SPSite.PreinitializeServer(SPRequest request) +346

Microsoft.SharePoint.SPWeb.InitializeSPRequest() +263

Microsoft.SharePoint.SPWeb.EnsureSPRequest() +51

Microsoft.SharePoint.SPWeb.get_Request() +45

Microsoft.SharePoint.WebControls.SPControl.SPWebEnsureSPControl(HttpContext context) +338

Microsoft.SharePoint.WebControls.SPControl.GetContextWeb(HttpContext context) +25

Microsoft.SharePoint.ApplicationRuntime.SPRequestModule.PostResolveRequestCacheHandler(Object oSender, EventArgs ea) +322

System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +92

System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +64

Clicking on Create a webapplication (_admin/extendvs.aspx) gave below exception:

Object reference not set to an instance of an object. at Microsoft.SharePoint.Administration.SPVirtualServer.InitializeApplicationComponents(SPWebApplication application, SPUrlZone zone)
at Microsoft.SharePoint.Administration.SPVirtualServerCollection.Undirty()
at Microsoft.SharePoint.Administration.SPVirtualServerCollection..ctor()
at Microsoft.SharePoint.Administration.SPGlobalAdmin.get_VirtualServers()
at Microsoft.SharePoint.WebControls.IisWebSiteSection.PopulateIisWebSiteDropDownList()
at Microsoft.SharePoint.WebControls.IisWebSiteSection.OnLoad(EventArgs e)
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

And if try to stop the Webapplication service (Windows SharePoint Services Web Application) through UI:

Object reference not set to an instance of an object. at Microsoft.SharePoint.ApplicationPages.ServerPage.OnObjectModelAction(Object sender, ObjectModelActionEventArgs e)
at Microsoft.SharePoint.WebControls.ActionLinkDataSourceControl.OnObjectModelAction(ObjectModelActionEventArgs e)
at Microsoft.SharePoint.WebControls.ActionLinkDataSourceControl.RaisePostBackEvent(String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

So the above code, though failed, yet updated the ApplicationPool property of the webapplication with a null object.The same could be confirmed by looking a the Objects table in SharePoint_Config database.

In Objects table, observing the “Properties” column of the object corresponding to the SPWebApplication under contention, one found the field corresponding to application pool as null.

<object type="Microsoft.SharePoint.Administration.SPWebApplication……

...........

..........

<fld name="m_ApplicationPool" type="null" />

 

..........

..........

</object>

And of course there is no ‘Microsoft.SharePoint.Administration.SPApplicationPool’ object corresponding to the new AppPool which was created manually. So the null apppool is what lead to the erroneous conditions, some of which have been mentioned above.

The learning is that we should have created the new App Pool using the SharePoint Object Model code, so that Config database is aptly updated.

We can initialise a new SPApplicationPool object - https://msdn.microsoft.com/en-us/library/ms458407.aspx

Set its properties – username, password etc… and then Deploy it. I will post the code-snippet once I am done testing it.