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

asp,net,core,mvc,控制器,各种,自定义,iactionhttpmethodprovider,接口 · 浏览次数 : 429

小编点评

IActionHttpMethodProvider 接口的结构很简单,其中包含一个属性“HttpMethods”。这个属性是一个字符串序列,表示受支持的 HTTP 请求方式。 当使用 IActionHttpMethodProvider 接口实现 ActionMethodProvider 接口时,属性“HttpMethods”用于指定可支持的 HTTP 请求方式。当使用 IRouteTemplateProvider 接口实现 RouteAttribute 时,属性“HttpMethods”用于指定可支持的 HTTP 请求方式。 通过构造函数的参数可以传递一个或 N 个HTTP请求方式。正因为如此,该特性类在同一个目标上就不需要多次应用了,所以,我把 AllowMultiple 设置为 false。

正文

IActionHttpMethodProvider 接口的结构很简单,实现该接口只要实现一个属性即可——HttpMethods。该属性是一个字符串序列。

这啥意思呢?这个字符串序列代表的就是受支持的 HTTP 请求方式。比如,如果此属性返回 GET POST,那么被修饰的对象既支持 HTTP-GET 请求,也支持 HTTP-POST 请求。咱们在写 Web API 时最熟悉的这几个特性类就是实现了 IActionHttpMethodProvider  接口。

[HttpGet]
[HttpPost]
[HttpPut]
[HttpDelete]
[HttpHead]
[HttpPatch]
[HttpOptions]

这几个特性类不仅实现了 IActionHttpMethodProvider 接口,还实现了 IRouteTemplateProvider。所以它们可以当 [Route] 特性来用,又可以限制 HTTP 请求方式,一举两得。

咱们在实际项目中,如果希望一个操作方法同时支持多种请求方法,可以叠加使用以上特性类。比如

[HttpPut]
[HttpPost]
public float GetAFloat()

还可以自己定义一个特性类,实现 IActionHttpMethodProvider 接口,从 HttpMethods 属性返回一组请求方式。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class CustHttpmethodsAttribute : Attribute, IActionHttpMethodProvider
{
    private readonly string[] _httpmethods;

    // 构造函数
    public CustHttpmethodsAttribute(params string[] httpmethods)
    {
        _httpmethods = httpmethods;
    }

    // 这个是实现接口的成员
    public IEnumerable<string> HttpMethods => _httpmethods;
}

很简单的一个类,HttpGet 等特性类只能应用到操作方法上,这里老周把限制放宽一些,让其可以应用到类和方法上,即可以用在控制器和操作方法上面。

通过构造函数的参数可以传递一个或 N 个HTTP请求方式。正因为如此,该特性类在同一个目标上就不需要多次应用了,所以,我把 AllowMultiple 设置为 false。

接下来,测试一下这厮能不能用。

[CustHttpmethods("PUT", "POST"), Route("manage/[action]")]
public class StudentController : ControllerBase
{
    public IActionResult AddNew(Student stu)
    {
        // 要是 StuSerail 或 Name 属性没找到
        // IsValid 就返回 false
        if(!ModelState.IsValid)
        {
            return Content("数据无效");
        }

        return Content($"添加成功!\n学号:{stu.StuSerial}\n姓名:{stu.Name}\n年龄:{stu.Age}\n微信名称:{stu.WXName}");
    }
}

下面是 Student 类的定义。

public class Student
{
    /// <summary>
    /// 学号
    /// </summary>
    [BindRequired]
    public long StuSerial { get; set; }
    /// <summary>
    /// 姓名
    /// </summary>
    [BindRequired]
    public string? Name { get; set; } = "宇宙人";
    /// <summary>
    /// 微信名字
    /// </summary>
    public string? WXName { get; set; } = "钓鱼佬";
    /// <summary>
    /// 年龄
    /// </summary>
    public int Age { get; set; } = 0;
}

应用了 BindRequired 特性的意思就是:在模型绑定时,如果没能在客户端提交的数据中找到这些属性的值,那么模型的绑定状态(Model State)就会设置 IsValid 属性为 false。在 Student 类中,StuSerial 和 Name 属性要求必须绑定有效。

根据上述代码的设计,Student 控制器中的所有操作都只允许 HTTP-PUT 和 HTTP-POST 两种请求。下面咱们来验证一下,前面写的 CustHttpmethods 特性是否生效。

这里老周用 .NET Tools 提供的 http-repl 工具来测试——嗯,别多想,肯定是个命令行工具。如果你还没安装,可以用这条命令安装它。

dotnet tool install -g Microsoft.dotnet-httprepl

其中,-g 表示安装到用户的默认路径中。

用法:httprepl http://localhost:1254,回车后进入交互模式,只要输入相关命令即可。如 get post delete put patch 等,帮助信息可以用 help 来查看。

咱们把 echo 选项打开,这样该工具就会显示请求的 HTTP 消息。

echo on

运行应用程序,试试 HTTP-GET 能不能访问。

get /manage/addnew?stuserial=123456&name=小吴&age=22

得到的响应消息如下:

 

显然,GET 方法无法通过。

那试试 POST 。

post /manage/addnew -h "Content-Type=application/x-www-form-urlencoded" -c stu.stuserial=123456&stu.name=小明&stu.age=24&stu.wxname=二哈

-h 表示要添加的 HTTP 消息头,多个头可以多次使用-h,总之一个头用一次-h;-c 表示正文(body)。

这一次提交很顺利,得到服务器的正确回应。

 

正文部分的 stu 前缀可以省略。

stuserial=123456&name=小高&age=20&wxname=工具人

POST 请求没有问题,再试试 PUT。

put /manage/addnew -h Content-Type:application/x-www-form-urlencoded -c stuserial=67980&name=小张&age=19&wxname=扫雷冠军

请求也成功完成,服务器有正确的响应。

 

 

咱们继续实验。刚才测试的都是标准的 HTTP 请求方式,要是咱们来个非规范的会怎么样呢?比如,弄个叫 “SET” 的请求方法。

[CustHttpmethods("SET"), Route("manage/[action]")]
public class StudentController : ControllerBase
{
      ……
}

实验继续。

这一次咱们不能用 http-repl 工具了,因为 SET 不是规范的请求方式,测试工具不支持。但可以写个控制台应用程序来测试。

// 这一行主要是为了等服务器运行起来
// 当此项目与服务器项目一起启动时用得上
await Task.Delay(1000);

Uri rootUrl = new("https://localhost:12550");

HttpClient client = new();

// form-data
IDictionary<string, string> data = new Dictionary<string, string>()
{
    ["stuserial"] = "76008",
    ["name"] = "小青",
    ["age"] = "19",
    ["wxname"] = "南方小鲟"
};

FormUrlEncodedContent content = new FormUrlEncodedContent(data);

HttpRequestMessage reqmsg = new HttpRequestMessage();
// 这个不是标准的,得自己写上
reqmsg.Method = new HttpMethod("SET");
reqmsg.RequestUri = new Uri(rootUrl, "/manage/addnew");
reqmsg.Content = content;
// 发送
var resp = await client.SendAsync(reqmsg);

Console.WriteLine($"响应代码:{(int)resp.StatusCode}");
Console.WriteLine($"响应内容:\n{await resp.Content.ReadAsStringAsync()}");

// 这两行只是为了让程序能停下来罢了,没其他用途
Console.WriteLine();
Console.ReadKey();

虽然是非标准的请求方式,但的确可用。

 

 

好了,今天咱们就聊到这儿了。

 

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

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

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

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

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

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

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

【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