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

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

    [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;

总算有满意的结果了。

最新文章

  1. 使用jQuery页面加载函数启动定时任务
  2. [BZOJ 2631]tree
  3. log4j的基本配置参数
  4. <1>数据引用与匿名存储
  5. google protocol buffer -2-.proto 定义规则
  6. Hibernate.cfg.xml 主配置
  7. [翻译]成为顶尖程序员应当学什么?Python、C还是Ruby?
  8. 【多线程】-Thread
  9. tsc.exe 已退出 代码为 1
  10. 想成为Python全栈开发工程师必须掌握的技能
  11. Python学习之旅(十二)
  12. raw_socket(原始套接字)以及普通socket使用终极总结
  13. Cpython解释器下实现并发编程——多进程、多线程、协程、IO模型
  14. alert.log中的minact-scn: useg scan erroring out with error e:376警告
  15. 引用google字体
  16. asp.net mvc webapi 实用的接口加密方法(转载)
  17. 03 重定向,请求转发,cookie,session
  18. hdu3746 Cyclic Nacklace KMP
  19. Python遇到ModuleNotFoundError: No module named 'email.mime'; 'email' is not a package问题的处理办法
  20. 关于CAE的那点儿破事儿

热门文章

  1. PLSQL 与 PLPGSQL
  2. 高可用代理服务器实现keepalive+squid
  3. Lua CallbackHell优化
  4. .NET 7 来了!!!
  5. 我也是一个“翻译家”——关于“robust”
  6. 3.Ceph 基础篇 - RBD 块存储使用
  7. Beats:如何使用Winlogbeat
  8. C++面向对象编程之类的写法
  9. 洛谷P1115 最大子段和 (线性DP)
  10. How to Create DLL(Dynamic link library)