6

デプロイされた ASP.NET MVC 3 アプリケーションがあり、コントローラー アクションの 1 つにバグが発見されました。政治的な理由から、数週間の頭痛の種となる大きなプロセスなしに、既存のコードを置き換えることは許可されていません。つまり、MVC アプリケーションを再構築することはできません。

固定アクションが 1 つだけの新しいコントローラーを含む新しいアセンブリをデプロイできます。

MVC アプリケーションのルートを追加または編集して、新しいコントローラー アクションをマップする方法はありますか?


ホットフィックス DLL で MVC アプリケーションをサブクラス化し、サブクラス化されたアプリケーションを参照するように global.asax を更新することを検討しています。

public class HotfixApplication : RealApplication
{
    public override void Init()
    {
        base.Init();
        var badRoute =  RouteTable.Routes.Where(...);
        var badRoute.FixIt();
    }
}

そして、修正プログラム DLL のコントローラー アクションにルーティングされます。

これはもっともらしく聞こえますか?安全?

4

2 に答える 2

3

ControllerFactory、HttpModuleに基づいてこのアプローチを試してください。

手順:

1#新しい「クラスライブラリ」プロジェクトを作成します。asp.netmvcWebアプリケーションプロジェクトへの参照を追加します。また、「System.Web」、「System.Web.Mvc」、「Microsoft.Web.Infrastructure.dll」アセンブリへの参照を追加します。

2#バグのあるコントローラー(TargetController)から継承された新しいControllerクラスを作成します。

public class FixedContorller : TargetController
{

    [FixedActionSelector]
    [ActionName("Index")]
    public ActionResult FixedIndex()
    {
        ViewBag.Title = "I'm Fixed...";
        return View();
    }
}

[FixedActionSelectorAttribute]はActionSelector属性であり、アクション名を解決するために使用されます。

    public class FixedActionSelector : ActionMethodSelectorAttribute
    {
    public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
    {
        return true;
    }
}

3#カスタムControllerFactoryを定義します。これにより、ターゲットコントローラーの代わりに固定コントローラーが作成されます。

public class MyControllerFactory : DefaultControllerFactory
{
    private static string targetControllerName = "Target";
    private static string targetActionName = "Index";

    protected override Type GetControllerType(System.Web.Routing.RequestContext requestContext, string controllerName)
    {
        var action = requestContext.RouteData.Values["action"].ToString();

        if (targetControllerName.Equals(controllerName, StringComparison.InvariantCultureIgnoreCase) &&
            targetActionName.Equals(action, StringComparison.InvariantCultureIgnoreCase))
        {
            return typeof(FixedContorller);
        }

        return base.GetControllerType(requestContext, controllerName);
    }
}

4#ここで、HttpModuleを定義します。これにより、アプリケーションの初期化時に上記のコントローラーファクトリが設定されます。httpModuleはプログラムで登録され、web.configに登録する必要はありません。

using System;
using System.Web;
using System.Web.Mvc;

[assembly: PreApplicationStartMethod(typeof(YourApp.Patch.FixerModule), "Register")]
namespace YourApp.Patch
{
    public class FixerModule : IHttpModule
    {
        private static bool isStarted = false;
        private static object locker = new object();

        public void Dispose()
        {
        }

        public void Init(HttpApplication context)
        {
            if (!isStarted)
            {
                lock (locker)
                {
                    if (!isStarted)
                    {
                        ControllerBuilder.Current.SetControllerFactory(typeof(MyControllerFactory));
                        isStarted = true;
                    }
                }
            }
        }

        public static void Register()
        {
            Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(FixerModule));
        }
    }
}

プロジェクトをコンパイルし、Webアプリケーションのbinフォルダーに.dllをコピーします。

これがお役に立てば幸いです...

于 2012-05-07T12:54:04.933 に答える
0

私が間違っている場合は誰かが私を修正しますが、プロジェクトがアセンブリを動的にロードするように設計されていない限り、何らかの展開なしでランタイムを変更することはできないと確信しています.

そうは言っても、ISS リダイレクトまたは Web.config ファイルに追加された HttpModule を利用して、問題のあるコントローラーへの要求を選択した新しい場所に向けることができます。

于 2012-05-04T17:45:05.593 に答える