加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-mvc – 在运行时替换控制器操作

发布时间:2020-12-16 03:42:37 所属栏目:asp.Net 来源:网络整理
导读:我们有一个已部署的ASP.NET MVC 3应用程序,并在其中一个控制器操作中发现了一个错误.出于政治原因,我们不允许替换任何现有的代码,如果没有一个需要数周头痛的大流程.即我们无法重建MVC应用程序. 我们被允许部署一个新的程序集,其中包含一个只有一个固定动作
我们有一个已部署的ASP.NET MVC 3应用程序,并在其中一个控制器操作中发现了一个错误.出于政治原因,我们不允许替换任何现有的代码,如果没有一个需要数周头痛的大流程.即我们无法重建MVC应用程序.

我们被允许部署一个新的程序集,其中包含一个只有一个固定动作的新控制器.

有没有办法添加或编辑MVC应用程序的路由来映射新的控制器操作?

我正在考虑将我的MVC应用程序子类化在修复程序DLL中并更新global.asax以引用子类应用程序.

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

它将路由到修补程序DLL中的控制器操作.

这听起来有道理吗?安全?

解决方法

尝试基于ControllerFactory,HttpModule的这种方法:

脚步:

1#创建一个新的“类库”项目.添加对asp.net mvc Web应用程序项目的引用.还要添加对’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,它将在应用程序init上设置上述controller-factory. 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));
        }
    }
}

编译项目并将.dll复制到Web应用程序的bin文件夹中.

希望这有助于……

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读