将旧版ASP.NET迁移到MVC 2(RC):未触发HttpApplication事件,用户主体为null

将旧版ASP.NET迁移到MVC 2(RC):未触发HttpApplication事件,用户主体为null,asp.net,asp.net-mvc-2,migration,side-by-side,Asp.net,Asp.net Mvc 2,Migration,Side By Side,问题 我正在尝试使用现有的ASP.NET web应用程序并手动将其迁移到MVC2(我目前正在运行RC)。我遵循了几个步骤(稍后我将列出),并且似乎它工作正常,但随后我注意到我无法设置authorized属性,因为用户在控制器上为空。然后我注意到,当我导航到一个操作时,没有引发任何HttpApplication通常的生命周期事件(如BeginRequest等)。我想这可能与用户主体为null的原因有关。web主机是本地IIS7实例(在我的Vista工作站上) 我创建了一个全新的MVC2Web应用程

问题

我正在尝试使用现有的ASP.NET web应用程序并手动将其迁移到MVC2(我目前正在运行RC)。我遵循了几个步骤(稍后我将列出),并且似乎它工作正常,但随后我注意到我无法设置
authorized属性
,因为用户在控制器上为空。然后我注意到,当我导航到一个操作时,没有引发任何HttpApplication通常的生命周期事件(如BeginRequest等)。我想这可能与用户主体为null的原因有关。web主机是本地IIS7实例(在我的Vista工作站上)

我创建了一个全新的MVC2Web应用程序,作为迁移时的参考。它运行得很好,引发应用程序事件并填充用户主体,正如我所期望的那样

如果你想惩罚自己,请继续阅读下面的全部细节(尽我所能)


