3

問題

既存の ASP.NET Web アプリケーションを取得し、手動で移行して MVC 2 を使用しようとしています (現在 RC を実行しています)。私はいくつかの手順に従いました(すぐにリストします)、動作しているように見えましたがAuthorizeAttribute、コントローラーで User が null であるため、設定できないことに気付きました。次に、アクションに移動したときに、HttpApplication の通常のライフサイクル イベント (BeginRequest など) が発生していないことに気付きました。これはおそらく User プリンシパルが null である理由に関連していると思います。Web ホストはローカルの IIS7 インスタンスです (Vista ワークステーション上)。

移行中に参照として使用する新しい MVC 2 Web アプリケーションを作成しました。それは問題なく動作し、アプリケーション イベントを発生させ、期待どおりに User プリンシパルを設定します。

自分を罰したい場合は、以下の詳細をお読みください (私の能力の及ぶ範囲で)。


移行手順

  1. アプリケーション ディレクトリのアプリケーション プールが .NET 2.0 で統合されていることを確認します。
  2. Web プロジェクトで System.Web.Abstractions (v.3.5.0.0)、System.Web.routing (v3.5.0.0)、および System.Web.Mvc (v2.0.0.0) を参照しました。ここで、System.Web.Mvc をローカル参照として追加して、統合と展開を容易にしました。
  3. csproj を変更して、MVC VS アドインの良さを有効にしました (この記事を参照してください) 。
  4. プロジェクトに Controllers および Views ディレクトリを追加し、サンプル 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. ルートを登録するように 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 統合ハンドラーを利用しています。すべてのオートファクトを完全に削除/無効にし、すべてを希望どおりに設定して、両方の方法を確認しました。どちらにしても問題には影響しません。

私はまた、私の特別な超甘い IgnoreRoute 設定の有無にかかわらず、これを試しました。無効。

また、ルートが機能しているように見えることを明確にしたいと思います。コントローラーとアクションに適切に送信されます。HttpContext.Current.User に Null プリンシパルがあり、アプリケーションのライフサイクルがまったく発生しないようです。イベント。現在のプリンシパルを取得したり、厄介な承認を行ったりする必要がなければ、何かが間違っていることに気付くことはなかったでしょう ;)

はい、通常の 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

これは最悪です:(。私の短編小説を読んでくれてありがとう。

4

2 に答える 2

1

更新済み よし、この問題は、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>

これにより問題が発生するのは、ASP.NET アプリケーションが認証されていないユーザーへのアクセスを拒否する既定の承認規則を使用しているという事実です。

  <system.web>
    <authorization>
      <deny users="?"/>
    </authorization>
  </system.web>

MVC ではこの方法は推奨されませんが、AuthorizeAttributeまたはその他のフィルターを使用します。

既存のコードをすべて MVC に移行するまで (これにはかなりの時間がかかります)、ASP.NET スタイルの承認を適切に維持して、認証されていない要求 (おそらくカスタムHttpModule?) をセキュリティで保護されたリソース (画像、javascript、css、静的 html、およびログイン/ログアウト ページを除くすべて) 用に削除し、web.config から上記を削除します。

さらに、私のアプリケーションはもともと ASP.NET であったため、Application_BeginRequest (など) は ASPX、ASMX、ASHX、AXD ページなどの重要なリソース要求のみであると想定していました。そのため、アプリケーション イベントを調整して、気にしない静的リソース (画像など) のリソース集約型処理 (DB にヒットするセキュリティ チェックなど) を停止する必要があります。

まとめ

runAllManagedModulesForAllRequests="true"統合モードの MVC には必須です。ASP.NET アプリケーションがロケーションベースの認証を頻繁に使用している場合、および/またはリクエスト ライフサイクル イベントで多くの処理を行っている場合、ASP.NET フォームと一緒に MVC を動作させるために余分な作業が必要になります。 .

于 2009-12-30T22:48:35.550 に答える
0

This may or may not help: I just finished reviewing the Nerd Dinner code and theycovered this topic specifically in the area of unit testing. Try browsering this http://www.wrox.com/WileyCDA/Section/id-321793.html and scrolling nearly to the bottom where they cover the sample unit tests. They have some fake out magic that makes their sample Account controller work to let you supply a fake user ID. Might work for you.

于 2009-12-30T21:56:36.963 に答える