我网站上的URL(ASP.NET MVC 4.6)如下所示: 的 /测试/ SOG
但是,我的网站是丹麦语,所以我想将丹麦语中的特殊字符“ø”重定向到所有网址中的“o”。
在上述情况下,对 / test /søg的请求应重定向到 / test / sog 。
我的网站相当大,所以我想在网站范围内执行此操作(而不必为每个网址创建单独的重定向控制器方法)。
我该怎么做?
答案 0 :(得分: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);
}
}
这有点复杂。虽然你可以进行302重定向(所有浏览器都遵守),但301更适合搜索引擎优化,这就是我在这里展示的方法。不幸的是,某些浏览器不会自动遵循301重定向。因此,需要一些额外的步骤来确保如果浏览器没有,则通过客户端302重定向重定向用户,如果失败,则显示可以跳转到下一页的链接。< / p>
我们首先使用路由来清理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;
}
}
接下来,我们有我们的控制器,其目的是实际提供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();
}
}
该视图将尝试通过Meta-Refresh通过JavaScript 和自动重定向用户。这两个都可以在浏览器中关闭,但用户可能会把它放到应该去的地方。如果没有,您应该告诉用户:
@{
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注册路由。重要的是,在注册任何其他路由之前(包括对MapMvcAttributeRoutes
或AreaRegistration.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
。