原文:构建可读性更高的 ASP.NET Core 路由

一、前言

  不知你在平时上网时有没有注意到,绝大多数网站的 URL 地址都是小写的英文字母,而我们使用 .NET/.NET Core MVC 开发的项目,因为在 C# 中类和方法名采用的是 Pascal 命名规范,根据 .NET 框架默认的路由规则,项目的 URL 地址会呈现出大小写混合的情况。对于强迫症来说,这种情况绝对不能忍,当然,由于整个项目的 URL 地址大小写混合显示,也无法更清晰的向用户、浏览器表达出当前页面的功能。那么,这篇文章就来介绍下,如何调整我们的 ASP.NET Core 项目的路由规则,从而使我们项目的 URL 地址可读性更高。

  PS:在构建 URL 的过程中,采用大写的地址还是采用小写的地址,每个人都会有自己的想法和这样做的理由,这篇文章不讨论两种方案的优劣,只是提供一种构建小写 URL 地址以及让我们的 URL 可读性更高的解决方案,请友善观看,切勿互怼。

  代码仓储:https://github.com/Lanesra712/grapefruit-common

二、Step by Step

  在构建项目的路由时,不管是采用大写的 URL 路由,还是采用小写的 URL 路由,我们首先需要确保的是,我们需要将整个项目的 URL 格式进行统一。不能说一个项目一部分的 URL 地址用大写的,而另一部分采用的是小写的 URL 地址。同时,同一个页面的大写的路径以及小写的路径,虽然最终服务器可能都会将两个地址指向同一个页面,但是对于搜索引擎的收录来说,这无疑是两个页面。

  试想以下,当别人告诉了我们一个有趣的网站,我们从浏览器的地址栏中输入网址进行访问。当我们输入 URL 地址时,不管是中文输入法还是英文输入法,输出的英文字母都是小写的,此时,如果输入的网址中存在大写字母,嗯,我们还需要使用 CapsLock 键进行大小写切换。

  另外,我们知道,对于 Windows 服务器来说,因为对于路径的大小写不敏感,如果我们弄错了地址的大小写,我们还是可以进行正常的访问的,可是,如果将应用部署到 Linux 服务器上的话。。。。

  至于更好的可读性,这个概念可能会显得有些主观。简单来说,就是当我们面对一个网址时,我们可以很清楚的通过这个网址知道这个网页的主要内容。例如,当我们看见www.youdomain.com/editor/post/new 这个网址时,虽然可能并没有打开这个网页,但我们还是可以大致猜到这个页面可能是新增文章的。可是,如果你收到的网址是 www.youdomain.com/9rg7f2/i?HXI-D+iaj34 这样的,没人能知道这个页面到底是干啥的。

  因此,为了便捷输入,首先我们需要将我们的 URL 地址转换成小写的形式,在 ASP.NET Core 中,微软提供了 RoutingServiceCollectionExtensions.AddRouting 这个扩展方法可以让我们将 URL 地址转换成小写。
  打开项目的 Startup.cs 文件,找到 ConfigureServices 方法,在方法体内添加下面的代码。

services.AddRouting(options =>
{
options.LowercaseUrls = true;
});

  示例项目的顶部链接代码如下所示,运行项目可以看到,通过设置小写路由后,程序根据 Controller 和 Action 自动生成的 URL 地址全部变成了小写。仔细观察可以发现,这里会出现一个问题。在某些特殊的情况下,Area/Controller/Action 可能是由多个英文字母拼接而成的一个混合英文单词,如果把这个混合的单词全部进行小写而不进行拆分的话,整个项目的 URL 可读性更低了。

<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Sample</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Post" asp-action="DraftSetting">Draft Setting</a>
</li>
</ul>
</div>
</div>
</nav>
</header>

  在 Startup 类中的 Configure 方法里,我们定义了针对包含 Area 和不包含 Area 的两个路由模板,整个项目的 URL 都是根据这两个模板进行生成的。那么这里我们是不是可以通过对单个 Controller 或是 Action 指定特殊的 URL 格式呢?

