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用记事本打开,更改路由配置,重新再浏览器中刷新,默认加载的视图就会发生改变。 这时,就达到了自己想要的效果。