将自定义属性值绑定到路由约束

Bind custom attribute value to route constraint

如何将自定义属性值绑定到路由?

我想要的:

[ApiController]
[CustomAttribute("value")]
[Route("{customAttributeValue}/[controller")]
public class ExampleController : Controller
{
    //...
}

那么我的路线应该是这样的。

我第一次看到版本控制 apis

[ApiController]
[ApiVersion("2")] 
[Route("v{version:apiVersion}/[controller]")]
public class ExampleController : Controller
{
    //...
}

所以大摇大摆地,这个示例控制器看起来像这样:

您可以使用自定义路由属性来解决这个问题。

示例代码:

namespace Test.Controllers
{

public class MyCustomValueAttribute : RouteAttribute
{

    public MyCustomValueAttribute(string route, string prefixRoute, int prefixRouteCustomValue) : base($"{prefixRoute}/{prefixRouteCustomValue}/{route}")
    {


    }
}


[ApiController]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    
    [HttpGet]
    [MyCustomValue("[controller]", "value", 20)]
    public IEnumerable<WeatherForecast> Get()
    {
        var rng = new Random();
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = rng.Next(-20, 55),
            Summary = Summaries[rng.Next(Summaries.Length)]
        })
        .ToArray();
    }
}

}

输出:

首先定义该自定义属性,它接受 string 值,该值必须是路由的一部分。

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public sealed class CustomValueAttribute : Attribute
{
    public CustomValueAttribute(string value)
        => Value = value;

    public string Value { get; }
}

设置一个IActionModelConvention将该属性值应用于正在执行的控制器的路由。在这里,您可以决定要在路由定义中用作占位符的名称;下面的例子使用 customValue.

public sealed class CustomValueRoutingConvention : IActionModelConvention
{
    public void Apply(ActionModel action)
    {
        var value = action.Controller.ControllerType.GetCustomAttribute<CustomValueAttribute>()?.Value;
        if (value is not null)
        {
            action.RouteValues.Add("customValue", value);
        }
    }
}    

下一步是将上述约定挂接到 MvcOptions
您可以在调用 AddControllers.

时执行此操作
builder.Services.AddControllers(
    mvcOptions => mvcOptions.Conventions.Add(new CustomValueRoutingConvention())
);

最后,CustomValueAttribute和路由占位符被应用到控制器。注意路由中的 [customValue] 占位符。

[ApiController]
[CustomValue("value")]
[Route("[customValue]/[controller]")]
public class ExampleController : ControllerBase

来自 Swagger 的视图