用于捕获所有 *.aspx 请求的 ASP.Net MVC 路由 [英] ASP.Net MVC route to catch all *.aspx requests

查看:21
本文介绍了用于捕获所有 *.aspx 请求的 ASP.Net MVC 路由的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

www.sample.com/default.aspxwww.sample.com/somedir/file.aspxwww.sample.com/somedir/file.aspx?foo=bar

应忽略对 MVC 路由的请求(正常处理).

到目前为止,这是我所拥有的,除了 ASPXFiles 路线从未被击中.

公共类RouteConfig{public static void RegisterRoutes(RouteCollection 路由){route.IgnoreRoute("{resource}.axd/{*pathInfo}");//从不产生匹配路线.MapRoute(name: "ASPXFiles",网址:*.aspx",默认值:新{控制器=ASPXFiles",动作=索引"});//用于处理所有其他请求(工作正常)路线.MapRoute(名称:默认",url: "{controller}/{action}/{id}",默认值:新 { 控制器 =主页",动作 =索引",id = UrlParameter.Optional });}}

}

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

解决方案

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

重定向AspxPermanentRoute

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

公共类 RedirectAspxPermanentRoute : RouteBase{private readonly IDictionary网址地图;public RedirectAspxPermanentRoute(IDictionary urlMap){this.urlMap = urlMap ??throw new ArgumentNullException(nameof(urlMap));}公共覆盖 RouteData GetRouteData(HttpContextBase httpContext){var path = httpContext.Request.Path;if (path.EndsWith(.aspx")){if (!urlMap.ContainsKey(path))返回空;var routeValues = urlMap[路径];var routeData = new RouteData(this, new MvcRouteHandler());routeData.Values[控制器"] =系统";routeData.Values["action"] = "Status301";routeData.DataTokens[routeValues"] = routeValues;返回路由数据;}返回空;}公共覆盖 VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values){返回空;}}

请注意,第一次检查是针对 .aspx 扩展名的,因此如果扩展名不匹配,将完全跳过其余的逻辑.这将为您的场景提供最佳性能.

系统控制器

我们设置 SystemController 以像往常一样返回视图.如果浏览器因为 301 没有重定向,用户将看到视图.

使用系统;使用 System.Net;使用 System.Web;使用 System.Web.Mvc;公共类 SystemController :控制器{////获取:/System/Status301/公共 ActionResult Status301(){var routeValues = this.Request.RequestContext.RouteData.DataTokens[routeValues"];var url = this.GetAbsoluteUrl(routeValues);Response.CacheControl = 无缓存";Response.StatusCode = (int)HttpStatusCode.MovedPermanently;Response.RedirectLocation = url;ViewBag.DestinationUrl = url;返回视图();}私有字符串 GetAbsoluteUrl(object routeValues){var urlBuilder = new UriBuilder(Request.Url.AbsoluteUri){路径 = Url.RouteUrl(routeValues)};var encodingAbsoluteUrl = urlBuilder.Uri.ToString();返回 HttpUtility.UrlDecode(encodedAbsoluteUrl);}}

Status301.cshtml

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

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

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

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


@{ViewBag.Title =页面已移动";}@section MetaRefresh {<meta http-equiv="刷新";content="5;@ViewBag.DestinationUrl";/>}<h2 class="error">Page Moved</h2><p>页面已移动.如果您是,请点击以下网址不会在 5 秒内自动重定向.请务必更新您的书签.</p><a href=@ViewBag.DestinationUrl">@ViewBag.DestinationUrl</a>.<脚本>//<!--设置超时(函数(){window.location = "@ViewBag.DestinationUrl";}, 5000);//-->

用法

首先,您需要向 _Layout.cshtml 添加一个部分,以便可以将元刷新添加到页面的头部部分.

<html lang="en"><头><meta charset="utf-8";/><title>@ViewBag.Title - 我的 ASP.NET MVC 应用程序</title><link href="~/favicon.ico";rel=快捷方式图标"类型=图像/x-图标";/><!-- 添加这个以便视图可以更新这个部分-->@RenderSection("MetaRefresh", required: false)<元名称=视口"内容=宽度=设备宽度"/>@Styles.Render("~/Content/css")@Scripts.Render("~/bundles/modernizr")<!-- 省略了布局代码-->

然后将 RedirectAspxRoute 添加到您的路由配置中.

公共类RouteConfig{public static void RegisterRoutes(RouteCollection 路由){routes.IgnoreRoute("{resource}.axd/{*pathInfo}");路线.添加(新重定向AspxPermanentRoute(新字典<字符串,对象>(){//左侧的旧 URL,右侧的新路由值.{ @"/about-us.aspx", new { controller = "Home", action = "About";} },{ @"/contact-us.aspx", new { controller = "Home", action = "Contact";} }}));路线.MapRoute(名称:默认",网址:{controller}/{action}/{id}",默认值:新 { 控制器 = 首页",动作 = 索引",id = UrlParameter.Optional });}}

This must have been asked before, but after reading here, here, here and here I can't extrapolate the relevant parts to make it work. I am revamping an old web forms site into MVC, and want to catch particular incoming HTTP requests so that I can issue a RedirectPermanent (to protect our Google rankings and avoid users leaving due to 404's).

Rather than intercept all incoming requests, or parse for some id value, I need to intercept all requests that end in (or contain) the .aspx file extension, e.g.

www.sample.com/default.aspx
www.sample.com/somedir/file.aspx
www.sample.com/somedir/file.aspx?foo=bar

Requests to the MVC routes should be ignored (just processed as normal).

Here's what I have so far, except the ASPXFiles route is never being hit.

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 }
        );
    }
}

}

Is this type of route possible to set up in MVC?

解决方案

I am showing the right way to make a 301 redirect in MVC, since not all browsers respond to 301 redirect requests properly, and you need to give the user an option to continue rather than the default "Object Moved" page that is generated by ASP.NET.

RedirectAspxPermanentRoute

We build a custom RouteBase subclass that detects when a URL ends with .aspx and routes to our SystemController to setup the 301 redirect. It requires you to pass in a map of URL (the URL to match) to route values (which are used to generate the 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;
    }
}

Note that the first check is for the .aspx extension, so the rest of the logic will be entirely skipped if the extension doesn't match. This will provide the best performance for your scenario.

SystemController

We setup the SystemController to return a view as we normally would. If the browser doesn't redirect because of the 301, the user will see the view.

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);
    }
}

Status301.cshtml

Follow the conventions of MVC and be sure to place this in the /Views/System/ folder.

Because it is a view for your 301 response, you can make it match the theme of the rest of your site. So, if the user ends up here, it is still not a bad experience.

The view will attempt to redirect the user automatically via JavaScript and via Meta-Refresh. Both of these can be turned off in the browser, but chances are the user will make it where they are supposed to go. If not, you should tell the user:

  1. The page has a new location.
  2. They need to click the link if not automatically redirected.
  3. They should update their bookmark.


@{
    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>

Usage

First you need to add a section to your _Layout.cshtml so the Meta-refresh can be added to the head section of your page.

<!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>

Then add the RedirectAspxRoute to your routing configuration.

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 }
        );
    }
}

这篇关于用于捕获所有 *.aspx 请求的 ASP.Net MVC 路由的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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