2012-04-30 20 views
6

Tôi đang cố gắng thêm lập trình ràng buộc vào trang web mặc định của mình tuy nhiên tôi liên tục nhận được ngoại lệ tham chiếu null trong tệp Microsoft.Web.Administration. Ban đầu tôi muốn chỉ định một chứng chỉ cùng với ràng buộc. Tôi đã có thể truy vấn chứng chỉ mà tôi muốn với điều này:NullReferenceException trong Microsoft.Web.Quản trị khi thêm https binding

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(); 

Điều này đã cho tôi chứng chỉ tôi muốn, nó không có giá trị và có thông tin tôi mong đợi.

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

Vì không có biến nào của tôi hoặc bất kỳ mục nào khác trong mã mẫu không có giá trị (bao gồm GetCertHash trả về mảng 20 byte). Tôi thậm chí đã cố gắng quá tải sau:

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

Và tôi vẫn nhận được cùng vô 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:

Dưới đây là một thử nghiệm ứng dụng đầy đủ mà demonstartes vấn đề này, cùng với các đối số dòng lệnh SELFSSL tôi sử dụng để tạo ra các giấy chứng nhận mẫu:

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(); 
     } 
    } 
} 

Chỉ để trang trải các căn cứ của tôi, IIS được cài đặt và gán thủ công chứng chỉ hoạt động tốt.

Trả lời

7

Vì vậy, tôi đã tìm thấy câu trả lời bằng cách giải mã dll Microsoft.Web.Administration và poking qua ngăn xếp. Nó chỉ ra rằng nếu bạn nhận được một trang web với một chức năng trợ giúp nó không thiết lập các tài sản ServerManager nội bộ trên trang web.

Chức năng dll đó gây ra vấn đề là này trong Microsoft.Web.Administration :: Cấu hình

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

Điều duy nhất mà có thể đã vô đây là một trong hai _configurationManager hoặc _configurationManager.Owner. Tôi đã kiểm tra những gì Owner đã và nó là một ServerManager mà nghiêng tôi ra rằng tôi có lẽ nên truy vấn các Site từ bên trong một khối sử dụng của người quản lý máy chủ. Một khi tôi đã làm điều đó ref ref null đi và tất cả mọi thứ đã làm việc. Thật không may là họ không kiểm tra cho null nhưng có lẽ giả định là không ai sẽ hành động trên một đối tượng trang web mà không có bối cảnh quản lý máy chủ.

Anyways, đây là mã Cập nhật:

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(); 
     } 
    } 

} 

Nó cũng rõ ràng từ bài ban đầu của tôi rằng gói các khối mã toàn bộ trong một nhà quản lý máy chủ không có nghĩa là bất cứ điều gì, họ không được cascaded. Bạn phải hành động trên trang web từ trình quản lý máy chủ mà nó đến từ đó.

Các vấn đề liên quan