将特殊字符重定向到其“转义的URL表单”

时间:2016-05-22 17:42:21

标签: asp.net asp.net-mvc asp.net-mvc-4 url asp.net-mvc-routing

我网站上的URL(ASP.NET MVC 4.6)如下所示: 的 /测试/ SOG

但是,我的网站是丹麦语,所以我想将丹麦语中的特殊字符“ø”重定向到所有网址中的“o”。

在上述情况下,对 / test /søg的请求应重定向到 / test / sog

我的网站相当大,所以我想在网站范围内执行此操作(而不必为每个网址创建单独的重定向控制器方法)。

我该怎么做?

1 个答案:

答案 0 :(得分:3)

这是一个有趣的问题,我想知道答案。事实证明这是相当简单的。为实现这一目标,您需要做两件事。

  1. 将字符串转换为罗马字符。
  2. 执行301重定向到新网址。
  3. 将字符串转换为罗马字符

    我找到了答案here,但将其修改为扩展方法,使其更易于使用。

    using System;
    using System.Globalization;
    using System.Text;
    
    public static class StringExtensions
    {
        public static string RemoveDiacritics(this string text)
        {
            var normalizedString = text.Normalize(NormalizationForm.FormD);
            var stringBuilder = new StringBuilder();
    
            foreach (var c in normalizedString)
            {
                var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
                if (unicodeCategory != UnicodeCategory.NonSpacingMark)
                {
                    stringBuilder.Append(c);
                }
            }
    
            return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
        }
    }
    

    执行301重定向到新URL

    这有点复杂。虽然你可以进行302重定向(所有浏览器都遵守),但301更适合搜索引擎优化,这就是我在这里展示的方法。不幸的是,某些浏览器不会自动遵循301重定向。因此,需要一些额外的步骤来确保如果浏览器没有,则通过客户端302重定向重定向用户,如果失败,则显示可以跳转到下一页的链接。< / p>

    RedirectToRomanizedUrlPermanent.cs

    我们首先使用路由来清理URL。如果干净的URL与原始URL不同(即替换了一个或多个字符),我们会将请求发送到名为SystemController的控制器以处理301重定向。

    public class RedirectToRomanizedUrlPermanent : RouteBase
    {
        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
            var path = httpContext.Request.Path;
            var romanPath = path.RemoveDiacritics();
            if (!path.Equals(romanPath, StringComparison.OrdinalIgnoreCase))
            {
                var routeData = new RouteData(this, new MvcRouteHandler());
    
                routeData.Values["controller"] = "System";
                routeData.Values["action"] = "Status301";
                routeData.DataTokens["redirectLocation"] = romanPath;
    
                return routeData;
            }
    
            return null;
        }
    
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            return null;
        }
    }
    

    SystemController.cs

    接下来,我们有我们的控制器,其目的是实际提供301状态。如果浏览器不尊重301,则向用户呈现视图。

    using System.Net;
    using System.Web.Mvc;
    
    public class SystemController : Controller
    {
        public ActionResult Status301()
        {
            var redirectLocation = this.Request.RequestContext.RouteData.DataTokens["redirectLocation"] as string;
    
            // IMPORTANT: Don't cache the 301 redirect because browsers tend to keep it around
            // meaning you cannot update the browser to a different URL from the server side.
            Response.CacheControl = "no-cache";
            Response.StatusCode = (int)HttpStatusCode.MovedPermanently;
            Response.RedirectLocation = redirectLocation;
    
            ViewBag.RedirectLocation = redirectLocation;
            return View();
        }
    }
    

    /Views/System/Status301.cshtml

    该视图将尝试通过Meta-Refresh通过JavaScript 自动重定向用户。这两个都可以在浏览器中关闭,但用户可能会把它放到应该去的地方。如果没有,您应该告诉用户:

    1. 该页面有一个新位置。
    2. 如果没有自动重定向,他们需要点击链接。
    3. 他们应将自己的书签更新为新网址。
    4. @{
          ViewBag.Title = "Page Moved";
      }
      @section MetaRefresh {
          <meta http-equiv="refresh" content="5;@ViewBag.RedirectLocation" />
      }
      
      <h2 class="error">Page Moved</h2>
      <p>
          The page has a new location. Click on the following link if you are 
          not redirected automatically in 5 seconds. Please update your bookmark(s) to the new location.
      </p>
      <a href="@ViewBag.RedirectLocation">@ViewBag.RedirectLocation</a>.
      
      <script>
          //<!--
          setTimeout(function () {
              window.location = "@ViewBag.RedirectLocation";
          }, 5000);
          //-->
      </script>
      

      用法

      在应用程序的_Layout.cshtml页面中添加一个部分,以便元刷新可以放在页面的<head>部分。

      <!DOCTYPE html>
      <html lang="en">
          <head>
              <meta charset="utf-8" />
              <title>@ViewBag.Title - My ASP.NET MVC Application</title>
              <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
              <!-- Add this so the view can update this section -->
              @RenderSection("MetaRefresh", required: false)
              <meta name="viewport" content="width=device-width" />
              @Styles.Render("~/Content/css")
              @Scripts.Render("~/bundles/modernizr")
          </head>
      
          <!-- layout code omitted -->
      
      </html>
      

      使用MVC注册路由。重要的是,在注册任何其他路由之前(包括对MapMvcAttributeRoutesAreaRegistration.RegisterAllAreas的任何呼叫)都会发生这种情况。

      public class RouteConfig
      {
          public static void RegisterRoutes(RouteCollection routes)
          {
              routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
      
              // IMPORTANT: Register this before any other routes.
              routes.Add(new RedirectToRomanizedUrlPermanent());
      
              routes.MapRoute(
                  name: "Default",
                  url: "{controller}/{action}/{id}",
                  defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
              );
          }
      }
      

      现在,当您输入/Ĥőmȩ/Ċőńţãçť等网址时,系统会自动将您重定向到/Home/Contact