代码之家  ›  专栏  ›  技术社区  ›  moribvndvs

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

  •  3
  • moribvndvs  · 技术社区  · 15 年前

    AuthorizeAttribute 因为用户在控制器上为空。然后我注意到,当我导航到一个操作时,没有引发任何HttpApplication通常的生命周期事件(如BeginRequest等)。我想这可能与用户主体为null的原因有关。web主机是本地IIS7实例(在我的Vista工作站上)。

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


    迁移步骤

    1. 确保应用程序目录的应用程序池为.NET 2.0且已集成
    2. 在我的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作为本地参考,以简化集成和部署。
    3. this article )
    4. 在项目中添加了控制器和视图目录,从示例MVC应用程序添加到/Views/web.config中。
    5. 修改了我的web.config( 注: 我在模块和处理程序中还有其他垃圾,但为了简单和安全起见,我隐藏了它们。。。但这些很可能是问题的一部分):

    这个 compilation 部分 :

    <compilation defaultLanguage="c#" debug="true">
          <assemblies>
            <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
            <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
            <add assembly="System.Web.Abstractions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
            <add assembly="System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
            <add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
            <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
            <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
            <add assembly="System.Data.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
          </assemblies>
        </compilation>
    

    这个 pages :

    <pages enableEventValidation="false"
           pageBaseType="MyAssembly.ThemedBasePage">
      <controls>
        <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      </controls>
    
      <namespaces>
        <add namespace="System.Web.Mvc"/>
        <add namespace="System.Web.Mvc.Ajax"/>
        <add namespace="System.Web.Mvc.Html"/>
        <add namespace="System.Web.Routing"/>
        <add namespace="System.Linq"/>
        <add namespace="System.Collections.Generic"/>
      </namespaces>
    </pages>
    

    这个 system.webServer/modules 第节(记住,IIS7集成) :

    <modules>
      <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" />
    
    </modules>
    

    system.webServer/handlers 部分

    <handlers>
          <remove name="WebServiceHandlerFactory-Integrated"/>
          <remove name="ScriptHandlerFactory"/>
          <remove name="ScriptHandlerFactoryAppServices"/>
          <remove name="ScriptResource"/>
          <remove name="MvcHttpHandler"/>
          <remove name="UrlRoutingHandler"/>
          <add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
          <add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
          <add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
          <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>
    
    1. 更新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
    

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

    2 回复  |  直到 15 年前
        1
  •  1
  •   moribvndvs    15 年前

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

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

    <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>
    

    而MVC并不鼓励这种做法,而是使用 AuthorizeAttribute 或者其他一些过滤器。

    此外,我的应用程序最初只是ASP.NET,它假设应用程序_BeginRequest(以及类似的)将只是重要的资源请求,比如ASPX、ASMX、ASHX和AXD页面。因此,我需要调整任何应用程序事件,以停止对我不关心的静态资源(同样,图像等)的任何资源密集型处理(命中数据库的安全检查等)。

    总结

    runAllManagedModulesForAllRequests=“true”

        2
  •  0
  •   Cyril Gandon niktrs    13 年前

    这可能有帮助,也可能没有帮助:我刚刚完成了对Nerd晚餐代码的审查,他们专门在单元测试领域讨论了这个主题。试试看这个 http://www.wrox.com/WileyCDA/Section/id-321793.html 并滚动到几乎底部,其中包含了示例单元测试。他们有一些伪造的魔法,让他们的示例帐户控制器工作,让你提供一个伪造的用户ID。可能对你有用。

    推荐文章