由于 ModelBinding在动作过滤器之前运行,直接使用 context.ActionArguments["parameter"]  获取模型对象

This article shows how to use an ActionFilter to validate the model from a HTTP POST request in an ASP.NET Core MVC application.

Code: https://github.com/damienbod/AngularAutoSaveCommands

2019-07-31: Updated to ASP.NET Core 3.0 Preview 7, Updated to Angular 8.1.3
2019-02-16: Updated to Angular 7.2.4, ASP.NET Core 2.2 nuget packages
2018-11-22: Updated to Angular 7.1.0, nuget packages
2018-09-28: Updated to ASP.NET Core 2.1.4 and Angular 6.1.9
2018-06-16: Updated to ASP.NET Core 2.1 and Angular 6.0.5
2018-02-11: Updated to ASP.NET Core All 2.0.5 and Angular 5.2.4
2017-08-19: Updated to ASP.NET Core 2.0 and Angular 4.3.5
2017.02.03: Updated to Angular 2.4.5 and webpack 2.2.1, VS2017 RC3, msbuild3
2016.12.23: Updated to Visual Studio 2017 and ASP.NET Core 1.1

Other articles in this series:

  1. Implementing UNDO, REDO in ASP.NET Core
  2. Angular Auto Save, Undo and Redo
  3. ASP.NET Core Action Arguments Validation using an ActionFilter

In an ASP.NET Core MVC application, custom validation logic can be implemented in an ActionFilter. Because the ActionFilter is processed after the model binding in the action execution, the model and action parameters can be used in an ActionFilter without having to read from the Request Body, or the URL.

The model can be accessed using the context.ActionArguments dictionary. The key for the property has to match the parameter name in the MVC Controller action method. Ryan Nowak also explained in this issue, that the context.ActionDescriptor.Parameters can also be used to access the request payload data.

If the model is invalid, the context status code is set to 400 (bad request) and the reason is added to the context result using a ContentResult object. The request is then no longer processed but short circuited using the terminology from the ASP.NET Core documentation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using System;
using System.IO;
using System.Text;
using AngularAutoSaveCommands.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
 
namespace AngularAutoSaveCommands.ActionFilters
{
    public class ValidateCommandDtoFilter : ActionFilterAttribute
    {
        private readonly ILogger _logger;
 
        public ValidateCommandDtoFilter(ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger("ValidatePayloadTypeFilter");
        }
 
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            var commandDto = context.ActionArguments["commandDto"] as CommandDto;
            if (commandDto == null)
            {
                context.HttpContext.Response.StatusCode = 400;
                context.Result = new ContentResult()
                {
                    Content = "The body is not a CommandDto type"
                };
                return;
            }
 
            _logger.LogDebug("validating CommandType");
            if (!CommandTypes.AllowedTypes.Contains(commandDto.CommandType))
            {
                context.HttpContext.Response.StatusCode = 400;
                context.Result = new ContentResult()
                {
                    Content = "CommandTypes not allowed"
                };
                return;
            }
 
            _logger.LogDebug("validating PayloadType");
            if (!PayloadTypes.AllowedTypes.Contains(commandDto.PayloadType))
            {
                context.HttpContext.Response.StatusCode = 400;
                context.Result = new ContentResult()
                {
                    Content = "PayloadType not allowed"
                };
                return;
            }
 
            base.OnActionExecuting(context);
        }
    }
}

The ActionFilter is added to the services in the Startup class. This is not needed if the ActionFilter is used directly in the MVC Controller.

1
services.AddScoped<ValidateCommandDtoFilter>();

The filter can then be used in the MVC Controller using the ServiceFilter attribute. If the commandDto model is invalid, a BadRequest response is returned without processing the business in the action method.

1
2
3
4
5
6
7
8
[ServiceFilter(typeof(ValidateCommandDtoFilter))]
[HttpPost]
[Route("Execute")]
public IActionResult Post([FromBody]CommandDto commandDto)
{
    _commandHandler.Execute(commandDto);
    return Ok(commandDto);
}

Links

https://docs.asp.net/en/latest/mvc/controllers/filters.html

https://github.com/aspnet/Mvc/issues/5260#issuecomment-245936046

https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ActionExecutingContext.cs

