Search code examples
c#iis-7custom-actionservermanager

Resolve 'configuration object is read only, because it has been committed by a call to ServerManager.CommitChanges()'?


I've written a custom action for an installer project that does the following:

  • Checks existing websites to see if any exist with the same name put in by the user.
  • Creates the website in IIS if it doesn't exist.
  • Creates an application pool.
  • Assigns the application pool to the created website.

When it comes to assigning the application pool I get and error:

The configuration object is read only, because it has been committed by a call to ServerManager.CommitChanges(). If write access is required, use ServerManager to get a new reference.

This baffles me as it seems to suggest that I can't assign the newly created application pool with the ServerManager.CommitChanges() call. However, everything else works fine using this, which I wouldn't expect if this was an issue.

Here is my code:

I have a ServerManager instance created like so:

private ServerManager mgr = new ServerManager();

In my Install method I do the following:

Site site = CreateWebsite();
if (site != null)
{
    CreateApplicationPool();
    AssignAppPool(site);
}

Check existing websites - done in OnBeforeInstall method

    private Site CheckWebsites()
    {
        SiteCollection sites = null;
        Site site = null;

        try
        {
            sites = mgr.Sites;
            foreach (Site s in sites)
            {
                if (!string.IsNullOrEmpty(s.Name))
                {
                    if (string.Compare(s.Name, targetSite, true) == 0) site = s;
                }
            }
        }
        catch{}

        return site;
    }

CreateWebSite method:

    private Site CreateWebsite()
    {
        Site site = CheckWebsites();

        if (site == null)
        {
            SiteCollection sites = mgr.Sites;
            int port;
            Int32.TryParse(targetPort, out port);
            site = sites.Add(targetSite, targetDirectory, port);
            mgr.CommitChanges();
        }
        else
        {
            //TO DO - if website already exists edit settings
        }

        return site;
    }

Create App Pool

//non-relevant code...

ApplicationPool NewPool = mgr.ApplicationPools.Add(ApplicationPool);
NewPool.AutoStart = true;
NewPool.ManagedRuntimeVersion = "4.0"; 
NewPool.ManagedPipelineMode = ManagedPipelineMode.Classic;
mgr.CommitChanges();

Assign App Pool

private void AssignAppPool(Site site)
{
    site.ApplicationDefaults.ApplicationPoolName = ApplicationPool; //ERRORS HERE
    mgr.CommitChanges();
}

I can't see why a site could be created, an app pool created but then not assigned. Help.


Solution

  • I finally realised that the 'configuration object' referred to in the error was the 'site'. Seems obvious now, but basically I needed to re-get the site to then assign the app pool to it. I think this is allow the previous changes to take place and then pick them up. So I altered my code by removing the need to pass the Site into private void AssignAppPool() and just getting the site again like this:

    Site site = mgr.Sites["TestWebApp"];