我们有一个已部署的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中的控制器操作。
这听起来有道理吗?安全
答案 0 :(得分:3)
尝试基于ControllerFactory的方法,HttpModule:
<强>步骤:强>
1#创建一个新的“类库”项目。添加对asp.net mvc Web应用程序项目的引用。还要添加对'System.Web','System.Web.Mvc','Microsoft.Web.Infrastructure.dll'程序集的引用。
2#创建一个从控制器(TargetController)继承的新Controller类,它有bug:
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上设置上述控制器工厂。 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文件夹中。
希望这会有所帮助......
答案 1 :(得分:0)
如果我错了,有人会纠正我,但我很确定,除非你的项目是为动态加载程序集而设计的,否则你将无法在没有某种部署的情况下修改运行时。
话虽这么说,您可以利用ISS重定向或添加到Web.config文件中的HttpModule将请求发送到违规控制器到您选择的新位置。