最近我正在实施一个HttpMoudle。并坚持说System.NullReferenceException: Object reference not set to an instance of an object.
这是我的代码。
public class MyHttpModuler : IHttpModule
{
private static IAuthProvider authProvider=null;
#region IHttpModule members
/// <summary>
/// Disposes of the resources (other than memory) used by the module that implements <see cref="T:System.Web.IHttpModule"/>.
/// </summary>
public void Dispose()
{
authProvider.Dispose();
authProvider = null;
}
public void Init(HttpApplication application)
{
authProvider = new BasicAuthProvider("achievo");
application.BeginRequest += new EventHandler(Application_BeginRequest);
}
private void Application_BeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpRequest request = app.Request;
HttpResponse response = app.Response;
TryAuthenticate(app);
}
#endregion
#region private method
/// <summary>
/// Tries to authenticate the user
/// </summary>
/// <param name="context">The context.</param>
/// <returns></returns>
private bool TryAuthenticate(HttpApplication context)
{
string authHeader = context.Request.Headers["Authorization"];
if (!string.IsNullOrEmpty(authHeader))
{
if (authHeader.StartsWith("basic ", StringComparison.InvariantCultureIgnoreCase))
{
string userNameAndPassword = Encoding.Default.GetString(
Convert.FromBase64String(authHeader.Substring(6)));
string[] parts = userNameAndPassword.Split(':');
if (authProvider.IsValidUser(parts[0], parts[1]))
{
//the authProvider object sometimes is null .Why?
return true;
}
}
}
return false;
}
#endregion
}
public class BasicAuthProvider : IAuthProvider
{
#region IAuthProvider Members
public string DomainName { get; set; }
public BasicAuthProvider(string sDmName)
{
DomainName = sDmName;
}
public bool IsValidUser(string userName, string password)
{
string sFullName = "LDAP://" + DomainName + ".com";
bool bLogin = ADHelper.IsAuthenticated(sFullName, DomainName + @"\" + userName, password);
return bLogin;
}
public bool IsRequestAllowed(HttpRequest request,string sName)
{
return sName == "joe.wang";
}
public void Dispose()
{
}
#endregion
}
特别是当多个用户进入网站时。发生NullReferenceException的例外。当我调试时,我发现有时可能不会调用Init
方法。也许这就是异常发生的原因。有人可以帮我查一下吗?谢谢
答案 0 :(得分:2)
您已将主要对象authProvider
设置为静态,因此您需要在进行同步时将其删除并删除。
private static IAuthProvider authProvider=null;
所以你需要把它写成:
public class MyHttpModuler : IHttpModule
{
//can not be shared with others request.
//private IAuthProvider authProvider = null;
//We do not need it now.
//private static readonly object _lockObj = new object();
#region IHttpModule members
/// <summary>
/// Disposes of the resources (other than memory) used by the module that implements <see cref="T:System.Web.IHttpModule"/>.
/// </summary>
public void Dispose()
{
//authProvider.Dispose();
//authProvider = null;
}
public void Init(HttpApplication application)
{
application.BeginRequest += new EventHandler(Application_BeginRequest);
}
private void Application_BeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpRequest request = app.Request;
HttpResponse response = app.Response;
TryAuthenticate(app);
}
#endregion
#region private method
/// <summary>
/// Tries to authenticate the user
/// </summary>
/// <param name="context">The context.</param>
/// <returns></returns>
private bool TryAuthenticate(HttpApplication context)
{
IAuthProvider authProvider = new BasicAuthProvider("achievo");
string authHeader = context.Request.Headers["Authorization"];
if (!string.IsNullOrEmpty(authHeader))
{
if (authHeader.StartsWith("basic ", StringComparison.InvariantCultureIgnoreCase))
{
string userNameAndPassword = Encoding.Default.GetString(
Convert.FromBase64String(authHeader.Substring(6)));
string[] parts = userNameAndPassword.Split(':');
if (authProvider.IsValidUser(parts[0], parts[1]))
{
//the authProvider object sometimes is null .Why?
authProvider=null;
return true;
}
}
}
authProvider=null;
return false;
}
#endregion
}
答案 1 :(得分:2)
问题是(正如 Aristos 指出的那样)你已经authProvider
静态。
这意味着当多个用户同时生成请求时,将会有多个HttpModule
同时运行的实例。但他们都会分享一个 authProvider
。
因此用户A 可能会启动请求,导致您的模块的新实例运行它的Init
方法。然后处理该请求的线程被置于保持状态,并且来自用户B 的另一个请求启动,导致另一个模块的新内容运行它的Init
方法。这将覆盖在用户A 的请求中放置的authProvider中的实例。然后 线程被置于保持状态,用户A 的前一个线程将恢复并完成处理请求,从而处理authProvider
(由设置)用户B 的请求)并将其设置为null。之后,用户B的请求再次恢复,并发现authProvider
现在为空。
根据您提供的代码,似乎最简单的解决方案就是从行中删除static
关键字:
private static IAuthProvider authProvider=null;
然后HttpModule
的每个实例都拥有它自己的authProvider
副本,一个请求不会影响另一个请求的状态。