app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}"); routes.MapRoute(
name: "areas",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
});

  答案当然是可以的。在 ASP.NET Core 中,我们可以通过在 Controller 或是 Action 方法上添加 RouteAttribute 的方式将用户自定义路由信息添加到项目的路由表中。例如这里我在 DraftSetting 这个 Action 上使用特性路由的方式手动指定当前 Action 生成特殊的 URL 格式。

public class PostController : Controller
{
[Route("post/draft-setting")]
public IActionResult DraftSetting()
{
return View();
}
}

  虽然这样可以解决我们的问题,可以一旦项目有新增页面时,就要手动的指定特性路由地址,这样似乎有些麻烦。那么,如何自动的让程序帮我们实现这一功能呢?

  在 ASP.NET Core 2.2 版本中,微软为我们提供了参数转换器这一概念,我们可以通过实现 IOutboundParameterTransformer 这个接口,从而将 URL 中路由的值或者是 URL 中路由参数的值按照我们的需求进行转换。就像下面的代码中,我通过实现这个接口,从而实现将多个英文单词生成的混合单词以 hyphen(-) 的形式进行分隔。

public class SlugifyParameterTransformer : IOutboundParameterTransformer
{
public string TransformOutbound(object value)
{
return value == null
? null
: Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower();
}
}

  这里我使用 hyphen(-) 作为 URL 中各个单词间的连字符,是因为对于搜索引擎来说,它会将 - 视为单词间分隔符,采用这种风格的 URL 更有利于搜索引擎收录。

  当接口功能实现之后,我们就需要对我们的默认全局路由进行修改。首先,我们需要在路由模板上指定需要替换的路由参数,这里我们指定 Area、Controller、Action 是需要进行路由参数转换的变量。

app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller:slugify=Home}/{action:slugify=Index}/{id?}"); routes.MapRoute(
name: "areas",
template: "{area:exists:slugify}/{controller:slugify=Home}/{action:slugify=Index}/{id?}"
);
});

  当定义好参数转换器以及需要转换的 URL 路由参数后,我们就可以在 AddRouting 方法中通过 ConstraintMap 进行配置需要转换的参数路由值。至此就可以完成我们进行路由参数转换的结果。

services.AddRouting(options => {
options.ConstraintMap["slugify"] = typeof(SlugifyParameterTransformer);
options.LowercaseUrls = true;
});

三、总结

   在本章中,我们主要是调整了 ASP.NET Core 项目中的默认路由,从而使项目的 URL 地址具有更好的可读性。通过使用小写路由和 hyphen(-) 路由,只是构建可读性更高的 URL 地址的第一步,在构建页面时,我们更应该考虑的是如何使用少数的单词就可以让用户清楚当前页面的功能,更简短,更易读的 URL 不仅对于用户,对于搜索引擎也是更友好的。

