zoukankan      html  css  js  c++  java
  • 深入Web框架-MVC自定义Route让Url更优雅

    如今,互联网越来越注重简单优雅的Url,Web框架可以为MVC自定义路由设置。 对比 /Products/UpdateUnitPrice/5和/products/update-unit-price/5,我相信大多数朋友会更喜欢第二种方式:小写,使用负(减)号作为连字符。那么我们该怎么来配置才能实现这种方式呢?

    目录

    Route 是双向的
    自定义Route类
    对应的扩展方法
    使用自定义Route类

    1,Route 是双向的

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

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

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

    2,自定义Route类


    在开始编写自定义的 Route 类之前,先定义一个将用在自定义的Route中的用于处理字符串的静态类:StringElegantHelper 类。StringElegantHelper 中有两个方法 Elegant 和 DeElegant,将分别用在 GetVirtualPath 和 GetRouteData 方法中,用于生成和解析优雅的 Url。

    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,也可以使用正则表达式来实现,但效率不如上面这种最朴实的方式高。有了 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
    代码其他部分比较简单,不多说了。

    3,对应的扩展方法

    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;
        }
    }

    4,使用自定义Route类

    借助上面的扩展方法,使用就很相当简单了。global.asax 文件中,把 routes.MapRoute 替换为 routes.MapElegantRoute 即可:

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

    文章转载自:深入Web框架-MVC自定义Route让Url更优雅

    web开发框架 -- 云微平台

    本文标题:深入Web框架-MVC自定义Route让Url更优雅

    本文地址:http://www.hocode.com/

  • 相关阅读:
    char 转string
    博客,记忆的图谱。
    history
    openstack Icehouse发布
    数据库常用命令
    nagios
    screen
    openstack 流量控制
    sublime 3
    磁盘类型
  • 原文地址:https://www.cnblogs.com/frfwef/p/12530435.html
Copyright © 2011-2022 走看看