ASP.NET MVC:自定义Route让URL更优雅

简介:

如今,互联网越来越注重简单优雅的 Url,对比下面两个:

         ~/Products/UpdateUnitPrice/5

        ~/products/update-unit-price/5

  我相信大多数朋友会更喜欢第二种方式:小写,使用负(减)号作为连字符。

  本文使用自定义 Route 来达到方式二的效果,只需增加几个类和简单修改下 global.asax 文件。

  Route 是双向的

  Route 的基本概念我就不多说了,这里重点强调一下 ASP.NET MVC 中 Route 是双向的,这可以从 RouteBase 类的定义可以看出:

public abstract class RouteBase{
2    public abstract RouteData GetRouteData(HttpContextBase httpContext);
3    public abstract VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values);
4   }

  GetRouteData 用于解析 Url,GetVirtualPath 用于生成 Url。

  在开始编写我们的 Route 类之前,我们需要一个用于处理字符串的静态类:

  StringElegantHelper 类

internal  static   class  StringElegantHelper {

    
public   static   readonly   char  minus  =   ' -';

    
public   static   string  Elegant( string  s) {
        var builder 
=   new  StringBuilder();
        var index 
=   0 ;
        foreach (var c 
in  s) {
            
if  (c  >=   ' A' && c <= 'Z') {
                 if  (index  >   0 ) builder.Append(minus);
                builder.Append(
char .ToLower(c));
            }
            
else   if  (c  ==  minus) {
                builder.Append(minus);
                builder.Append(minus);
            }
            
else
                builder.Append(c);
            index
++ ;
        }
        
return  builder.ToString();
    }

    
public   static   string  DeElegant( string  s) {
        var builder 
=   new  StringBuilder();
        var iterator 
=  s.GetEnumerator();
        
while  (iterator.MoveNext()) {
            
if  (iterator.Current ! =  minus) {
                builder.Append(iterator.Current);
                
continue ;
            }
            
if  (!iterator.MoveNext()) {
                builder.Append(minus);
                break;
            }
            
if  (iterator.Current  ==  minus)
                builder.Append(minus);
            
else
                builder.Append(iterator.Current);
        }
        
return  builder.ToString();
    }
}

        StringElegantHelper 中有两个方法 Elegant 和 DeElegant,将分别用在 GetVirtualPath 和 GetRouteData 方法中,用于生成和解析优雅的 Url。 

  这两方法也可以使用正则表达式来实现,但我认为效率不高,就采用了上面这种最朴实的方式。

  有了 StringElegantHelper 类,写出 ElegantRoute 就简单多了:

  ElegantRoute 类

     public   class  ElegantRoute : Route {
    public   static   readonly   string [] ToElegant  =    new  [] {  " controller " " action "  };    
     
public  ElegantRoute( string  url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler)
        : base(url, defaults, constraints, dataTokens, routeHandler) { }

    
public  override RouteData GetRouteData(HttpContextBase httpContext) {
        var result 
=  base.GetRouteData(httpContext);
        
if  (result  ==  null)  return  null;

        foreach (var key 
in  ToElegant)
            HandleItem(result.Values, key, StringElegantHelper.DeElegant);
        
return  result;
    }

    
public  override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) {
        var elegantValues 
=   new  RouteValueDictionary(values);
        foreach (var key 
in  ToElegant)
            HandleItem(elegantValues, key, StringElegantHelper.Elegant);
        
return  base.GetVirtualPath(requestContext, elegantValues);
    }

    
private  void HandleItem(RouteValueDictionary dict,  string  key, Func < string string >  handler) {
        
if  (!dict.ContainsKey(key))  return ;
        
//
        var value 
=  dict[key];
        
if  (!(value  is   string ))  return ;
        
//
        dict[key] 
=  handler(value  as   string );
    }
}

  注意,上面代码中只对 controller 和 action 的路由值进行了“优雅”处理,其它值并没有,为什么呢?

  大家可以考虑以下网址:

  ~/customers/details/ANTON

  全部处理的话会变成:

  ~/customers/details/a-n-t-o-n

  代码其他部分比较简单,不多说了。

  最后,还需要几个扩展方法,以方便在 global.asax 文件中使用:

  ElegantRouteExtensions 类

public   static   class  ElegantRouteExtensions {
    
public   static  ElegantRoute MapElegantRoute(this RouteCollection routes,  string  name,  string  url,  object  defaults) {
        var route 
=   new  ElegantRoute(url,
            
new  RouteValueDictionary(defaults),
            
new  RouteValueDictionary(),  // constraints
            
new  RouteValueDictionary(),  // dataTokens
            
new  MvcRouteHandler());
        routes.Add(name, route);
        
return  route;
    }
}

        我只写出一个,大家可根据需要添加。

  使用 ElegantRouter

  借助上面的扩展方法,使用就很相当简单了。

  global.asax 文件中,把 routes.MapRoute 替换为 routes.MapElegantRoute 即可:

routes.MapElegantRoute(   //  MapRoute
    
" Default "
    
" {controller}/{action}/{id} "
    
new  { controller  =   " Home " , action  =   " Index " , id = UrlParameter.Optional } 
);

  运行起来验证,点下右上角的 [ Log On ] 链接:

  

  ElegantRoute 生成和解析通过。










本文转自 wws5201985 51CTO博客,原文链接:http://blog.51cto.com/wws5201985/735607,如需转载请自行联系原作者
目录
相关文章
|
2月前
|
Windows
.NET 隐藏/自定义windows系统光标
【10月更文挑战第20天】在.NET中,可以使用`Cursor`类来控制光标。要隐藏光标,可将光标设置为`Cursors.None`。此外,还可以通过从文件或资源加载自定义光标来更改光标的样式。例如,在表单加载时设置`this.Cursor = Cursors.None`隐藏光标,或使用`Cursor.FromFile`方法加载自定义光标文件,也可以将光标文件添加到项目资源中并通过资源管理器加载。这些方法适用于整个表单或特定控件。
|
3月前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
45 7
|
4月前
|
开发框架 .NET Docker
【Azure 应用服务】App Service .NET Core项目在Program.cs中自定义添加的logger.LogInformation,部署到App Service上后日志不显示Log Stream中的问题
【Azure 应用服务】App Service .NET Core项目在Program.cs中自定义添加的logger.LogInformation,部署到App Service上后日志不显示Log Stream中的问题
|
3月前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
72 0
|
4月前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
53 0
|
4月前
|
开发框架 前端开发 安全
ASP.NET MVC 如何使用 Form Authentication?
ASP.NET MVC 如何使用 Form Authentication?
|
4月前
|
开发框架 前端开发 .NET
Asp.net Webapi 的 Post 方法不能把参数加到 URL 中?试试这样写
Asp.net Webapi 的 Post 方法不能把参数加到 URL 中?试试这样写
|
4月前
|
开发框架 .NET
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
136 0
|
7月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
208 0
|
6月前
|
安全 程序员 Shell
老程序员分享:NSIS自定义界面,下载并安装Net.Framework4.8
老程序员分享:NSIS自定义界面,下载并安装Net.Framework4.8