• 【ASP.NET Core】MVC控制器的各种自定义:修改参数的名称


    在上一篇中,老周演示了通过实现约定接口的方式自定义控制器的名称。

    至于说自定义操作方法的名称,就很简单了,因为有内置的特性类可以用。看看下面的例子。

        [Route("[controller]/[action]")]
        public class StockController : Controller
        {
            [ActionName("OutGoing"), HttpGet("{q?}")]
            public string Sendout(int q) => $"今天发出{q}笔订单";
        }

    上述代码中,本来操作方法的名称是“Sendout”,但应用了 ActionName 特性后,就变成“OutGoing”了。访问 /stock/outgoing/12 试试看。

     

     如何?简单吧。可是有大伙伴会说,那我用实现约定接口的方式能实现吗?能,扩展的是 IActionModelConvention 接口,修改 ActionModel 实例的 ActionName 属性就可以了。请参考下面代码:

    复制代码
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class MyActionNameAttribute : Attribute, IActionModelConvention
    {
        private readonly string _actionName;
    
        public MyActionNameAttribute(string Name)
        {
           _actionName = Name;
        }
    
        public void Apply(ActionModel action)
        {
            action.ActionName = _actionName;
        }
    }
    复制代码

    然后,咱们用自己定义的这个特性类替换 ActionName 特性。

        [Route("[controller]/[action]")]
        public class StockController : Controller
        {
            [MyActionName("OutGoing"), HttpGet("{q?}")]
            public string Sendout(int q) => $"今天发出{q}笔订单";
        }

    效果是一样的哟。

    ------------------------------------------------------------------ 银河分隔线 ----------------------------------------------------------------

    控制器和操作方法的自定义名称好弄,但,方法参数的名称就不好弄了。有大伙伴就不乐意了,我直接按思路套代码不就行了吗?扩展下 IParameterModelConvention 接口,然后设置 ParameterModel.ParameterName 属性不就完事了吗?

    是的,梦境总是那么美好,咱们不妨试试。

    复制代码
        [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
        public class MyParameterAttribute : Attribute, IParameterModelConvention
        {
            private readonly string _name;
    
            public MyParameterAttribute(string name)
            {
                _name = name;
            }
    
            public void Apply(ParameterModel parameter)
            {
                parameter.ParameterName = _name;
            }
        }
    复制代码

    接着,套在控制器的操作方法上。

    public class TestController : Controller
    {
        [HttpGet("test/get")]
        public int GetNumber([MyParameter("num")]int xx) => xx * 5;
    }

    试试看,访问 /test/get?num=5。结果……

     

     WTF,这是咋回事呢?不知道伙伴们有没有看过老周曾写过模型绑定的水文。其实这里我们不需要对模型绑定有多深的了解,但我们得知道,对于操作方法的参数来说,是存在模型绑定这一过程的。这就导致不能修改一下参数名就完事了,ModelBinder 认的是参数的数据类型,而不是 ApplicationModel 中的信息。这里头牵涉的东西太多了,你无法任性地扩展一两个接口就能完事的。但也不是没有办法,不用写扩展,有个现成的特性类也能给参数设置别名。

       [HttpGet("test/get")]
       public int GetNumber([ModelBinder(Name = "num")]int xx) => xx * 5;

    使用 ModelBinder特性,然后改一下 Name 属性就好了。咱们再试试。

     

     怎么样,有效果吧。

    可你又说了,我要是坚持要通过约定接口来扩展,那有法子乎?有,原理一样,改 ModelBinder 的名字。

    复制代码
        [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
        public class MyParameterAttribute : Attribute, IParameterModelConvention
        {
            private readonly string _name;
    
            public MyParameterAttribute(string name)
            {
                _name = name;
            }
    
            public void Apply(ParameterModel parameter)
            {
                // 注意,BindingInfo 属性可能会为null
                parameter.BindingInfo ??= new BindingInfo();
                // 修改模型名称
                parameter.BindingInfo.BinderModelName = _name;
            }
        }
    复制代码

    原理就是设置 BindingInfo 类的 BinderModelName 属性。

    再试试看。

    [HttpGet("test/get")]
    public int GetNumber([MyParameter("num")]int xx) => xx * 5;

     

    总算有满意的结果了。

     

  • 相关阅读:
    【Openxml】颜色变化属性计算
    如何修改运行中的docker容器的端口映射
    解决sleuth链路追踪失效的问题,sleuth版本升级为3.1.3后X-B3-TraceId:-打印不出来了,解决方案
    [LeetCode] 最后一个单词的长度【58】
    利用在Tomcat上部署servlet程序(手动布置加强关于servlet知识的理解,当前的idea是可以实现自动部署的)
    【无锁队列】无锁CAS_无锁队列
    blender从视频中动作捕捉,绑定到人物模型
    C# Socket通信从入门到精通(10)——如何检测两台电脑之间的网络是否通畅
    Linux管道的工作过程
    Linux 怎样通过win 远程桌面连接链接Linux后台服务器的可视化图形界面
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/16905627.html