构建可读性更高的 ASP.NET Core 路由的更多相关文章

  1. ASP.NET Core路由中间件[3]: 终结点(Endpoint)

    到目前为止,ASP.NET Core提供了两种不同的路由解决方案.传统的路由系统以IRouter对象为核心,我们姑且将其称为IRouter路由.本章介绍的是最早发布于ASP.NET Core 2.2中 ...

  2. ASP.NET Core路由中间件[2]: 路由模式

    一个Web应用本质上体现为一组终结点的集合.终结点则体现为一个暴露在网络中可供外界采用HTTP协议调用的服务,路由的作用就是建立一个请求URL模式与对应终结点之间的映射关系.借助这个映射关系,客户端可 ...

  3. ASP.NET Core 路由 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core 路由 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 路由 前两章节中,我们提到 ASP.NET Core 支持 MVC 开发 ...

  4. ASP .Net Core路由(Route) - 纸壳CMS的关键

    关于纸壳CMS 纸壳CMS是一个开源免费的,可视化设计,在线编辑的内容管理系统.基于ASP .Net Core开发,插件式设计: GitHub:https://github.com/SeriaWei/ ...

  5. 理解ASP.NET Core - 路由(Routing)

    注:本文隶属于<理解ASP.NET Core>系列文章,请查看置顶博客或点击此处查看全文目录 Routing Routing(路由):更准确的应该叫做Endpoint Routing,负责 ...

  6. ASP.NET Core路由中间件[1]: 终结点与URL的映射

    目录 一.路由注册 二.设置内联约束 三.默认路由参数 四.特殊的路由参数 借助路由系统提供的请求URL模式与对应终结点(Endpoint)之间的映射关系,我们可以将具有相同URL模式的请求分发给应用 ...

  7. 或许是你应该了解的一些 ASP.NET Core Web API 使用小技巧

    一.前言 在目前的软件开发的潮流中,不管是前后端分离还是服务化改造,后端更多的是通过构建 API 接口服务从而为 web.app.desktop 等各种客户端提供业务支持,如何构建一个符合规范.容易理 ...

  8. ASP.NET Core 1.1 静态文件、路由、自定义中间件、身份验证简介

    概述 之前写过一篇关于<ASP.NET Core 1.0 静态文件.路由.自定义中间件.身份验证简介>的文章,主要介绍了ASP.NET Core中StaticFile.Middleware ...

  9. ASP.NET Core 1.0 静态文件、路由、自定义中间件、身份验证简介

    概述 ASP.NET Core 1.0是ASP.NET的一个重要的重新设计. 例如,在ASP.NET Core中,使用Middleware编写请求管道. ASP.NET Core中间件对HttpCon ...

随机推荐

  1. 前端 MV*模式

    https://github.com/livoras/blog/issues/11 MVC 调用关系如下: Controller(model) ,controller中执行业务逻辑,操作model V ...

  2. perl 对ENV环境变量的使用

    1.hash 方式访问. %ENV  key为环境变量名,value为环境变量值 2.调用ENV模块 . use Env qw(PATH); print "path is $ENV{path ...

  3. TB平台搭建之二

    主要想记录关于debug问题: 一般我会1.定位问题所在位置比如使能信号错误.地址读写错误.数据流pipeline错误.... 2.首先看问题的源头(对应信号)是否还正确,比如出现XX要查看她的第一级 ...

  4. 看外设(uart/spis/i2c/i2s)模块设计

    1.先看外设接口协议. 2.看具体设计文档. 3.仿真case.

  5. day22面向对象

    面向对象编程: 1.什么是面向对象 面向过程(编程思想): 过程,解决问题的步骤,流程即第一步做什么,第二步做什么 将复杂问题,拆成若干小问题,按照步骤一一解决,将复杂问题流程化(为其制定固定的实现流 ...

  6. MIP经典问题:旅行商问题 (traveling salesman problem)

    *本文主要记录和分享学习到的知识,算不上原创. *参考文献见链接. 旅行商问题.背包问题都是0-1规划问题中最为经典的问题. 通常来说,当我们学习并熟悉一种求解混合整数问题的技巧时,可以用这种技巧来求 ...

  7. 常见slave 延迟原因以及解决方法

    一  序言在运维线上M-M 架构的MySQL数据库时,接收的比较多关于主备延时的报警: 点击(此处)折叠或打开 check_ins_slave_lag (err_cnt:1)critical-slav ...

  8. cf891a Pride

    倘若存在 1,那么答案是 \(n-cnt_1\). 否则,设最短的公约数为 1 的区间长度为 \(minlen\),答案是 \(minlen-1+n-1\). #include <iostrea ...

  9. 【LeetCode】Intersection of Two Linked Lists(相交链表)

    这道题是LeetCode里的第160道题. 题目讲的: 编写一个程序,找到两个单链表相交的起始节点. 如下面的两个链表: 在节点 c1 开始相交. 示例 1: 输入:intersectVal = 8, ...

  10. [uiautomator篇] uiautoviewer 定位不到元素

    定位工具: Uiautomatorviewer 在我们的APP中,只有这一个页面,元素无法加载出来,其它的都没有什么问题.   提示的错误:Error while obtaining UI hiera ...