Asp.NET MVC 应用程序一旦完成部署到线上后,就不能够修改路由配置,只有重新编译应用程序,重新部署到程序集才能够完成,最近在学习过程中看到了一篇博客关于如何更改路由选项后,能够直接运行到已部署的应用程序中。
首先看看我在程序中,解决方案的结构选项,方便学习,,Route文件夹中放的是这次需要的类文件和接口,在控制器中我定义了一个HomeController 在里面定义了Index和Modify两个方法,也在Views文件夹中定义了相应的视图用于测试使用。
1,定义一个IRouteRegistrar.cs 接口,用于编写Routes.cs这个类
/// <summary>
/// 路由注册接口
/// </summary>
public interface IRouteRegistrar
{
void RegistrarRoutes(RouteCollection routes);
}
2.编写一个Routes.cs 类,并且实现IRouteRegistrar 接口
/// <summary>
/// Route配置文件,要更改路由在这个文件中更改
/// </summary>
public class Routes:IRouteRegistrar
{
public void RegistrarRoutes(RouteCollection routes)
{
//实现路由注册的方法,改方法编写和RoutesConfig.cs的写法一样
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
3.编写Routes 的扩展类 RouteRegistrationExtensions.cs,用于Routes集合的扩展,方便后续操作
/// <summary>
/// 扩展路由注册方法,方便后续代码编写
/// </summary>
public static class RouteRegistrationExtensions
{
/// <summary>
/// 加载路由
/// </summary>
/// <param name="routes">要扩展的路由对象</param>
/// <param name="virtualPath">文件存在的相对路径</param>
static void ReloadRoutes(this RouteCollection routes, string virtualPath)
{
//根据文件创建程序集
var assembly = BuildManager.GetCompiledAssembly(virtualPath);
//根据类名反射出类对象 注意:类名需加上类名所在的命名空间
var registrar = assembly.CreateInstance("MVC路由配置发布后可更改Demo.Routes") as IRouteRegistrar;
using (routes.GetWriteLock())
{
routes.Clear();
if (registrar !=null)
{
//注册路由
registrar.RegistrarRoutes(routes);
}
}
}/// <summary>
/// 注册路由
/// </summary>
/// <param name="routes">要扩展的路由对象</param>
/// <param name="virtualPath"></param>
public static void RegisterRoutes(this RouteCollection routes, string virtualPath)
{
if (String.IsNullOrEmpty(virtualPath))
{
throw new ArgumentException("virtualPath路径不存在");
}
routes.ReloadRoutes(virtualPath);
//调用监听事件
ConfigFileChangeNotifier.Listen(virtualPath, routes.ReloadRoutes);
}
}
4.编写一个ConfigFileChangeNotifier.cs 类,用于监听配置文件更改时,进行相应的操作
/// <summary>
/// 配置文件更改监听类
/// </summary>
public class ConfigFileChangeNotifier
{
VirtualPathProvider _vpp;
Action<string> _changeCallback;
private ConfigFileChangeNotifier(Action<string> changeCallBack)
: this(HostingEnvironment.VirtualPathProvider, changeCallBack)
{ }private ConfigFileChangeNotifier(VirtualPathProvider vpp, Action<string> changeCallBack)
{
_vpp = vpp;
_changeCallback = changeCallBack;
}/// <summary>
/// 监听事件(当文件的内容发生改变时,调用action)
/// </summary>
/// <param name="virtualPath">文件路径</param>
/// <param name="action">委托对象</param>
public static void Listen(string virtualPath, Action<string> action)
{
var notifier = new ConfigFileChangeNotifier(action);
notifier.ListenForChanges(virtualPath);
}void ListenForChanges(string virtualPath)
{
var virtualPathDependencies = new List<string>();
virtualPathDependencies.Add(virtualPath);
CacheDependency cacheDependency = _vpp.GetCacheDependency(
virtualPath, virtualPathDependencies, DateTime.UtcNow);
HttpRuntime.Cache.Insert(virtualPath /*key*/,
virtualPath /*value*/,
cacheDependency,
Cache.NoAbsoluteExpiration,
Cache.NoSlidingExpiration,
CacheItemPriority.NotRemovable,
new CacheItemRemovedCallback(OnConfigFileChanged));
}void OnConfigFileChanged(string key, object value,
CacheItemRemovedReason reason)
{
//判断是否发生改变
if (reason != CacheItemRemovedReason.DependencyChanged)
{
return;
}
_changeCallback(key);
ListenForChanges(key);
}
}5.需要的工具类已经编写完成,在最后需要在App_Start文件夹中找到RouteConfig.cs类,在RegisterRoutes方法中,注册刚刚编写的代码
public static void RegisterRoutes(RouteCollection routes)
{
RouteTable.Routes.RegisterRoutes(@"~/Route/Routes.cs");
}好了,上面的代码编写完成,运行效果如下。
运行程序 这是在原来的路由情况下运行出来的效果,不要关闭运行的应用程序,这是找到应用程序中Route文件夹下的Routes.cs用记事本打开,更改路由配置,重新再浏览器中刷新,默认加载的视图就会发生改变。 这时,就达到了自己想要的效果。