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

asp,net,core,mvc,控制器,各种,自定义,修改,参数,名称 · 浏览次数 : 636

小编点评

**方法参数的名称扩展** 1. 使用扩展接口类实现**IActionModelConvention**接口。 2. 在操作方法上设置**MyActionNameAttribute**。 3. 使用**IParameterModelConvention**接口定义**MyParameterAttribute**。 4. 在操作方法的参数上设置**MyParameterAttribute**。 5. 使用**ModelBinder**进行模型绑定。 **示例代码** ```csharp [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; } } [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; } } ```

正文

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

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

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

 

总算有满意的结果了。

 

与【ASP.NET Core】MVC控制器的各种自定义:修改参数的名称相似的内容:

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

在上一篇中,老周演示了通过实现约定接口的方式自定义控制器的名称。 至于说自定义操作方法的名称,就很简单了,因为有内置的特性类可以用。看看下面的例子。 [Route("[controller]/[action]")] public class StockController : Controller

【ASP.NET Core】MVC控制器的各种自定义:应用程序约定的接口与模型

从本篇起,老周会连发N篇水文,总结一下在 MVC 项目中控制器的各种自定义配置。 本文内容相对轻松,重点讨论一下 MVC 项目中的各种约定接口。毕竟你要对控制器做各种自定义时,多数情况会涉及到约定接口。约定接口的结构都差不多,均包含一个 Apply 方法,实现类需要通过这个方法修改关联的模型设置。

【ASP.NET Core】MVC控制器的各种自定义:IActionHttpMethodProvider 接口

IActionHttpMethodProvider 接口的结构很简单,实现该接口只要实现一个属性即可——HttpMethods。该属性是一个字符串序列。 这啥意思呢?这个字符串序列代表的就是受支持的 HTTP 请求方式。比如,如果此属性返回 GET POST,那么被修饰的对象既支持 HTTP-GET

【ASP.NET Core】MVC控制器的各种自定义:特性化的路由规则

MVC的路由规则配置方式比较多,咱们用得最多的是两种: A、全局规则。就是我们熟悉的”{controller}/{action}“。 app.MapControllerRoute( name: "bug", pattern: "{controller}/{action}" ); app.MapCon

【ASP.NET Core】MVC操作方法如何绑定Stream类型的参数

咱们都知道,MVC在输入/输出中都需要模型绑定。因为HTTP请求发送的都是文本,为了使其能变成各种.NET 类型,于是在填充参数值之前需 ModelBinder 的参与,以将文本转换为 .NET 类型。 尽管 ASP.NET Core 已内置基础类型和复杂类型的各种 Binder,但有些数据还是不能

如何将 Autofac 整合进 Net6.0 Core MVC 项目中

一、前言 1、简而言之 Asp.Net Core Mvc,我也用了很长一段时间了,它现在的编程模型和方式还是特别棒的,都是组件开发,什么都可以替换,当然了,您别抬杠,有些还是不能替换的。自从我们进入了跨平台开发的时代,IOC容器也成了一个不可或缺的东西了。微软为我们提供了一个默认实现,那就是 ISe

【ASP.NET Core】动态映射MVC路由

ASP.NET Core 中的几大功能模块(Razor Pages、MVC、SignalR/Blazor、Mini-API 等等)都以终结点(End Point)的方式公开。在HTTP管道上调用时,其扩展方法基本是以 Map 开头,如 MapControllers、MapBlazorHub。 对于

Asp.net MVC 跨域设置

.Net Core 跨域

异常过滤器—MVC中异常过滤器使用

## 一、什么是异常过滤器? 异常过滤器(**Exception Filters**)是 ASP.NET Core 中用于处理全局异常的机制。它们允许你在发生异常时捕获、处理和记录异常,并提供自定义的异常处理逻辑。异常过滤器在整个应用程序范围内生效,可以用于处理各种异常情况。用于实现常见的错误处理策

做一个windos服务和api搭配,获取电脑的mac地址

创建webapi项目,只是搭配服务用,什么三层mvc都不弄了,默认的模板直接用就好。 简单分析下,采用signalr通信来传递mac地址,所以先安装个signalr的包(如果简单操作的话可以不装最新的,微软自带一个,不过好像是弃用的) using Microsoft.AspNetCore.Signa