ASP.Net MVC 路由捕获所有 *.aspx 请求

Evi*_*lDr 5 c# asp.net asp.net-mvc asp.net-mvc-routing asp.net-mvc-5

一定是以前被问过的,但是在阅读了这里这里这里这里之后,我无法推断相关部分以使其工作。我正在将一个旧的 Web 表单网站改造成 MVC,并希望捕获特定的传入 HTTP 请求,以便我可以发出RedirectPermanent(以保护我们的 Google 排名并避免用户因 404 问题而离开)。

我不需要拦截所有传入请求或解析某些id值,而是需要拦截以.aspx文件扩展名结尾(或包含)的所有请求,例如

www.sample.com/default.aspx
www.sample.com/somedir/file.aspx
www.sample.com/somedir/file.aspx?foo=bar
Run Code Online (Sandbox Code Playgroud)

对 MVC 路由的请求应被忽略(只是正常处理)。

这是我到目前为止所拥有的,除了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 }
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

}

这种类型的路由可以在MVC中设置吗?

Nig*_*888 3

我展示了在 MVC 中进行 301 重定向的正确方法,因为并非所有浏览器都能正确响应 301 重定向请求,并且您需要为用户提供继续选项,而不是由 ASP 生成的默认“对象已移动”页面。网。

重定向Aspx永久路由

我们构建一个自定义RouteBase子类来检测 URL 何时以以下结尾.aspx并路由到我们SystemController以设置 301 重定向。它要求您传入 URL 映射(要匹配的 URL)来路由值(用于生成 MVC URL)。

public class RedirectAspxPermanentRoute : RouteBase
{
    private readonly IDictionary<string, object> urlMap;

    public RedirectAspxPermanentRoute(IDictionary<string, object> urlMap)
    {
        this.urlMap = urlMap ?? throw new ArgumentNullException(nameof(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;
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,第一次检查是针对.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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Status301.cshtml

遵循 MVC 的约定,并确保将其放在/Views/System/文件夹中。

因为它是 301 响应的视图,所以您可以使其与网站其余部分的主题相匹配。所以,如果用户最终来到这里,这仍然不是一个糟糕的体验。

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

  1. 该页面有一个新位置。
  2. 如果未自动重定向,他们需要单击该链接。
  3. 他们应该更新他们的书签。

@{
    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>
Run Code Online (Sandbox Code Playgroud)

用法

首先,您需要向页面添加一个部分_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>
Run Code Online (Sandbox Code Playgroud)

然后将其添加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 }
        );
    }
}
Run Code Online (Sandbox Code Playgroud)