ASP.NET Core 路由生成外部链接

ASP.NET Core 应用程序链接都是根据应用程序中定义的路由来创建的,即使路由更新了,链接地址也会跟着更新,从而避免手动更新所有的链接

ASP.NET Core 路由使用下面的帮助标签生成action方法的链接

1 asp-controller

2 asp-action.

1 根据默认路由生成链接

应用程序是如何根据定义的路由创建链接的呢?让我们创建一个ASP.NET Core MVC应用程序,命名为AspNetCore.RouteLinks 

ASP.NET Core 路由生成外部链接

应用程序创建完成之后,你能看到Program类中有一个默认的路由,路由代码如下:
app.MapControllerRoute(    name: "default",    pattern: "{controller=Home}/{action=Index}/{id?}");
接下来我们进入HomeController的Index视图,添加下面代码:
<a asp-controller="Home" asp-action="Check">Outgoing URL</a>
运行应用程序,在浏览器中查看生成的HTML格式,我们会发现生成了如下代码:
<a href="/Home/Check">Outgoing URL</a>

如下图所示:                   

ASP.NET Core 路由生成外部链接
我们在超链接标签上使用了asp-controller和asp-action帮助标签(asp-controller="Home" asp-action="Check" ) 生成链接,这个帮助标签告诉dotnet为该标签创建一个href属性,并且该属性值连接到HomeController的Check方法
dotnet会使用应用程序给定的路由为check方法创建一个完整的url链接,应用程序已经包含默认路由,因此根据默认路由能够生成url,如果我们有多个路由,dotnet将依次匹配每个路由并且使用匹配成功的路由创建url,涉及到路由匹配的问题,我们后面会涉及到
下面代码指向Customer控制器的Check方法,下面代码将工作
<a asp-controller="Customer" asp-action="Check">Check action of Customer Controller</a>

在这种情况下,生成如下链接:

<a href="/Customer/Check">Check action of Customer Controller</a>
2 智能化生成链接
进入Home控制器的Check方法,创建一个指向Index方法的链接
<a asp-action="Index">Go to Index</a>

在这种情况下,你会发现在HTML中生成的地址仅仅包含/ 而不是Home/Index,如下所示:

<a href="/">Go to Index</a>
这是因为在应用程序中定义的路由针对controller和action提供了默认值,默认的controller是Home,默认的action是Index,这和asp-controller和asp-action帮助标签功能是相等的,因此ASP.NET Core没有给Href属性添加Controller和Action
3 根据Attribute路由生成链接
使用Attribute路由生成链接,添加AdminController在应用程序中,添加下面代码:
using Microsoft.AspNetCore.Mvc;namespace RouteLinks.Controllers{    [Route("News/[controller]/USA/[action]/{id?}")]    public class AdminController : Controller    {        public IActionResult Index()        {            return View();        }    }}

在AdminController上添加一个路由,使用attribute 路由生成一个链接

在Home控制器的Index方法添加一个超链接标签,设置asp-controller=Admin,asp-action=Index 代码如下:
<a asp-controller="Admin" asp-action="Index">Index Action of Admin Controller</a>

下面是Attribute 路由生成的链接:

<a href="/News/Admin/USA/Index">Index Action of Admin Controller</a>

4 当出现多个路由时生成外部链接

当应用程序中出现多个路由时,路由中间件会按照他们在Program类中定义的顺序来处理并且生成对外的链接,基于下面3个规则尝试与每个路由做匹配:
(1) 每个URL段必须提供一个值
(2) 对于仅限默认值的变量,我们必须要么不提供值,要么提供与默认值匹配的值
(3) 变量段的值应满足路线约束
URL中如果没有使用默认路由变量,但是路由本身提供了默认值,例子:在如下路由中,controller变量有默认值,因此路由中间件做匹配,有了默认值之后,我们不给该变量提供默认值时,该变量使用USA作为默认值
app.MapControllerRoute(    name: "defaultonly",    pattern: "{controller}/{action}",    defaults: new { controller = "USA" });
假如你应用程序中有2个路由
app.MapControllerRoute(    name: "stock",    pattern: "Stock/{action}",    defaults: new { controller = "Home" });app.MapControllerRoute(    name: "default",    pattern: "{controller=Home}/{action=Index}/{id?}");

在Home控制器的Index视图中添加下面代码:

