奇怪的 ASP.net“未将对象引用设置到对象的实例”
我们对导致此异常的原因进行了一些概述。
我在我的开发机器(windows xp、asp.net 4)上创建了一个网站,并将其定位到 .Net 3.5。然后,我在舞台计算机(Windows 7、ASP.net 2、IIS 7.5)上部署了 100% 工作的网站。
在解决了许多安全问题之后,我在这个令人困惑的异常处停下来,虽然我清楚地理解它的含义,但我无法理解为什么这个异常会来自堆栈跟踪中提到的行。
...这就是你们进来的地方! :)
所以堆栈跟踪:
[NullReferenceException: Object reference not set to an instance of an object.]
DVL.Ruby.Admin.Config.ConfigManager..ctor(String path) in C:\Documents and Settings\Andy\Desktop\SS_DVL\Displays\Ruby.root\Ruby\Ruby.Admin\Config\ConfigManager.cs:41
DVL.Ruby.Admin.SettingGroups.Page_Load(Object sender, EventArgs e) in C:\Documents and Settings\Andy\Desktop\SS_DVL\Displays\Ruby.root\Ruby\Ruby.Admin\SettingStates.aspx.cs:33
System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35
System.Web.UI.Control.OnLoad(EventArgs e) +99
System.Web.UI.Control.LoadRecursive() +50
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +627
ConfigManager.cs
namespace DVL.Ruby.Admin.Config
{
public class ConfigManager
{
private XElement m_appSettings;
private XElement m_appMappings;
private XElement m_appConnectionStrings;
private List<Setting> m_settings;
private List<ConnectionString> m_connectionStrings;
private string m_path;
private ConfigManager() { }
private ConfigManager(string path)
{
if (path==null)
{
throw new NullReferenceException("The web.config path provided cannot be null.");
}
if (File.Exists(path)==false)
{
throw new ArgumentException("The web.config file does not exist.");
}
// Load the file
XDocument configDocument = XDocument.Load(path);
m_path = path; // <-- Line 41
// Do some stuff...
}
/// <summary>
/// Creates and returns a new instance of the ConfigManager
/// </summary>
/// <param name="path">The path of the web.config file to load.</param>
/// <returns>A new instance of the ConfigManager</returns>
public static ConfigManager Load(string path)
{
return new ConfigManager(path);
}
SettingStates.aspx.cs
namespace DVL.Ruby.Admin
{
public partial class SettingGroups : System.Web.UI.Page
{
ConfigManager m_configManager;
List<State> m_states;
protected void Page_Load(object sender, EventArgs e)
{
// Check we have the location of the web.config file we'll be editing
string webConfigPath = WebConfigurationManager.AppSettings[Constants.ApplicationKey_WebConfigPath];
if (webConfigPath == null)
{
return;
}
try
{
// Initialise the manager
m_configManager = ConfigManager.Load(webConfigPath); // <-- Line 33
}
catch (ConfigurationException ex)
{
ErrorMessage.Visible = true;
ErrorMessage.Text = ex.Message;
SaveStateButton.Enabled = false;
LoadStateButton.Enabled = false;
return;
}
因此,正如您所看到的,空引用出现在这一行:
m_path = path;
这很奇怪,因为我检查路径是否为空(并不是说它会产生影响) )并且 m_path 已经为空,但这并不重要,因为我正在分配!
在查看反射器中的库时,我注意到的一件事是编译版本更改为:
this.m_path = path;
我猜这给出了可能失败的逻辑点(即“this”引用)。但为什么这会是空的呢?这与我创建对象实例的静态 Load(string) 方法有关吗?如果是这样,为什么它可以在我的开发电脑上运行,而不能在部署计算机上运行?
我很高兴只为该对象提供一个普通的构造函数,但我只是遵循 Microsoft 开发其 API 的方式(ala XDocument)。我尝试再次使用反射器来查看他们是否以不同的方式实现加载方法,但该方法是空的(可能是混淆的?)。
无论如何,让我们总结一下,主要问题是:
- 为什么它在第 41 行失败?
- 为什么我的开发机器上没有出现这种情况?
So a bit of an overview around the lead up to this exception.
I've created a website on my dev machine (windows xp, asp.net 4) and targeted it to .Net 3.5. I then deployed the 100% working website on the stage machine (Windows 7, ASP.net 2, IIS 7.5).
After sorting out numerous security problems, I've come to a stop at this bewildering exception, which although I clearly understand what it means, I can't fathom why this exception would be coming from the line mentioned in the stack trace.
...Which is where you lot come in! :)
So the stack trace:
[NullReferenceException: Object reference not set to an instance of an object.]
DVL.Ruby.Admin.Config.ConfigManager..ctor(String path) in C:\Documents and Settings\Andy\Desktop\SS_DVL\Displays\Ruby.root\Ruby\Ruby.Admin\Config\ConfigManager.cs:41
DVL.Ruby.Admin.SettingGroups.Page_Load(Object sender, EventArgs e) in C:\Documents and Settings\Andy\Desktop\SS_DVL\Displays\Ruby.root\Ruby\Ruby.Admin\SettingStates.aspx.cs:33
System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35
System.Web.UI.Control.OnLoad(EventArgs e) +99
System.Web.UI.Control.LoadRecursive() +50
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +627
ConfigManager.cs
namespace DVL.Ruby.Admin.Config
{
public class ConfigManager
{
private XElement m_appSettings;
private XElement m_appMappings;
private XElement m_appConnectionStrings;
private List<Setting> m_settings;
private List<ConnectionString> m_connectionStrings;
private string m_path;
private ConfigManager() { }
private ConfigManager(string path)
{
if (path==null)
{
throw new NullReferenceException("The web.config path provided cannot be null.");
}
if (File.Exists(path)==false)
{
throw new ArgumentException("The web.config file does not exist.");
}
// Load the file
XDocument configDocument = XDocument.Load(path);
m_path = path; // <-- Line 41
// Do some stuff...
}
/// <summary>
/// Creates and returns a new instance of the ConfigManager
/// </summary>
/// <param name="path">The path of the web.config file to load.</param>
/// <returns>A new instance of the ConfigManager</returns>
public static ConfigManager Load(string path)
{
return new ConfigManager(path);
}
SettingStates.aspx.cs
namespace DVL.Ruby.Admin
{
public partial class SettingGroups : System.Web.UI.Page
{
ConfigManager m_configManager;
List<State> m_states;
protected void Page_Load(object sender, EventArgs e)
{
// Check we have the location of the web.config file we'll be editing
string webConfigPath = WebConfigurationManager.AppSettings[Constants.ApplicationKey_WebConfigPath];
if (webConfigPath == null)
{
return;
}
try
{
// Initialise the manager
m_configManager = ConfigManager.Load(webConfigPath); // <-- Line 33
}
catch (ConfigurationException ex)
{
ErrorMessage.Visible = true;
ErrorMessage.Text = ex.Message;
SaveStateButton.Enabled = false;
LoadStateButton.Enabled = false;
return;
}
So as you can see, the null reference is occurring at this line:
m_path = path;
Which is odd, because i check if path is null (not that it'd make a difference) and m_path is already null but that doesn't matter as I'm assigning!
One thing I noticed when looking at the library in reflector is that the compiled version changes to:
this.m_path = path;
Which I guess gives a logical point at which is may be failing (i.e. the 'this' reference). But why would this be null? Is it something to do with my static Load(string) method creating the object instance? If so, why does it work on my dev pc and not the deployment machine?
I'm quite happy to just have a normal constructor for the object, but I was just following how Microsoft have developed their APIs (ala XDocument). I tried to use reflector again to see if they're implementing their load method differently but the method was empty (maybe obfuscated?).
Anyway, lets wrap up, so the main questions:
- Why is it failing on line 41?
- Why does is not occur on my dev machine?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧,
基本上,可能是菜鸟的错误。该网站是在 Release 中编译的,我猜这意味着它不包含所有调试信息,因为它是错误的行号(第 41 行应该是进一步指向构造函数的指针,其中有一个更容易理解的问题与配置发生)。
一切都很好,但这让我有点烦恼。 ASP.net 的编译版本与控制台或其他应用程序不同吗?我确定我已经获得了之前版本中包含正确行的堆栈跟踪?
另外,为什么堆栈跟踪中的行号是正确的?即第 33 行是正确的。这纯粹是巧合吗?
塔!
安迪.
Ok,
So basically, possibly a noob mistake. The website was compiled in Release, which I'm guessing means it doesn't contain all the debug information, as it was the line number that was wrong (line 41 should have been pointer further into the constructor where a more understandable problem to do with config occured).
All's well and good, but it bugs me a little. Are ASP.net compiles in release different to console or other applications? I'm sure I've got a stack trace with correct lines from a Release before?
Also, why are the line numbers correct further down the stack trace? i.e. Line 33 was correct. Was this just pure coincidence?
Ta!
Andy.