.net core 从 ActionFilterAttribute 获取Request.Body 的正确方式的更多相关文章

  1. 深入探究ASP.NET Core读取Request.Body的正确方式

    前言 相信大家在使用ASP.NET Core进行开发的时候,肯定会涉及到读取Request.Body的场景,毕竟我们大部分的POST请求都是将数据存放到Http的Body当中.因为笔者日常开发所使用的 ...

  2. @Spring MVC 中几种获取request和response的方式

    1.最简单方式:处理方法入参 例如: @RequestMapping("/test") @ResponseBody public void saveTest(HttpServlet ...

  3. Struts2获取request的几种方式汇总

    Struts2获取request三种方法 struts2里面有三种方法可以获取request,最好使用ServletRequestAware接口通过IOC机制注入Request对象. 在Action中 ...

  4. .net core web api 获取request body的纯文本

    本文代码 https://github.com/wuhaibo/readPlainTextDotNetCoreWepApi 总有些时候我们希望获得Request body 的纯文本 那么怎么做呢?很简 ...

  5. springMVC 中几种获取request和response的方式

    1.最简单方式:参数 例如: @RequestMapping("/test") @ResponseBody public void saveTest(HttpServletRequ ...

  6. 在springMVC的controller中获取request,response对象的一个方法

    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttr ...

  7. ASP.NET Core Web APi获取原始请求内容

    前言 我们讲过ASP.NET Core Web APi路由绑定,本节我们来讲讲如何获取客户端请求过来的内容. ASP.NET Core Web APi捕获Request.Body内容 [HttpPos ...

  8. RequestContextHolder 很方便的获取 request

    在 Spring boot web 中我们可以通过 RequestContextHolder 很方便的获取 request. ServletRequestAttributes requestAttri ...

  9. jeecg中的一个上下文工具类获取request,session

    通过调用其中的方法可以获取到request和session,调用方式如下: HttpServletRequest request = ContextHolderUtils.getRequest();H ...

随机推荐

  1. SQL Server中如何把 科学记数法字符串 变为 数字字符串

    当我们将Excel的数据导入SQL Server时,如果用SQL Server的字符串类型(VARCHAR和NVARCHAR等)来存储从Excel导入的数字,有时候这些数字会变成科学记数法字符串(例如 ...

  2. 网络编程中用到的SOCKET是什么?

    摘取网络上的一些内容: 什么是TCP/IP.UDP? Socket在哪里呢? Socket是什么呢? 什么是TCP/IP.UDP? TCP/IP(Transmission Control Protoc ...

  3. 【转载】socket通信-C#实现tcp收发字符串文本数据

    在日常碰到的项目中,有些场景需要发送文本数据,也就是字符串,比如简单的聊天文字,JSON字符串等场景.那么如何如何使用SharpSocket来收发此类数据呢?其中要掌握的关键点是什么呢? 点击查看原博 ...

  4. python3.6安装pyinstaller报错:AttributeError: module 'enum' has no attribute 'IntFlag'

    转载至:https://blog.csdn.net/qq_41185868/article/details/80599336 感谢原作者的分享 解决思路:这可能是由包Enum34引起的.因为Pytho ...

  5. dm9000网卡 S3C2440

    配置U-Boot支持dm9000网卡 原理图 # vi drivers/net/Makefile obj-$(CONFIG_DRIVER_NET_CS8900) += cs8900.o obj-$(C ...

  6. Mac OS 查看端口和杀死进程

    查看sudo lsof -i:port (端口号) sudo lsof -i:9501 COMMAND PID USER FD TYPE DEVICESIZE/OFF NODE NAME php 77 ...

  7. 【Netty】Netty的Hello World程序之Discard Server

    一.有关Discard Server的说明 世界上最简单的协议(程序)不是“Hello, World!”而是Discard(丢弃).它是一种丢弃任何接收到的数据而没有任何响应的协议. 要实现丢弃协议, ...

  8. Markdown Mermaid

    Mermaid 是一个用于画流程图.状态图.时序图.甘特图的库,使用 JS 进行本地渲染,广泛集成于许多 Markdown 编辑器中. 之前用过 PlantUML,但是发现这个东西的实现原理是生成 U ...

  9. Httpd服务入门知识-Httpd服务常见配置案例之定义站点主页面及错误页面配置

    Httpd服务入门知识-Httpd服务常见配置案例之定义站点主页面及错误页面配置 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.定义站点主页面 [root@node101.yi ...

  10. Redis持久化 - RDB和AOF

    原文:https://segmentfault.com/a/1190000016021217 一.持久化的作用 1. 什么是持久化 持久化(Persistence),即把数据(如内存中的对象)保存到可 ...