繁体   English   中英

如何对 ASP.NET Core 3.1 C# 中的自动“规范链接”重定向器进行重复数据删除?

[英]How to deduplicate an automatic “Canonical Link” redirector in ASP.NET Core 3.1 C#?

对于我的 ASP.NET Core 3.1 C# 应用程序中的每个 web 页面,我想为 SEO 目的自动生成规范链接。

目前(POC 阶段),我在每个 controller 动作 function 中都有以下片段:

Uri actualUrl = new Uri($"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}{HttpContext.Request.Path}{HttpContext.Request.QueryString}");
RouteValueDictionary values = RouteData.Values;
values.Remove("controller");
values.Remove("action");
foreach (var q in HttpContext.Request.Query)
    values.Add(q.Key, q.Value);
// Further route/query parameter "fixes" here.
Uri canonicalUrl = new Uri(Url.ActionLink(values: values));
if (!canonicalUrl.Equals(actualUrl))
    return RedirectPermanentPreserveMethod(canonicalUrl.ToString());

此代码段首先使用当前实际的 URL 构建一个Uri 然后它可能会“修复”一些重要的路由/查询参数(如下所示)。 最后,它将实际 uri 与所需 uri 进行比较,并在实际 uri 与所需 uri 不同时重定向到所需 uri(区分大小写)。

RouteData.Values["subpage"] = "Digital-Contents";

此过程使 web 应用程序能够为以下示例 URL 生成正确的规范 url( http://example.com/MyController/MyAction/Digital-Contents )。

然而,POC 是大量的代码重复,因此本身并不理想。

我的第一个想法是使用中间件。 但是,对于中间件,操作 controller 无法“修复”路由/查询参数,这些参数超出了常规路由结构的范围(如大多数 ASP.NET 示例中显示的“id”路由参数)。 例如, ActionLink能够为 controller 和操作生成正确的区分大小写的 url slug,但不能处理(“修复”)其他路由/查询参数。

我的第二个想法是使用通用的 class,但我失去了上下文。

最好的解决方案是单个(无效)function 调用,它可以放置在实际操作重处理之前(在处理数据和生成输出之前的操作 controller 内部)。

如何对这个“自动规范重定向器”代码进行重复数据删除?

这可能不是最好的解决方案,我只是根据您提供的代码修改了案例:

 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class CanonicalUrlAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var httpContext = filterContext.HttpContext;

            Uri actualUrl = new Uri($"{httpContext.Request.Scheme}://{httpContext.Request.Host}{httpContext.Request.Path}{httpContext.Request.QueryString}");
            RouteValueDictionary values = filterContext.RouteData.Values;
            values.Remove("controller");
            values.Remove("action");
            foreach (var q in httpContext.Request.Query)
                values.Add(q.Key, q.Value);

            // Further route/query parameter "fixes" here.
            Uri canonicalUrl = new Uri(new UrlHelper(filterContext).ActionLink(values));
            if (!canonicalUrl.Equals(actualUrl))
                filterContext.Result = new LocalRedirectResult(canonicalUrl.ToString());
        }
    }

用法

 [CanonicalUrl]
 public class HomeController : Controller {

}

如果您使用视图模型中的名称来生成诸如example.com/some-category/some-product之类的 URL,那么我将使用此链接中的帮助程序根据 model 名称(在我的情况下为在创建 model 时保存到 db)然后使用自定义路由:

  endpoints.MapControllerRoute(
                    name: "category",
                    pattern: "{Category}/{Product}",
                    defaults: new { controller = "Product", action = "Index" });

这种模式省略了动作和 controller 来自 route 的名称(我更喜欢),并为您提供类似example.com/some-category/some-product的内容,在您的操作中,您只需将模型的 slug 与提供的路线段进行比较用户(使用路由约束)如下:

 public async Task<IActionResult> Index([FromRoute,Required] Category,[FromRoute,Required] Product)

并且您对不匹配进行路由重定向,如下所示:

  return RedirectToRoutePermanent("category", new { Product = Product.Slug, Category = Product.Category.Slug });

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM