将自定义属性值绑定到路由约束
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 的视图
如何将自定义属性值绑定到路由?
我想要的:
[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 的视图