我有一个API,其中所有方法都需要一个固定参数{customer}:
/cust/{customerId}/purchases
/cust/{customerId}/invoices
/cust/{customerId}/whatever*
我如何映射所有控制器以默认方式以可重用的方式接收此参数:
endpoints.MapControllerRoute(name: "Default", pattern: "/cust/{customerId:int}/{controller}*"
我在启动时使用了.net core 3.0和新的.useEndpoints方法。
答案 0 :(得分:1)
您可以创建ControllerModelConvention
的实现以自定义属性路由行为。有关更多详细信息,请参见official docs。
例如,假设您想将一个属性路由约定(例如/cust/{customerId:int}/[controller]
)与现有属性进行全局组合,只需创建一个如下约定:
public class FixedCustomIdControllerConvention : IControllerModelConvention
{
public void Apply(ControllerModel controller)
{
var customerRouteModel= new AttributeRouteModel(){
Template="/cust/{customerId:int}",
};
var isApiController= controller.ControllerType.CustomAttributes.Select(c => c.AttributeType)
.Any(a => a == typeof(ApiControllerAttribute));
foreach (var selector in controller.Selectors)
{
if(!isApiController)
{
var oldAttributeRouteModel=selector.AttributeRouteModel;
var newAttributeRouteModel= oldAttributeRouteModel;
if(oldAttributeRouteModel != null){
newAttributeRouteModel= AttributeRouteModel.CombineAttributeRouteModel(customerRouteModel, oldAttributeRouteModel);
}
selector.AttributeRouteModel=newAttributeRouteModel;
} else{
// ApiController won't honor the by-convention route
// so I just replace the template
var oldTemplate = selector.AttributeRouteModel.Template;
if(! oldTemplate.StartsWith("/") ){
selector.AttributeRouteModel.Template= customerRouteModel.Template + "/" + oldTemplate;
}
}
}
}
}
然后在启动中注册它:
services.AddControllersWithViews(opts =>{
opts.Conventions.Add(new FixedCustomIdControllerConvention());
});
假设我们有一个ValuesController
:
[Route("[controller]")]
public class ValuesController : Controller
{
[HttpGet]
public IActionResult Get(int customerId)
{
return Json(new {customerId});
}
[HttpPost("opq")]
public IActionResult Post(int customerId)
{
return Json(new {customerId});
}
[HttpPost("/rst")]
public IActionResult PostRst(int customerId)
{
return Json(new {customerId});
}
}
注册上述FixedCustomIdControllerConvention
后,路由行为为:
GET https://localhost:5001/cust/123/values
将与Get(int customerId)
方法匹配。POST https://localhost:5001/cust/123/values/opq
将与Post(int customerId)
方法匹配/rst
中加了一个斜杠,所以通行了全球惯例。结果,POST https://localhost:5001/rst
将与PostRst(int customerId)
方法(具有customId = 0)相匹配如果您使用的是带有[ApiController]
注释的控制器:
[ApiController]
[Route("[controller]")]
public class ApiValuesController : ControllerBase
{
[HttpGet]
public IActionResult Get([FromRoute]int customerId)
{
return new JsonResult(new {customerId});
}
[HttpPost("opq")]
public IActionResult Post([FromRoute]int customerId)
{
return new JsonResult(new {customerId});
}
[HttpPost("/apirst")]
public IActionResult PostRst([FromRoute]int customerId)
{
return new JsonResult(new {customerId});
}
}
您可能需要用[FromRoute]
装饰路由中的参数。