2012-04-30 7 views
6

Estoy tratando de agregar mediante programación un enlace a mi sitio web predeterminado, sin embargo, siempre obtengo una excepción de referencia nula dentro de la dll de Microsoft.Web.Administration. Originalmente quería asignar un certificado junto con el enlace. Yo era capaz de consultar el certificado que quería con esto:NullReferenceException en Microsoft.Web.Administration al agregar el enlace https

var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine); 
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite); 

var certificate = store.Certificates.Find(X509FindType.FindByIssuerName, 
                "TEST_SELF_SIGNED", true) 
                .OfType<X509Certificate>().FirstOrDefault(); 

Este adecuadamente me dio el certificado que quería, que era no nulo y tenía la información que esperaba.

Site site = GetSite("Default Web Site"); 
var binding = site.Bindings.Add("*:443", certificate.GetCertHash(), "https"); 

Dado que ninguno de mis variables o cualquier otro artículo en el código de ejemplo son nulos (incluyendo GetCertHash que devuelve una matriz de 20 bytes) Estoy confundido en cuanto a por qué estoy recibiendo un nulo aquí. Incluso he intentado lo siguiente sobrecarga:

site.Bindings.Add("*:443", "https"); 

Y sigo teniendo la misma pila ref nulo:

System.NullReferenceException was unhandled 
    Message=Object reference not set to an instance of an object. 
    Source=Microsoft.Web.Administration 
    StackTrace: 
     at Microsoft.Web.Administration.Configuration.SetDirty() 
     at Microsoft.Web.Administration.ConfigurationElement.SetDirty() 
     at Microsoft.Web.Administration.ConfigurationElement.SetAttributeValue(String attributeName, Object value) 
     at Microsoft.Web.Administration.Binding.SetBindingProperty(String attributeName, String value) 
     at Microsoft.Web.Administration.BindingCollection.Add(String bindingInformation, Byte[] certificateHash, String certificateStoreName) 
     at TestApp.Program.Main(String[] args) in C:\Projects\Cube\trunk\src\AutoUpdate\TestApp\Program.cs:line 33 
     at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) 
     at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 
     at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 
     at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
     at System.Threading.ThreadHelper.ThreadStart() 
    InnerException:

Aquí es una prueba de la aplicación completa que demonstartes el tema, junto con los argumentos de línea de comando SelfSSL I utilizados para generar el certificado de muestra:

selfssl.exe/T/N: CN = TEST_SELF_SIGNED/K: 512/V: 9,999/Q

class Program 
{ 
    static void Main(string[] args) 
    { 

     using (ServerManager manager = new ServerManager()) 
     { 
      var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine); 
      store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite); 

      var certificate = store.Certificates.Find(X509FindType.FindByIssuerName, "TEST_SELF_SIGNED", true).OfType<X509Certificate>().FirstOrDefault(); 

      Site site = GetSite("Default Web Site"); 
      site.Bindings.Add("*:443", certificate.GetCertHash(), store.Name); 

      store.Close(); 

      manager.CommitChanges(); 
     } 
    } 

    public static Site GetSite(string siteName) 
    { 
     using (var serverManager = new ServerManager()) 
     { 
      return serverManager.Sites.Where(p => p.Name.ToLower() == siteName.ToLower()).FirstOrDefault(); 
     } 
    } 
} 

Solo para cubrir mis bases, Iis está instalado y la asignación manual del certificado funciona muy bien.

Respuesta

7

Así que encontré la respuesta descompilando la DLL de Administración de Microsoft.Web y hurgando en la pila. Resulta que si obtiene un Sitio con una función auxiliar, no establece la propiedad interna del Administrador del servidor en el sitio.

La función de la DLL que causó el problema era esto en Microsoft.Web.Administration :: Configuración

internal void SetDirty() 
{ 
    if (this._hasBeenCommitted || this._configurationManager.Owner.ReadOnly) 
    throw new InvalidOperationException(Resources.ObjectHasBeenCommited); 
    this._isDirty = true; 
} 

La única cosa que podría haber sido nula aquí estaba bien _configurationManager o _configurationManager.Owner. Comprobé qué era Owner y fue un ServerManager que me avisó que probablemente debería consultar el Site desde dentro de un bloque usando el administrador del servidor. Una vez que hice eso, el ref nulo se fue y todo funcionó. Es desafortunado que no estén buscando nulos, pero tal vez la suposición es que nadie actuaría en un objeto del sitio sin el contexto del administrador del servidor.

De todas formas, aquí es el código de actualización:

class Program 
{ 
    static void Main(string[] args) 
    { 

     using (var serverManager = new ServerManager()) 
     { 
      var selfSignedCnName = "TEST_SELF_SIGNED"; 
      var websiteName = "Default Web Site"; 

      var site = serverManager.Sites.Where(p => p.Name.ToLower() == websiteName.ToLower()).FirstOrDefault(); 
      var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine); 
      store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite); 

      var certificate = store.Certificates.Find(X509FindType.FindByIssuerName, selfSignedCnName, true).OfType<X509Certificate>().FirstOrDefault(); 

      site.Bindings.Add("*:443:", certificate.GetCertHash(), store.Name); 

      store.Close(); 

      serverManager.CommitChanges(); 
     } 
    } 

} 

También es claro a partir de mi post inicial que envolver todo el bloque de código en un administrador de servidor no significa nada, que no se conectan en cascada. Debe actuar en el sitio desde el administrador del servidor del que proviene.

Cuestiones relacionadas