由于 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. 2019 贝壳找房java面试笔试题 (含面试题解析)

      本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.贝壳找房等公司offer,岗位是Java后端开发,因为发展原因最终选择去了贝壳找房,入职一年时间了,也成为了面 ...

  2. npm err! Unexpected end of JSON input while parsing near解决办法

    npm install时出现npm err! Unexpected end of JSON input while parsing near错误 输入  npm cache clean --fore ...

  3. jquery问题,如何调用带this的函数?

    这样写: 1 2 3 4 5 6 7 8 9 10 11 12 $(".aa").on("mouseout",function(){     var obj = ...

  4. CSS 精灵技术(sprite)

    一.精灵技术产生的背景 图所示为网页的请求原理图,当用户访问一个网站时,需要向服务器发送请求,网页上的每张图像都要经过一次请求才能展现给用户.  然而,一个网页中往往会应用很多小的背景图像作为修饰,当 ...

  5. python小项目之文本编辑器

    高考完后这么久才想起这系列教程,实在抱歉,现在该来继续教程了. 本节利用前面所学知识,来完成一个小工具--文本编辑器! tkinter 在实现文本编辑器之前,先来了解下tkinter这个python库 ...

  6. Spring Cloud Sleuth 整合

    引入Maven依赖 org.springframework.cloud spring-cloud-starter-sleuth 日志发生的变化 当应用ClassPath下存在org.springfre ...

  7. PostgreSQL 基本数据类型及常用SQL 函数操作

    数据类型 名字 别名 描述 bigint int8 有符号的8字节整数 bigserial serial8 自动增长的8字节整数 bit [ (n) ]   定长位串 bit varying [ (n ...

  8. Linux基础:时间同步工具Chrony

    在Linux下,默认情况下,系统时间和硬件时间,并不会自动同步.在Linux运行过程中,系统时间和硬件时间以异步的方式运行,互不干扰.硬件时间的运行,是靠Bios电池来维持,而系统时间,是用CPU t ...

  9. prometheus学习系列八: Prometheus Grafana展示平台

    在prometheus中,我们可以使用web页面进行数据的查询和展示, 不过展示效果不太理想,这里使用一款专业的展示平台进行展示. grafana安装 # 下载wget https://dl.graf ...

  10. php中的闭包类

    看注释 <?php //闭包类实现匿名函数 //call方法调用 class Customer { private $firstname; private $lastname; public f ...