添加HTTPS绑定时的NullReferenceException在Microsoft.Web.Administration [英] NullReferenceException in Microsoft.Web.Administration when adding https binding

查看:469
本文介绍了添加HTTPS绑定时的NullReferenceException在Microsoft.Web.Administration的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图以编程方式添加绑定到我的默认网站但是我始终得到Microsoft.Web.Administration DLL中的空引用异常。本来我想与绑定一起分配证书。我能够查询,我想这个证书:

  VAR店=新的X509Store(StoreName.Root,StoreLocation.LocalMachine ); 
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);

变种证书= store.Certificates.Find(X509FindType.FindByIssuerName,
TEST_SELF_SIGNED,真)
.OfType&所述; x509证书>()FirstOrDefault();

这正常给我我想要的证书,这是为非空,并且有我的预期的信息。

 网​​站网站= GetSite(默认Web站点); 
变种结合= site.Bindings.Add(*:443,certificate.GetCertHash(),HTTPS);



既然没有我的变量或在示例代码中任何其他项目都是空(包括GetCertHash返回20字节数组)我很困惑,为什么我在这里得到一个空。我甚至尝试以下过载:

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

和我仍然得到同样的空REF堆栈:

 System.NullReferenceException了未处理
消息=对象未设置为一个对象的实例引用。
来源= Microsoft.Web.Administration
堆栈跟踪:
在Microsoft.Web.Administration.Configuration.SetDirty()
在Microsoft.Web.Administration.ConfigurationElement.SetDirty()
。在Microsoft.Web.Administration.ConfigurationElement.SetAttributeValue(字符串的attributeName,对象的值)
在Microsoft.Web.Administration.Binding.SetBindingProperty(字符串的attributeName,字符串值)
在Microsoft.Web。 Administration.BindingCollection.Add(字符串bindingInformation,字节[] certificateHash,字符串certificateStoreName)
在TestApp.Program.Main(字串[] args)在C:\Projects\Cube\trunk\src\ AutoUpdate\TestApp\Program.cs:行33
在System.AppDomain._nExecuteAssembly(RuntimeAssembly组装,字串[] args)
在System.AppDomain.ExecuteAssembly(字符串assemblyFile,证据assemblySecurity,字符串[ ]参数)
在Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
在System.Threading.ThreadHelper.ThreadStart_Context(对象状态)
在System.Threading.ExecutionContext.Run(ExecutionContext中的ExecutionContext ,ContextCallback回调,对象状态,布尔ignoreSyncCtx)
在System.Threading.ExecutionContext.Run(ExecutionContext中的ExecutionContext,ContextCallback回调,对象状态)在System.Threading.ThreadHelper.ThreadStart()

的InnerException:

下面是一个完整的测试应用程序,demonstartes问题,与我用来生成样品证书selfssl命令行参数一起:




selfssl.exe / T / N:CN = TEST_SELF_SIGNED / K:512 / V:9999 / Q




 类节目
{
静态无效的主要(字串[] args)
{$ b $使用b
(ServerManager的经理=新ServerManager的())
{
变种店=新的X509Store(StoreName.Root,StoreLocation.LocalMachine);
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);

变种证书= store.Certificates.Find(X509FindType.FindByIssuerNameTEST_SELF_SIGNED,真).OfType&所述; x509证书>()FirstOrDefault();

位的网站= GetSite(默认Web站点);
site.Bindings.Add(*:443,certificate.GetCertHash(),store.Name);

store.Close();

manager.CommitChanges();
}
}用

公共静态网站GetSite(字符串站点名称)
{
(VAR ServerManager的=新ServerManager的())
{
返回serverManager.Sites.Where(p值=> p.Name.ToLower()== siteName.ToLower())FirstOrDefault();
}
}
}



只是为了掩饰我的基地, IIS的安装和手动分配证书的作品就好了。


解决方案

于是我找到了答案通过反编译的Microsoft.Web.Administration DLL并通过烟囱戳。事实证明,如果你得到一个网站具有辅助功能的它不设置该网站上的内部ServerManager的属性。



这导致问题该DLL函数这Microsoft.Web.Administration ::配置

 内部空间使用setDirty()
{
如果( this._hasBeenCommitted || this._configurationManager.Owner.ReadOnly)
抛出新的InvalidOperationException异常(Resources.ObjectHasBeenCommited);
this._isDirty = TRUE;
}

这本来是空在这里要么 _configurationManager 或 _configurationManager.Owner 。我查了一下所有者是,这是一个 ServerManager的这通风报信我送行,我也许应该查询网站。一旦我做到了零裁判走了,一切正常。这是不幸的,他们没有检查空的,但也许假设是没有人会采取行动,而不服务器管理器上下文站点对象上。



不管怎样,下面是更新代码:

 类节目
{
静态无效的主要(字串[] args)
{使用(VAR ServerManager的=新ServerManager的())
{
VAR selfSignedCnName =TEST_SELF_SIGNED

;
VAR websiteName =默认Web站点;

变种站点= serverManager.Sites.Where(p值=> p.Name.ToLower()== websiteName.ToLower())FirstOrDefault();
变种店=新的X509Store(StoreName.Root,StoreLocation.LocalMachine);
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);

无功证书= store.Certificates.Find(X509FindType.FindByIssuerName,selfSignedCnName,真).OfType<&x509证书GT;()FirstOrDefault()。

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

store.Close();

serverManager.CommitChanges();
}
}

}



这也是从我最初的职位,包裹在服务器管理器中的整个代码块并不意味着什么明确的,他们没有级联。你必须采取行动,从它来自服务器管理网站上。


I'm trying to programmatically add a binding to my default website however I am consistently getting a null reference exception within the Microsoft.Web.Administration dll. Originally I wanted to assign a certificate along with the binding. I was able to query the certificate that I wanted with this:

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 properly gave me the certificate I wanted, it was non-null and had the information 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 items in the sample code are null (including GetCertHash which returns a 20 byte array) I'm confused as to why I'm getting a null here. I even tried the following overload:

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

And I still get the same null 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 full test-app that demonstartes the issue, along with the selfssl command line arguments I used to generate 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 the certificate works just fine.

解决方案

So I found the answer by decompiling the Microsoft.Web.Administration dll and poking through the stack. It turns out that if you get a Site with a helper function it doesn't set the internal ServerManager property on the site.

The function the dll that caused the issue was this in Microsoft.Web.Administration::Configuration

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

The only thing that could have been null here was either _configurationManager or _configurationManager.Owner. I checked what Owner was and it was a ServerManager which tipped me off that I should probably query the Site from within a using block of server manager. Once I did that the null ref went away and everything worked. It's unfortunate that they aren't checking for null's but maybe the assumption is nobody would ever act on a site object without the server manager context.

Anyways, here is the updated code:

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

}

It's also clear from my initial post that wrapping the entire code block in a server manager doesn't mean anything, they aren't cascaded. You have to act on the site from the server manager it came from.

这篇关于添加HTTPS绑定时的NullReferenceException在Microsoft.Web.Administration的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