博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASP.NET MVC:自定义Route让URL更优雅
阅读量:6649 次
发布时间:2019-06-25

本文共 3885 字,大约阅读时间需要 12 分钟。

如今,互联网越来越注重简单优雅的 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,如需转载请自行联系原作者
你可能感兴趣的文章
Java网络编程从入门到精通(3):为什么不能直接通过IP访问网站
查看>>
三层结构之联接查询的实现
查看>>
flash与中文输入法冲突,div遮挡flash问题
查看>>
配置高可用的Hadoop平台
查看>>
ActiveMQ 即时通讯服务 浅析
查看>>
关于使用C#画函数图形的问题
查看>>
MEF 打造的插件系统
查看>>
人机交互,来和我猜拳吧!
查看>>
Android -- Activity的销毁和重建
查看>>
朴素UNIX它-Linux CFS注视
查看>>
为GridView添加两种自定义分页样式
查看>>
有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少...
查看>>
LintCode: Binary Tree Postorder Traversal
查看>>
Hadoop工作流不足(六)
查看>>
算法 - 乞讨n中位数(C++)
查看>>
GMM高斯混合模型学习笔记(EM算法求解)
查看>>
你所未知的3种 Node.js 代码优化方式
查看>>
JSP简单的练习-用户登记表
查看>>
Objective-C:KVO机制
查看>>
如何解决数据一致性、任务调度、流水号生成等问题?
查看>>