ASP.NET Core如何禁用模型验证(或者从模型状态中移除某些属性)?
这是一篇4年前的文章:【经验分享】在ASP.NET Core中,如果禁用某个请求的模型验证?
事隔多年,又有网友问到这个问题。我就来重新整理一下,顺便扩展一下之前的解决办法。
=====
这是一个来自网友【David】的提问。在 AppBoxCore 项目的新增用户页面,新增一个上传按钮:
<f:FileUpload ID="filePhoto" ShowRedStar="false" ShowEmptyLabel="true" ButtonText="上传个人头像"
ButtonOnly="true" Required="false" ButtonIcon="ImageAdd"
OnFileSelected="@Url.Handler("filePhoto_FileSelected")"
OnFileSelectedFields="filePhoto">
</f:FileUpload>
后台代码:
public IActionResult OnPostFilePhoto_FileSelected(IFormFile filePhoto, IFormCollection values)
{
if (filePhoto != null)
{
string fileName = filePhoto.FileName; // 。。。
} return UIHelper.Result();
}
此时上传照片时,会弹出错误提示框(截图所示)。
The 用户名 field is required.
The 邮箱 field is required.
The 性别 field is required.
The 密码 field is required.

这是因为页面模型中定义了一个绑定属性:
[CheckPower(Name = "CoreUserNew")]
public class UserNewModel : BaseAdminModel
{
[BindProperty]
public User CurrentUser { get; set; } // ...
}
而在 POST 请求中会触发模型绑定,如果发现模型不完整就会报错。这个错误提示框是由 FineUICore 框架处理的,无需自己写代码。
现在问题就来了!
====================
对于上述场景,仅仅是上传图片而无需验证 CurrentUser 模型属性,该如何处理呢?
其实也很简单,只需要在处理器中清空模型状态就可:
public IActionResult OnPostFilePhoto_FileSelected(IFormFile filePhoto, IFormCollection values)
{
ModelState.Clear(); if (filePhoto != null)
{
string fileName = filePhoto.FileName; // 。。。
} return UIHelper.Result();
}
Done!
====================
这个问题也确实让我走了不少弯路,刚开始总想着如何禁用某些POST请求的模型验证,想着微软总能为处理器(Handler)提供一些注解(Annotation)来吧,结果查了一圈没有发现!
后来,想着换个思路:既然找不到禁用的方法,就清空模型状态,结果也是一样的。
延伸思考
============================
上面既然可以使用ModelState.Clear();清空所有的模型状态,那是否也可以移除模型状态中的某些属性呢?
以用户登录表单为例(用户名+密码),先看下模型定义:
namespace FineUICore.Examples.WebForms.Pages.DataModel.Models
{
public class User
{
[Required]
[Display(Name = "用户名")]
[StringLength(20)]
public string UserName { get; set; } [Required(ErrorMessage = "用户密码不能为空!", AllowEmptyStrings = true)]
[Display(Name = "密码")]
[MaxLength(9, ErrorMessage = "密码最大为 9 个字符!")]
[MinLength(3, ErrorMessage = "密码最小为 3 个字符!")]
[DataType(DataType.Password)]
[RegularExpression("^(?:[0-9]+[a-zA-Z]|[a-zA-Z]+[0-9])[a-zA-Z0-9]*$", ErrorMessage = "密码至少包含一个字母和数字!")]
public string Password { get; set; } }
}
页面模型中,定义一个名为 CurrentUser 的绑定属性:
[BindProperty]
public User CurrentUser { get; set; }
在页面视图中,将用户名和密码通过两个文本输入框渲染到页面中:
<f:Window Width="350" WindowPosition="GoldenSection" EnableClose="false" IsModal="false" Title="登录表单" ID="Window1">
<Items>
<f:SimpleForm ShowHeader="false" BodyPadding="10" ShowBorder="false" ID="SimpleForm1">
<Items>
<f:TextBox For="CurrentUser.UserName"></f:TextBox>
@* <f:TextBox For="CurrentUser.Password"></f:TextBox> *@
</Items>
</f:SimpleForm>
</Items>
<Toolbars>
<f:Toolbar Position="Bottom" ToolbarAlign="Right" ID="Toolbar1">
<Items>
<f:Button OnClick="btnLogin_Click" OnClickFields="SimpleForm1" ValidateTarget="Top" ValidateForms="SimpleForm1" Type="Submit" Text="登录" ID="btnLogin"></f:Button>
<f:Button Type="Reset" Text="重置" ID="btnReset"></f:Button>
</Items>
</f:Toolbar>
</Toolbars>
</f:Window>
注意,上述代码中我们注释掉了 CurrentUser.Password,以便在后台验证模型状态验证失败的情况。
此时提交表单,FineUICore会自动弹出模型验证失败的消息,如下图所示。

