I am trying to programmatically add a binding to my default website, but I am constantly getting a null-link exception in the Microsoft.Web.Administration dll. Initially, I wanted to assign a certificate along with the binding. I was able to request the certificate I need:
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();
This correctly gave me the certificate that I wanted, it was not null and had the information that I expected.
Site site = GetSite("Default Web Site"); var binding = site.Bindings.Add("*:443", certificate.GetCertHash(), "https");
Given that none of my variables or any other elements in the sample code are null (including GetCertHash, which returns an array of 20 bytes), I am confused about why I get null here. I even tried the following overload:
site.Bindings.Add("*:443", "https");
And I still get the same zero ref stack:
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:
Here is a complete test application that demonstrates the problem, as well as the selfssl command line arguments that I used to create the sample certificate:
selfssl.exe / T / N: CN = TEST_SELF_SIGNED / K: 512 / V: 9999 / 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(); } } }
Just to cover my bases, Iis is installed and manually assigning a certificate works fine.