迁移步骤

  • 确保应用程序目录的应用程序池为.NET 2.0且已集成
  • 在我的Web项目中引用了System.Web.Abstracts(v.3.5.0.0)、System.Web.routing(v3.5.0.0)和System.Web.Mvc(v2.0.0.0)。现在,我添加了System.Web.Mvc作为本地参考,以简化集成和部署
  • 修改csproj以启用MVC与插件(请参阅)
  • 在项目中添加了控制器和视图目录,从示例MVC应用程序添加到/Views/web.config中
  • 修改了我的web.config(注意:我在模块和处理程序中还有其他垃圾,但为了简单和安全起见,我隐藏了它们……但这些很可能是问题的一部分):
  • 编译
    部分:

    system.webServer/modules
    部分(记住,IIS7集成):

  • 更新my global.asax以注册路由,并忽略会干扰我的旧内容的内容:

    private static void RegisterRoutes(RouteCollection routes)
    {
      // place any routes here you need to ignore, whether they
      // be legacy or legitimate resources.
      routes.IgnoreRoute(""); // i currently have functionality at "/", and this route frees up the root to be used by my Default.aspx
      routes.IgnoreRoute("{webForms}.aspx/{*pathInfo}");
      routes.IgnoreRoute("{webServices}.asmx/{*pathInfo}");
      routes.IgnoreRoute("ajaxpro/{*pathInfo}");
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
      routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new {controller = "Home", action = "Index", id = ""} // Parameter defaults
      );
    }   
    
    
    
    protected void Application_Start()
    {
       // legacy crap here
    
       AreaRegistration.RegisterAllAreas();    
       RegisterRoutes(RouteTable.Routes);
    }
    
  • 其他信息

    我还使用最新版本的Autofac(v1.4.5.676)并利用其Web集成处理程序。我已经检查了这两种方式,所有autofact的东西都被完全删除/禁用,所有东西都按照我想要的方式设置;这两种方式对问题都没有影响

    我也尝试过使用和不使用我专门的super sweet IgnoreRoute设置。没有效果

    另外,我想说明的是,这些路由看起来确实有效,我被正确地发送到我的控制器和操作,我只是在HttpContext.Current.User中有一个空主体,它似乎完全不会引发任何应用程序生命周期事件。如果我不需要,你知道,得到当前的委托人或做任何令人讨厌的授权,我永远不会知道有什么不对劲;)

    是的,常规ASPX页面工作正常,应用程序生命周期事件正常引发

    下面是我制作的一个失败的简单测试控制器的示例:

        [Authorize]
        public class FartsController : Controller
        {
            //
            // GET: /Farts/
            public ActionResult Index()
            {
                return View();
            }
    
        }
    
    产生以下异常:

    [NullReferenceException: Object reference not set to an instance of an object.]
       System.Web.Mvc.AuthorizeAttribute.AuthorizeCore(HttpContextBase httpContext) +48
       System.Web.Mvc.AuthorizeAttribute.OnAuthorization(AuthorizationContext filterContext) +35
       System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor) +103
       System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +316
       System.Web.Mvc.Controller.ExecuteCore() +104
       System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +36
       System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +7
       System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__4() +34
       System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +21
       System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +12
       System.Web.Mvc.Async.WrappedAsyncResult`1.End() +53
       System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +43
       System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +7
       System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8678910
       System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
    
    [NullReferenceException:对象引用未设置为对象的实例。]
    System.Web.Mvc.AuthorizeAttribute.AuthorizeCore(HttpContextBase httpContext)+48
    System.Web.Mvc.AuthorizationAttribute.OnAuthorization(AuthorizationContext filterContext)+35
    System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext ControllerContext,IList`1 filters,ActionDescriptor ActionDescriptor)+103
    System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext ControllerContext,String actionName)+316
    System.Web.Mvc.Controller.ExecuteCore()+104
    System.Web.Mvc.ControllerBase.Execute(RequestContext-RequestContext)+36
    System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext RequestContext)+7
    System.Web.Mvc.c__显示类8.b__4()+34
    System.Web.Mvc.Async.c__显示类1.b__0()+21
    System.Web.Mvc.Async.c_uuudisplayClass8`1.b_uuu7(IAsyncResult)+12
    System.Web.Mvc.Async.WrappedAsyncResult`1.End()+53
    System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)+43
    System.Web.Mvc.MvcHandler.System.Web.IHTTPassynchandler.EndProcessRequest(IAsyncResult结果)+7
    System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()+8678910
    System.Web.HttpApplication.ExecuteStep(IExecutionStep步骤,布尔值&同步完成)+155
    

    这太糟糕了:(.谢谢你阅读我的短篇小说。

    这可能有用,也可能没用:我刚刚完成了对书呆子晚餐代码的审查,他们专门在单元测试领域研究了这个主题。试着浏览一下这个主题,并滚动到几乎底部的单元测试示例。他们有一些伪造的魔法,使他们的示例帐户能够controller可以让你提供一个假用户ID。可能对你有用。

    更新了 好的,我认为这个问题是我对MVC真正工作原理的理解上的失败(直到我回过头来,以一种全新的思维比较ASP.NET和MVC web配置之间的差异时,才清楚)

    出现问题的原因是,MVC应用程序需要以下设置才能在集成模式下正常运行(重要部分是
    runAllManagedModulesForAllRequests=“true”
    ):

    
    
    这对我造成问题的原因是,我的ASP.NET应用程序使用默认授权规则拒绝未经身份验证的用户的访问:

      <system.web>
        <authorization>
          <deny users="?"/>
        </authorization>
      </system.web>
    
    
    
    而MVC不鼓励这种做法,而是使用
    AuthorizeAttribute
    或其他一些过滤器

    在我将所有现有代码转移到MVC之前(这将需要相当长的时间),我必须想出一个聪明的解决方案来保持ASP.NET风格的授权,然后推出未经授权的代码
    private static void RegisterRoutes(RouteCollection routes)
    {
      // place any routes here you need to ignore, whether they
      // be legacy or legitimate resources.
      routes.IgnoreRoute(""); // i currently have functionality at "/", and this route frees up the root to be used by my Default.aspx
      routes.IgnoreRoute("{webForms}.aspx/{*pathInfo}");
      routes.IgnoreRoute("{webServices}.asmx/{*pathInfo}");
      routes.IgnoreRoute("ajaxpro/{*pathInfo}");
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
      routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new {controller = "Home", action = "Index", id = ""} // Parameter defaults
      );
    }   
    
    
    
    protected void Application_Start()
    {
       // legacy crap here
    
       AreaRegistration.RegisterAllAreas();    
       RegisterRoutes(RouteTable.Routes);
    }
    
        [Authorize]
        public class FartsController : Controller
        {
            //
            // GET: /Farts/
            public ActionResult Index()
            {
                return View();
            }
    
        }
    
    [NullReferenceException: Object reference not set to an instance of an object.]
       System.Web.Mvc.AuthorizeAttribute.AuthorizeCore(HttpContextBase httpContext) +48
       System.Web.Mvc.AuthorizeAttribute.OnAuthorization(AuthorizationContext filterContext) +35
       System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor) +103
       System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +316
       System.Web.Mvc.Controller.ExecuteCore() +104
       System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +36
       System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +7
       System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__4() +34
       System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +21
       System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +12
       System.Web.Mvc.Async.WrappedAsyncResult`1.End() +53
       System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +43
       System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +7
       System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8678910
       System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
    
    <system.webServer>
        <validation validateIntegratedModeConfiguration="false"/>
        <modules runAllManagedModulesForAllRequests="true">
            <remove name="ScriptModule"/>
            <remove name="UrlRoutingModule"/>
            <add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
            <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    
           <!-- omitted for clarify -->
        </modules>
        <handlers>
            <!-- omitted for clarity -->
            <add name="MvcHttpHandler" preCondition="integratedMode" verb="*" path="*.mvc" type="System.Web.Mvc.MvcHttpHandler, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
            <add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd" type="System.Web.HttpForbiddenHandler, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
        </handlers>
    </system.webServer>
    
      <system.web>
        <authorization>
          <deny users="?"/>
        </authorization>
      </system.web>