asp.net-core - 如何从 asp.net 核心中的约定中删除控制器
问题描述
我在 asp.net 核心中编写了一个解决方案,我需要更改路由名称,在控制器及其方法的名称中添加一个斜杠。我正在使用这段代码。
public class SlugifyParameterTransformer : IOutboundParameterTransformer
{
public string TransformOutbound(object value)
{
if (value == null) { return null; }
// Slugify value
return Regex.Replace(
value.ToString(),
"(?<!^)([A-Z][a-z]|(?<=[a-z])[A-Z])",
"-$1",
RegexOptions.Compiled)
.Trim()
.ToLower();
}
}
在 Startup.cs
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.Conventions.Add(new RouteTokenTransformerConvention(
new SlugifyParameterTransformer()));
}
);
}
我举个例子。
该项目有两个控制器
namespace Selling.API.Controllers
{
[ApiController]
[Route("api/v2/[controller]")]
public class SellsController : ControllerBase
{
[HttpPost("[action]")]
public async Task<ActionResult<IResponse<Sells>>> GetAll(){
// some code here
}
}
}
namespace Selling.API.Controllers
{
[ApiController]
[Route("api/v2/[controller]")]
public class CustomersController : ControllerBase
{
[HttpPost("[action]")]
public async Task<ActionResult<IResponse<Customers>>> GetAll(){
// some code here
}
}
}
如果我使用 SlugifyParameterTransformer,它将使用斜杠转换路由,从而导致:
api/v2/sells/get-all
api/v2/customers/get-all
但是,我需要忽略销售控制器,因为某些应用程序使用原始格式:
api/v2/Sells/GetAll
代码运行完美,并用斜杠转换所有路由名称,但所有控制器都被转换,我需要排除这个约定的一个控制器。我试图在 lugifyParameterTransformer 类中编写一些解决方案,但没有成功。我该如何解决这个问题?
解决方案
这是您的示例的解决方法,您可以通过实施IControllerModelConvention
.
public class DashedRoutingConvention: IControllerModelConvention
{
public void Apply(ControllerModel controller)
{
if (controller.ControllerName != "Home" && controller.ControllerName != "Sells")
{
if (controller.Selectors.Any(selector => selector.AttributeRouteModel != null))
{
foreach (var controllerSelector in controller.Selectors.Where(x => x.AttributeRouteModel != null))
{
var originalTemp = controllerSelector.AttributeRouteModel.Template;
var newTemplate = new StringBuilder();
newTemplate.Append(PascalToKebabCase(controller.ControllerName));
controllerSelector.AttributeRouteModel = new AttributeRouteModel
{
Template = originalTemp.Replace("[controller]", newTemplate.ToString())
};
foreach (var controllerAction in controller.Actions)
{
foreach (var actionselector in controllerAction.Selectors.Where(x=>x.AttributeRouteModel!=null))
{
var origTemp = actionselector.AttributeRouteModel.Template;
var template = new StringBuilder();
template.Append(PascalToKebabCase(controllerAction.ActionName));
controllerSelector.AttributeRouteModel = new AttributeRouteModel
{
Template = originalTemp.Replace("[action]", newTemplate.ToString())
};
}
}
}
}
}
}
public static string PascalToKebabCase(string value)
{
if (string.IsNullOrEmpty(value))
return value;
var a= Regex.Replace(
value,
"(?<!^)([A-Z][a-z]|(?<=[a-z])[A-Z])",
"-$1",
RegexOptions.Compiled)
.Trim()
.ToLower();
return Regex.Replace(
value,
"(?<!^)([A-Z][a-z]|(?<=[a-z])[A-Z])",
"-$1",
RegexOptions.Compiled)
.Trim()
.ToLower();
}
}
然后在 Startup.cs 中注册
services.AddMvc(options =>
{
options.Conventions.Add(new DashedRoutingConvention());
});
它仅适用于您在示例中提供的路由模板,如果您想将其应用于所有路由,您可能必须在控制器和方法上统一路由模板。
对于控制器和操作上的非自定义路由,您可以参考这里
推荐阅读
- php - 高速公路管理订阅
- error-handling - 从 JMS 发送消息时如何捕获错误
- bash - Bash脚本:带有If语句的While循环导致无限循环
- javascript - Google API 日历承诺
- servlets - AEM CQ5 servlet 未在本地环境中调用
- javascript - React Native:Android 未显示所有图像(即使它们相同)
- php - 最后用 ?> 查找文件的简单方法?
- c++ - 如何制作 std::function 参考
- java - 如何使用 appium 测试聊天应用程序?
- java - java.lang.NoClassDefFoundError:无法初始化类 org.apache.xmbeans.XmlBeans