ASP.NET Core中我们可以使用C# Attribute特性给Controller和Actions方法添加路由,如果Program类中定义了契约路由,我们可以使用Attribute路由来重写契约路由。
1 Attribute路由例子
和之前一样,我们通过一个例子来了解Attribute路由,在Visual Studio中创建一个ASP.NET Core MVC项目
默认的契约路由定义在Program类中,如下代码所示:
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
如何设置Attribute路由呢?在C#中有[Route()] 特性,我们可以把该特性应用到Controller或者Action 方法,例如 提交一个特性-[Route("CallRoute")]在Home控制器的Index方法上,这将针对这个方法添加一个attribute路由,现在Inedx方法将使用/CallRoute路由,代码如下:
using AspNetCore.AttributeRoute.Models;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
namespace AspNetCore.AttributeRoute.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
[Route("CallRoute")]
public IActionResult Index()
{
return View();
}
}
}
运行程序并访问https://localhost:7073/CallRoute,我们发现HomeController中的Index方法被调用,这是因为使用路由特性访问这个方法的url
图片
使用契约路由,打开https://localhost:7073/Home/Index,我们发现这个地址不再工作,这是因为Attribute路由的重写契约路由,因此老的路由不再工作
这里我们必须记住,当我们使用Attribute路由时,并不意味着所有契约路由将不能工作,当契约路由和Attribute路由都被应用时,在ASP.NET Core中Attribute路由具有更高的优先级,你可以测试一下,当我们打开https://localhost:7073/Home/Privacy,HomeController中的Privacy方法被调用
2 Attribute路由中的[controller]和[action]标记
[controller]和[action]标记作为路由特性引用Controller和Action名字,为了更容易理解,我们创建一个例子,添加AdminController.cs,在Controller中添加如下代码:
using Microsoft.AspNetCore.Mvc;
namespace AspNetCore.AttributeRoute.Controllers
{
public class AdminController : Controller
{
[Route("[controller]/CallMe")]
public string Index()
{
return "'Admin' Controller, 'Index' View";
}
public string List()
{
return "'Admin' Controller, 'List' View";
}
}
}
我们将这个路由特性提交到Index方法,这个路由包含了Controller段,这个段会使用Controller名字替换掉,这个路由的特性被替换为Admin,后面跟着CallMe的字符串,因此调用这个方法的url是/Admin/CallMe
运行程序来,打开https://localhost:7073/Admin/Callme,你会发现Admin控制器中的Index方法被调用,如下图所示:
注意,我们没有给List方法添加Attribute特性,因此它将使用 https://localhost:7073/Admin/List
我们将[action]标记应用到路由特性,添加一个新的action方法叫Show在AdminController并且在该方法上使用Attribute路由:
[Route("[controller]/CallMe/[action]")]
public string Show()
{
return "'Admin' Controller, 'Show' View";
}
我们使用https://localhost:7073/admin/callme/show 调用这个action方法
3 在Controller上使用路由特性
我们也可以在Controller上使用路由特性,因此控制器里面的所有方法将继承这个路由特性,修改AdminController代码如下:
using Microsoft.AspNetCore.Mvc;
namespace AspNetCore.AttributeRoute.Controllers
{
[Route("News/[controller]/USA/[action]/{id?}")]
public class AdminController : Controller
{
//[Route("[controller]/CallMe")]
public string Index()
{
return "'Admin' Controller, 'Index' View";
}
public string List()
{
return "'Admin' Controller, 'List' View";
}
//[Route("[controller]/CallMe/[action]")]
public string Show()
{
return "'Admin' Controller, 'Show' View";
}
}
}
我们在Controller上应用了Attribute路由,因此该类的所有方法会会自动继承它,下面URL将调用Index方法
/News/Admin/USA/Index
/News/Admin/USA/Index/100
/News/Admin/USA/Index/Hello
下面URL将调用List方法
/News/Admin/USA/List
/News/Admin/USA/List/100
/News/Admin/USA/List/Hello
4 Attribute路由约束
Attribute路由可以使用路由约束,例如在下面代码中我们Attribute路由中给id段添加Int约束,这将只允许id段使用int值
[Route("[controller]/[action]/{id:int}")]
public class AdminController : Controller
{
}
因此上面的URL将匹配
/Admin/Index/10
/Admin/List/4
/Admin/Privacy/5
下面URL将不会被匹配
/Admin/Index/Jack
/Admin/List
/Admin/Privacy/USA/100
我们在上一节中创建一个户自定约束叫OnlyGodsConstraint,它也可以被应用到路由特性,代码如下:
using Microsoft.AspNetCore.Mvc;
namespace URLRouting.Controllers
{
[Route("News/[controller]/USA/[action]/{id:allowedgods?}")]
public class AdminController : Controller
{
public string Index()
{
return "'Admin' Controller, 'Index' View";
}
public string List(string id)
{
return "'Admin' Controller, 'List' View";
}
}
}
使用https://localhost:7073/News/Admin/USA/Index/Shiv调用Index方法,如下图所示:
总结
这节我们主要了解了Attribute路由