MVC 5 中 PostAuthenticateRequest 管道中的空引用问题

6
我正在尝试按照Brock Allen的示例,使用声明添加自定义角色到Windows角色中。(http://brockallen.com/2013/01/17/adding-custom-roles-to-windows-roles-in-asp-net-using-claims/)。但是,我只是从他们的示例中复制粘贴代码,就出现了以下错误。我正在使用仅添加了Microsoft.IdentityModel的全新MVC 5项目进行尝试。我漏掉了什么导致了这个错误?

对象引用未设置为对象的实例。说明: 当前Web请求执行期间发生了未处理的异常。请查看堆栈跟踪以获取有关错误的更多信息以及错误在代码中的起源和位置。

异常详细信息:System.NullReferenceException: 对象引用未设置为对象的实例。

源错误:

当前Web请求的执行期间生成了一个未处理的异常。可以使用下面的异常堆栈跟踪标识异常的来源和位置。

堆栈跟踪:

[NullReferenceException: 对象引用未设置为对象的实例。]
System.Web.PipelineModuleStepContainer.GetStepArray(RequestNotification notification, Boolean isPostEvent) +22
System.Web.PipelineStepManager.ResumeSteps(Exception error) +1324
System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb) +95
System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +186

这是我global.asax.cs文件中的代码。
public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        PostAuthenticateRequest += WebApiApplication_PostAuthenticateRequest;
    }

    void WebApiApplication_PostAuthenticateRequest(object sender, EventArgs e)
    {
        if (Request.IsAuthenticated)
        {

            var id = ClaimsPrincipal.Current.Identities.First();
            id.AddClaim(new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/gender", "potato"));

        }
    }
}
2个回答

10
经过更深入的挖掘,似乎是“magic”或者自动事件包装使得这个工作。我不需要声明一个事件处理程序。
namespace WebApplication1
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }

        void Application_PostAuthenticateRequest()
        {
            if (Request.IsAuthenticated)
            {  
                var id = ClaimsPrincipal.Current.Identities.First();   
            }
        }
    }
}

3
你之前的代码(event_handler += method)无法正常工作的原因是,在Application_Start方法中,尚未加载完所有的事件处理程序模块。 在事件处理程序模块加载完成后,ASP.NET会使用“_EventHandlerMethod”的约定来正确连接你的方法。 如果你想给这些方法起其他名字,可以在Init()方法中这样做。 - MisterHux
好的,我现在明白了。无论我的类名是什么,我都必须将第一个片段命名为“Application”。在我的情况下,我实现了“Application_PreRequestHandlerExecute”。 - Ashi
@MisterHux,你知道有没有文档说明如果你显式注册事件处理程序,就会出现尚未加载所有模块的情况吗? - Rui

1

回答晚了!我遇到了同样的问题。我通过在构造函数中挂钩事件来解决它,而不是在Application_Start中。
作者:Luke Puplett


我更喜欢Michael的解决方案。 - Ashi
运行得很好!谢谢! - hal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接