<a asp-action="Index">Link1</a><a asp-controller="Product">Link2</a>
生成下面代码:
<a href="/Stock/Index">Link1</a><a href="/Product">Link2</a>
第一个链接生成url使用了stock路由,第二个链接生成url使用了default,在第一个链接<a asp-action="Index">Link1</a>中,我们没有给controller 提供值,因为它使用了默认值,因此这里满足第二条规则,我们也可以使用<a asp-controller="Home" asp-action="Index">产生相同的链接,这里我们给controller参数提供了Home的值,在这种情况下第二条规则被匹配成功

5 asp-route-{value}

到目前为止,您已经看到了如何使用控制器和方法创建链接,如果我们想要给其它段变量传递值,如id?,我们可以使用asp-route-{value}帮助标签,将{value}替换变量段的名称,如id,让我们创建一个链接,并传递一个Id的值

创建一个名字为ProductController控制器,并添加一个Index方法:
using Microsoft.AspNetCore.Mvc;namespace RouteLinks.Controllers{    public class ProductController : Controller    {        public string Index(int id)        {            return "Id Value is: " + id;        }    }}
我们从Home控制器的Index视图链接到Product控制器的Index方法,我们给Id段传递一个值,使用asp-route-{value} 帮助标签添加下面链接在Home控制器的Index视图中:
<a asp-controller="Product" asp-action="Index" asp-route-id="100">Pass 100 to the id segment</a>

现在运行应用程序并且检查html中生成的链接:

<a href="/Product/Index/100">Pass 100 to the id segment</a>

点击链接,将会跳转到Product控制器的Index方法,我们将显示Id段的值,这个段的值是100,使用asp-route-{value}帮助标签来设置该值    

ASP.NET Core 路由生成外部链接

6 根据指定路由生成链接

我们还可以使用路由名字生成链接,这时需要我们给asp-route标签指定一个具体的路由名称,代码如下:

app.MapControllerRoute(    name: "sales",    pattern: "sales/{controller=Home}/{action=Index}");

我们现在使用路由来创建一个链接,使用asp-route帮助标签,asp-route="sales",sales是路由的名称

在View中添加下面代码:

<a asp-route="sales">Sales</a>

将会生成如下地址:

<a href="/sales">Sales</a> 
我们除了使用asp-controller和asp-action帮助标签之外,还可以使用asp-route标签
这意味着路由对Controller和Action有默认值
7 Url.Action
我们还可以使用Url.Action()方法给action方法生成url,该方法是是根据应用程序中指定的路由来生成的,在HomeController的Index方法添加如下代码:
<p>@Url.Action("List", "Product", new { id = 10 })</p>

生成的url

/Product/List/10
 Url.Action() 方法使用下面参数:
  (1) Controller名称
  (2) Action名称
  (3) asp-route-{value}

也可以在action方法中使用Url.Action() ,代码如下:

string url = Url.Action("Index", "Home", new { id = 100 });

这里第一个参数是Action名称,第二个参数是Controller名称,第三个参数是asp-route-{value}

8 URL 片段(#)

使用#表示一个url片段,#是可选的并且位于url最后,#代表网页中的一个位置,例如:在锚点标签如下,url片段的名称为"Printing",因此当我们点击这个锚点,浏览器会搜索id为"Printing"的html标签,并且会滚动到这个标签
<a href="/Product/List#Printing">Printing</a>
我们可以使用asp-fragment="fragment-name" 帮助标签创建URL片段
<a asp-controller="Product" asp-action="List" asp-fragment="Printing">    URL Fragment</a>
9 在网页尾部添加斜杠(/)

RouteOption可以设置URL生成以至于在URL末尾能包含斜杠(/),进入Program.cs类并且添加代码:

builder.Services.Configure<RouteOptions>(options =>{    options.AppendTrailingSlash = true;});

将会生成如下url

https://localhost:7248/Stock/Index/https://localhost:7248/Product/https://localhost:7248/Product/Index/100/

10 小写URL

为了使URL变得更优雅,我们可以使用如下代码将其设置成小写的形式:
builder.Services.Configure<RouteOptions>(options =>{    options.LowercaseUrls = true;});

路由中间件会将url设置为小写形式

例如:check 方法的url http://localhost:58470/home/check/

总结
这节我们主要学习了在ASP.NET Core路由如何生成URL

源代码地址

https://github.com/bingbing-gui/Asp.Net-Core-Skill/tree/master/Fundamentals/AspNetCore.Route/AspNetCore.RouteLinks