我一般如何在 MapRoute 方法中实现 URL 重写? [英] How do I generically implement URL-rewriting in a MapRoute method?

查看:27
本文介绍了我一般如何在 MapRoute 方法中实现 URL 重写?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


我正在尝试将 URL 从 C# 的 Pascal-case 重写为 SEO 友好格式.
例如,我希望 /User/Home/MyJumbledPageName 看起来像这样:

/user/home/my-jumbled-page-name // lower-case, and words separated by dashes


这是我转换 URL 中每个令牌"的方法:


Here is my method for converting each "token" in the URL:

public static string GetSEOFriendlyToken(string token)
{
    StringBuilder str = new StringBuilder();

    for (int i = 0, len = token.Length; i < len; i++)
    {
        if (i == 0)
        {
            // setting the first capital char to lower-case:
            str.Append(Char.ToLower(token[i]));
        }
        else if (Char.IsUpper(token[i]))
        {
            // setting any other capital char to lower-case, preceded by a dash:
            str.Append("-" + Char.ToLower(token[i]));
        }
        else
        {
            str.Append(token[i]);
        }
    }
    return str.ToString();
}


...在我的 RouteConfig.cs 文件中,我已经映射了这些路由:


...and in my RouteConfig.cs file in the root, I have mapped these routes:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    // without this the first URL is blank:
    routes.MapRoute(
        name: "Default_Home",
        url: "index", // hard-coded?? it works...
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );

    routes.MapRoute(
        name: "Home",
        // the method calls here do not seem to have any effect:
        url: GetSEOFriendlyToken("{action}") + "/" + GetSEOFriendlyToken("{id}"),
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}


使用此代码,/AboutTheAuthor 之类的 URL 不会转换为我想要的,即 /about-the-author.

似乎我的方法调用被忽略了,这里发生了什么?实现这一点的传统方法是什么?


With this code, a URL such as /AboutTheAuthor is not converted to what I want, which would be /about-the-author.

It seems that my method call is ignored, what's happening here? And what's the conventional way to implement this?

推荐答案

你必须定义你自己的RouteBase类或子类Route

You have to define your own RouteBase class or subclass Route

public class SeoFriendlyRoute : Route
{
    private readonly string[] _valuesToSeo;

    public SeoFriendlyRoute(string url, RouteValueDictionary defaults, IEnumerable<string> valuesToSeo, RouteValueDictionary constraints = null, RouteValueDictionary dataTokens = null, IRouteHandler routeHandler = null)
        : base(url, defaults, constraints ?? new RouteValueDictionary(), dataTokens ?? new RouteValueDictionary(), routeHandler ?? new MvcRouteHandler())
    {
        if (valuesToSeo == null) { throw new ArgumentNullException("valuesToSeo"); }
        _valuesToSeo = valuesToSeo.ToArray();
    }
    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        var routeData = base.GetRouteData(httpContext);
        if (routeData != null)
        {
            foreach (var key in _valuesToSeo)
            {
                if (routeData.Values.ContainsKey(key))
                {
                    routeData.Values[key] = GetActualValue((string)routeData.Values[key]);
                }
            }
        }
        return routeData;
    }
    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        var seoFriendyValues = new RouteValueDictionary(values);
        foreach (var key in _valuesToSeo)
        {
            if (seoFriendyValues.ContainsKey(key))
            {
                seoFriendyValues[key] = GetSeoFriendlyValue((string)seoFriendyValues[key]);
            }
        }
        return base.GetVirtualPath(requestContext, seoFriendyValues);
    }

    private string GetSeoFriendlyValue(string actualValue)
    {
        //your method
        StringBuilder str = new StringBuilder();
        for (int i = 0, len = actualValue.Length; i < len; i++)
        {
            if (i == 0)
            {
                str.Append(Char.ToLower(actualValue[i]));
            }
            else if (Char.IsUpper(actualValue[i]))
            {
                str.Append("-" + Char.ToLower(actualValue[i]));
            }
            else
            {
                str.Append(actualValue[i]);
            }
        }
        return str.ToString();
    }

    private static string GetActualValue(string seoFriendlyValue)
    {
        //action name is not case sensitive
        //one limitation is the dash can be anywhere but the action will still be resolved
        // /my-jumbled-page-name is same as /myjumbled-pagename
        return seoFriendlyValue.Replace("-", string.Empty); 
    }
}

用法

routes.Add("Default", new SeoFriendlyRoute(
    url: "{controller}/{action}/{id}",
    valuesToSeo: new string[] { "action", "controller" },
    defaults: new RouteValueDictionary(new { controller = "Home", action = "Index", id = UrlParameter.Optional }))
);

这篇关于我一般如何在 MapRoute 方法中实现 URL 重写?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