这 一定 是以前问过的,但是在这里,这里,这里和这里阅读之后,我无法推断相关的部分以使其起作用。我正在将一个旧的Web表单站点改版为MVC,并希望捕获特定的传入HTTP请求,以便发出一个RedirectPermanent(以保护Google排名并避免用户由于404而离开)。
RedirectPermanent
除了拦截 所有 传入请求或解析某个id值外,我还需要拦截所有以( .aspx) 文件扩展名结尾(或包含)的请求。
id
www.sample.com/default.aspx www.sample.com/somedir/file.aspx www.sample.com/somedir/file.aspx?foo=bar
对MVC路由的请求应被忽略(正常处理)。
到目前为止,这里就是我所能得到的,除了那条ASPXFiles路线从未被击中。
ASPXFiles
public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); // never generates a match routes.MapRoute( name: "ASPXFiles", url: "*.aspx", defaults: new { controller = "ASPXFiles", action = "Index" } ); // Used to process all other requests (works fine) routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } }
}
是否可以在MVC中设置这种类型的路由?
我正在显示在MVC中进行301重定向的 正确 方法,因为并非所有浏览器都能正确响应301重定向请求,并且您需要为用户提供一个继续选项,而不是由ASP生成的默认“对象已移动”页面。净。
我们构建了一个自定义RouteBase子类,该子类可检测URL何时以结尾,.aspx并路由至我们SystemController以设置301重定向。它要求您传入URL映射(要匹配的URL)以路由值(用于生成MVC URL)。
RouteBase
.aspx
SystemController
public class RedirectAspxPermanentRoute : RouteBase { private readonly IDictionary<string, object> urlMap; public RedirectAspxPermanentRoute(IDictionary<string, object> urlMap) { if (urlMap == null) throw new ArgumentNullException("urlMap"); this.urlMap = urlMap; } public override RouteData GetRouteData(HttpContextBase httpContext) { var path = httpContext.Request.Path; if (path.EndsWith(".aspx")) { if (!urlMap.ContainsKey(path)) return null; var routeValues = urlMap[path]; var routeData = new RouteData(this, new MvcRouteHandler()); routeData.Values["controller"] = "System"; routeData.Values["action"] = "Status301"; routeData.DataTokens["routeValues"] = routeValues; return routeData; } return null; } public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) { return null; } }
请注意,第一个检查是针对.aspx扩展名的,因此如果扩展名不匹配,则其余逻辑将被完全跳过。这将为您的方案提供最佳性能。
我们将设置SystemController为像往常一样返回视图。如果浏览器由于301而无法重定向,则用户将看到该视图。
using System; using System.Net; using System.Web; using System.Web.Mvc; public class SystemController : Controller { // // GET: /System/Status301/ public ActionResult Status301() { var routeValues = this.Request.RequestContext.RouteData.DataTokens["routeValues"]; var url = this.GetAbsoluteUrl(routeValues); Response.CacheControl = "no-cache"; Response.StatusCode = (int)HttpStatusCode.MovedPermanently; Response.RedirectLocation = url; ViewBag.DestinationUrl = url; return View(); } private string GetAbsoluteUrl(object routeValues) { var urlBuilder = new UriBuilder(Request.Url.AbsoluteUri) { Path = Url.RouteUrl(routeValues) }; var encodedAbsoluteUrl = urlBuilder.Uri.ToString(); return HttpUtility.UrlDecode(encodedAbsoluteUrl); } }
请遵循MVC的约定,并确保将其放置在/Views/System/文件夹中。
/Views/System/
因为它是301响应的视图,所以可以使其与网站其余部分的主题匹配。因此,如果用户最终来到这里,那仍然不是一个糟糕的体验。
该视图将尝试通过JavaScript 和 Meta-Refresh 自动重定向用户。这两个功能都可以在浏览器中关闭,但是用户很可能会将其放置在应有的位置。如果没有,您应该告诉用户:
@{ ViewBag.Title = "Page Moved"; } @section MetaRefresh { <meta http-equiv="refresh" content="5;@ViewBag.DestinationUrl" /> } <h2 class="error">Page Moved</h2> <p> The page has moved. Click on the following URL if you are not redirected automatically in 5 seconds. Be sure to update your bookmarks. </p> <a href="@ViewBag.DestinationUrl">@ViewBag.DestinationUrl</a>. <script> //<!-- setTimeout(function () { window.location = "@ViewBag.DestinationUrl"; }, 5000); //--> </script>
首先,您需要在页面中添加一个部分,_Layout.cshtml以便可以将元刷新添加到页面的头部。
_Layout.cshtml
<!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>
然后将添加RedirectAspxRoute到您的路由配置。
RedirectAspxRoute
public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.Add(new RedirectAspxPermanentRoute( new Dictionary<string, object>() { // Old URL on the left, new route values on the right. { @"/about-us.aspx", new { controller = "Home", action = "About" } }, { @"/contact-us.aspx", new { controller = "Home", action = "Contact" } } }) ); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } }