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 接口的更多相关文章

  1. ASP.NET Core 入门教程 4、ASP.NET Core MVC控制器入门

    一.前言 1.本教程主要内容 ASP.NET Core MVC控制器简介 ASP.NET Core MVC控制器操作简介 ASP.NET Core MVC控制器操作简介返回类型简介 ASP.NET C ...

  2. ASP.NET Core 入门笔记5,ASP.NET Core MVC控制器入门

    摘抄自https://www.cnblogs.com/ken-io/p/aspnet-core-tutorial-mvc-controller-action.html 一.前言 1.本教程主要内容 A ...

  3. ASP.NET Core MVC 控制器创建与依赖注入

    本文翻译自<Controller activation and dependency injection in ASP.NET Core MVC>,由于水平有限,故无法保证翻译完全准确,欢 ...

  4. 扒一扒asp.net core mvc控制器的寻找流程

    不太会排版,大家将就看吧. asp.net core mvc和asp.net mvc中都有一个比较有意思的而又被大家容易忽略的功能,控制器可以写在非Web程序集中,比如Web程序集:"MyW ...

  5. asp.net core MVC 控制器,接收参数,数据绑定

    1.参数 HttpRequest HttpRequest 是用户请求对象 QueryString Form Cookie Session Header 实例: public IActionResult ...

  6. Asp.Net Core MVC控制器和视图之间传值

    一.Core MVC中控制器和视图之间传值方式和Asp.Net中非常类似 1.弱类型数据:ViewData,ViewBag 2.强类型数据:@model 二.代码 实例  1.ViewData pub ...

  7. ASP.NET Core 入门教程 3、ASP.NET Core MVC路由入门

    一.前言 1.本文主要内容 ASP.NET Core MVC路由工作原理概述 ASP.NET Core MVC带路径参数的路由示例 ASP.NET Core MVC固定前/后缀的路由示例 ASP.NE ...

  8. Pro ASP.NET Core MVC 第6版 第一章

    目录 第一章 ASP.NET Core MVC 的前世今生 ASP.NET Core MVC 是一个微软公司开发的Web应用程序开发框架,它结合了MVC架构的高效性和简洁性,敏捷开发的思想和技术和.N ...

  9. ASP.NET Core MVC 之视图(Views)

    ASP.NET Core MVC 控制器可以使用视图返回格式化的结果. 1.什么是视图 在 MVC 中,视图封装了用户与应用交互呈现细节.视图是具有生成要发送到客户端内容的,包含嵌入代码的HTML模板 ...

  10. ASP.NET Core 入门笔记4,ASP.NET Core MVC路由入门

    敲了一部分,懒得全部敲完,直接复制大佬的博客了,如有侵权,请通知我尽快删除修改 摘抄自https://www.cnblogs.com/ken-io/p/aspnet-core-tutorial-mvc ...

随机推荐

  1. k8s中pod的容器日志查看命令

    如果容器已经崩溃停止,您可以仍然使用 kubectl logs --previous 获取该容器的日志,只不过需要添加参数 --previous. 如果 Pod 中包含多个容器,而您想要看其中某一个容 ...

  2. SpringCloud组件编写Dockerfile文件模板

    在组件根目录下的Dockerfile文件 # Dockerfile文件内容 FROM idocker.io/jre:1.8.0_212 #自定义的基础镜像 VOLUME /tmp # 挂载目录 ADD ...

  3. CentOS7内置Realtek网卡驱动r8169降级r8168

    前几天装了几台服务器测试,在使用的过程中发现,每次重启系统,登录界面会弹出网卡提示  "r8169 0000:02:00 eth0 Invalid ocp reg 17758!" ...

  4. 1_Linux

    一. Linux介绍 1.1 引言 在学习Linux之前, 大家先了解开发环境,生产,测试环境 开发环境: 平时大家大多是在Windows或者Mac操作系统下去编写代码进行开发,在开发环境中安装大量的 ...

  5. 请求库之requests库

    目录 一.介绍 二.基于get请求 1 基本请求 2 带参数的get请求 3 请求携带cookie 三.基于post请求 1 基本用法 2 发送post请求,模拟浏览器的登录行为 四.响应Respon ...

  6. C++ 自学笔记 对象的初始化

    数组的初始化: 在 C++中  struct ≈ Class:struct里面可以有函数. 默认构造函数: 没有参数的构造函数就是默认构造函数

  7. PAT (Advanced Level) Practice 1003 Emergency 分数 25 迪杰斯特拉算法(dijkstra)

    As an emergency rescue team leader of a city, you are given a special map of your country. The map s ...

  8. 一个C#开发者学习SpringCloud搭建微服务的心路历程

    前言 Spring Cloud很火,很多文章都有介绍如何使用,但对于我这种初学者,我需要从创建项目开始学起,所以这些文章对于我的启蒙,帮助不大,所以只好自己写一篇文章,用于备忘. SpringClou ...

  9. 一键生成通用高亮代码块到剪贴板,快捷粘贴兼容 TT/WX/BJ 编辑器

    有些在线图文编辑器不支持直接插入代码块,但可以直接粘贴 HTML 格式的高亮代码块. 花了一点时间研究了一下各家的编辑器,规则却各不相同.有的要求代码块被包含于 <code> ... &l ...

  10. 树莓派Zero 2 W(ubuntu-22.04)通过.NET6和libusb操作USB读写

    有这个想法的初衷 喜欢电子和DIY硬件的朋友对稚晖君应该都不陌生,他定期都会分享一些自己做的好玩的硬件,他之前做了一个ElectronBot桌面机器人我就很感兴趣,所以就自己也做了一个. 起初我只是自 ...