这个逻辑上是没有问题的,那个弹出框提示是FineUICore系统处理的(无需用户编码),看下事件处理函数:
public IActionResult OnPostBtnLogin_Click()
{
if (ModelState.IsValid)
{
if (CurrentUser.UserName == "admin" && CurrentUser.Password == "admin888")
{
ShowNotify("成功登录!", MessageBoxIcon.Success);
}
else
{
ShowNotify(String.Format("用户名({0})或密码({1})错误!",
CurrentUser.UserName,
CurrentUser.Password), MessageBoxIcon.Error);
}
} return UIHelper.Result();
}
为了从模型验证状态中移除某些属性,我们可以直接这么写:
public IActionResult OnPostBtnLogin_Click()
{
ModelState.Remove("CurrentUser.Password"); if (ModelState.IsValid)
{
...
} }
参考文章:https://stackoverflow.com/questions/16266988/exclude-fields-from-model-validation
上述文章指出,调用 ModelState.Remove() 方法虽然不够优雅,但是可以快速解决问题。更加优雅的做法是自定义一个单独的视图模型,示例代码:
public class PersonViewModel
{
[Required]
public String FirstName { get; set; } [Required]
public String LastName { get; set; }
} public class PersonWithEmailViewModel : PersonViewModel
{
[Required]
public String Email { get; set; }
}
ASP.NET Core如何禁用模型验证(或者从模型状态中移除某些属性)?的更多相关文章
- asp.net core 3.x 身份验证-3cookie身份验证原理
概述 上两篇(asp.net core 3.x 身份验证-1涉及到的概念.asp.net core 3.x 身份验证-2启动阶段的配置)介绍了身份验证相关概念以及启动阶段的配置,本篇以cookie身份 ...
- ASP.NET Core教程【二】从保存数据看Razor Page的特有属性与服务端验证
前文索引:ASP.NET Core教程[一]关于Razor Page的知识 在layout.cshtml文件中,我们可以看到如下代码: <a asp-page="/Index" ...
- asp.net core 3.x 身份验证-2启动阶段的配置
注册服务.配置选项.添加身份验证方案 在Startup.ConfigureServices执行services.AddAuthentication() 注册如下服务(便于理解省略了部分辅助服务): s ...
- ASP.NET Core 2 学习笔记(九)模型绑定
ASP.NET Core MVC的Model Binding会将HTTP Request数据,以映射的方式对应到参数中.基本上跟ASP.NET MVC差不多,但能Binding的来源更多了一些.本篇将 ...
- 基于ASP.NET Core Data Protection生成验证token
ASP.NET Core Data Protection 不仅提供了非对称加密能力,而且提供了灵活的秘钥存储方式以及一致的加解密接口(Protect与Unprotect).Session中用到了它,C ...
- asp.net core 3.x 身份验证-1涉及到的概念
前言 从本篇开始将围绕asp.net core身份验证写个小系列,希望你看完本系列后,脑子里对asp.net core的身份验证原理有个大致印象.至于身份验证是啥?与授权有啥联系?就不介绍了,太啰嗦. ...
- ASP.NET Core 一步步搭建个人网站(持续更新中~~~)
摘要 ASP.NET Core2.0发布有一阵子了,这是.NET 开源跨平台的一个重大里程碑, 也意味着比1.0版本要更加成熟.目前.net core具有开源.跨平台.灵活部署.模块化架构等等特性,吸 ...
- ASP.NET Core 6框架揭秘-实例演示版[持续更新中…]
作为<ASP.NET Core 3框架揭秘>的升级版,<ASP.NET Core 6框架揭秘>提供了很多新的章节,同时对现有的内容进行大量的修改.虽然本书旨在对ASP.NET ...
- 使用ASP.NET Core 3.x 构建 RESTful API - 3.3 状态码、错误/故障、ProblemDetails
HTTP状态码 HTTP状态码会告诉API的消费者以下事情: 请求是否执行成功了 如果请求失败了,那么谁为它负责 HTTP的状态码有很多,但是Web API不一定需要支持所有的状态码.HTTP状态码一 ...
- ASP.Net Core 5.0 MVC 配置文件读取,Startup 类中ConfigureServices 方法、Configure 方法的使用
配置文件读取 1. 新建FirstController控制器 在appsettings文件内容替换成以下代码 { "Position": { "Title": ...
随机推荐
- ubuntu环境下安装perf工具
检查当前环境内核的版本,执行如下命令: uname -a 输出信息如下: Linux jackie-ubuntu 5.4.0-26-generic #30-Ubuntu SMP Mon Apr 20 ...
- Git 安全远程访问:SSH 密钥对生成、添加和连接步骤解析
使用 SSH 密钥对的 Git 安全远程访问:生成.添加和连接 SSH(Secure Shell)是一种用于安全远程访问的协议,它提供了加密通信和身份验证机制.在使用 SSH 连接到远程 Git 存储 ...
- Python设计模式----4.构建者模式
构建者模式: 将一个复杂对象的构造与表现进行分离,利用多个步骤进行创建,同一个构建过程可用于创建多个不同的表现 构建者模式一般由 Director(指挥官)和 Builder(建设者)构成 class ...
- 美团一面,面试官让介绍AQS原理并手写一个同步器,直接凉了
写在开头 今天在牛客上看到了一个帖子,一个网友吐槽美团一面上来就让手撕同步器,没整出来,结果面试直接凉凉. 就此联想到一周前写的一篇关于AQS知识点解析的博文,当时也曾埋下伏笔说后面会根据AQS的原理 ...
- oracle database recover database (下篇)
1. recover database 恢复级别一共三个:recover database > recover tablespace > recover datafile ,最高级别 da ...
- BI 和报表有什么区别
BI 从早期提出的概念上来划分可以分为数据仓库.ETL.olap 和报表这几部分可以看到报表只是 BI 中的一个组成部分,只不过数据在 web 端展示时通常是通过报表形式,所以经常会把报表当做是 BI ...
- 重新整理数据结构与算法(c#)——算法套佛洛伊德算法[三十二]
前言 佛洛伊德算法和迪杰斯特拉算法非常像,但是它求的是任何一个点到其他点之间的距离. 假设有一张图: 转换为矩阵为: 他们的前驱为: 可能上面表述前驱不清楚,举个例子. 看下图: 这第二种图表示,从A ...
- 第四章:if else switch使用
/* * @Issue: 输入整数a和b,若a²+b²大于100,则输出a²+b²之和的百位以上的数字,否则直接输出a²+b²的和 * @Author: 一届书生 * @LastEditTime : ...
- k8s架构与原理介绍
K8s概述 目录 K8s概述 1.什么是K8s 2.K8s 设计架构 3. k8s重要节点描述 4. 过程原理: 5. k8s的核心功能 6. k8s的历史 7. k8s的安装方式 8. k8s的应用 ...
- DTCC 2020 | 阿里云赵殿奎:PolarDB的Oracle平滑迁移之路
简介: Oracle兼容性是业务客户从Oracle生态迁移到PolarDB生态的第一步也是至关重要的一步,PolarDB通过不断沉淀支持大量实际业务的真实Oracle兼容性功能,确保客户业务可以真正做 ...