首页 > 解决方案 > 如何从 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 类中编写一些解决方案,但没有成功。我该如何解决这个问题?

标签: asp.net-core

解决方案


这是您的示例的解决方法,您可以通过实施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());
});

它仅适用于您在示例中提供的路由模板,如果您想将其应用于所有路由,您可能必须在控制器和方法上统一路由模板。

对于控制器和操作上的非自定义路由,您可以参考这里


推荐阅读