在开启 Nullable 可空类型之后,原本可以调用的 API 也许就会提示 400 BadRequest 因为传入参数不合法,模型校验失败,此时将不会进入预期的 API 函数,同时也不会在输出里面找到有用的信息

在 SDK 风格的 csproj 文件开启可空类型可以添加下面代码

<Nullable>enable</Nullable>
为了方便让小伙伴知道上面代码加在哪里,我贴出更多的 csproj 文件代码

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
在开启之后,原本工作的很好的 API 也许在客户端调用的时候,将会提示 400 BadRequest 内容大概如下

{
"type":"https://tools.ietf.org/html/rfc7231#p-6.5.1",
"title":"One or more validation errors occurred.",
"status":400,
"traceId":"00-99b1c07693a55c4990389901832992a4-b2ed63ee45e85344-01",
"errors":
{
"Account":
[
"The Account field is required."
]
}
}
复习一下为什么会存在 400 错误

也许调用的 API 错误了,本来是预期调用 Foo 的,但却调用了 A 接口
也许调用的端口不对,也许是被 Fiddler 干扰了
也许是传入的参数不合法
如上面提示,实际内容是 The Account field is required 翻译过来就是接口里面的参数,要求一定存在 Account 属性

而明明之前工作的好好的,接口实现如下

[HttpPost]
// ReSharper disable once StringLiteralTypo
[Route("/lindexi/doubi")]
[RequestSizeLimit(100_000_000)]
public async Task<string> PostFile([FromForm] LindexiUploadFileRequest request)
也就是需要通过 FromForm 拿到内容,而 LindexiUploadFileRequest 的定义如下

[DataContract]
public class LindexiUploadFileRequest
{
[DataMember(Name = "file")]
[JsonPropertyName("file")]
public IFormFile File { get; set; }

[DataMember(Name = "account")]
[JsonPropertyName("account")]
public string Account { get; set; }
}
客户端调用代码大概如下

public async Task<string> Upload(string host, string file)
{
var multipartFormDataContent = new MultipartFormDataContent();
var fileName = Path.GetFileName(file);

var stringContent = new StringContent(fileName);
multipartFormDataContent.Add(stringContent, "Name");

using var fileStream = new FileStream(file, FileMode.Open);
using var streamContent = new StreamContent(fileStream);
multipartFormDataContent.Add(streamContent, "File", fileName);

var account = "";

multipartFormDataContent.Add(new StringContent(account), "Account");

var httpClient = new HttpClient();
var url = $"{host}/lindexi/doubi";

var response = await httpClient.PostAsync(url, multipartFormDataContent).ConfigureAwait(false);
var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
return $"{response.StatusCode}\n{content}";
}

小伙伴是否可以看出问题?实际上在开启可空之后,尽管在客户端代码里面设置了 multipartFormDataContent.Add(new StringContent(account), "Account"); 但是传入的内容是空字符串

而开启可空之后,定义的数据模型 public string Account { get; set; } 表示 Account 一定不是空,于是传入空的 Account 属性将会校验不通过

有两个解决方法,第一个解决方法就是标记 Account 属性可空

[DataMember(Name = "account")]
[JsonPropertyName("account")]
public string? Account { get; set; }
但是对于大项目,很难测试全,此时可以在全局配置,让行为和之前相同

services.AddControllers(options => options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true);
打开 Startup.cs 文件,在 ConfigureServices 函数添加上面代码即可

但对于 EF 这边,有更多的变更,详细请看 Working with nullable reference types - EF Core

因此如果是新项目,我推荐开启可空,而对于现有的项目,我不推荐打开

MvcOptions.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes Property (Microsoft.AspNetCore.Mvc)

Nullable=Enabled results in required validation errors for parameters or bound properties with default values · Issue #18403 · dotnet/aspnetcore

ASP.NET Core 警惕可空类型开启之后模型校验失败的更多相关文章

  1. 008.Adding a model to an ASP.NET Core MVC app --【在 asp.net core mvc 中添加一个model (模型)】

    Adding a model to an ASP.NET Core MVC app在 asp.net core mvc 中添加一个model (模型)2017-3-30 8 分钟阅读时长 本文内容1. ...

  2. ASP.NET Core WebAPI控制器返回类型的最佳选项

    前言 从.NET Core 2.1版开始,到目前为止,控制器操作可以返回三种类型的WebApi响应.这三种类型都有自己的优点和缺点,但都缺乏满足REST和高可测性的选项. ASP.NET Core中可 ...

  3. ASP.NET Core 2 学习笔记(九)模型绑定

    ASP.NET Core MVC的Model Binding会将HTTP Request数据,以映射的方式对应到参数中.基本上跟ASP.NET MVC差不多,但能Binding的来源更多了一些.本篇将 ...

  4. ASP.NET Core会议管理平台实战_4、参数校验、操作结果封装,注册参数配置

    登陆和注册之前,需要封装 前端参数的校验,ajax的封装 参数校验,创建公共的类 ,它是一个静态类 这样在调用的时候,直接一句话就可以了,这就是封装的好处 空字符串的校验 调用方式 EF的源码里面有这 ...

  5. 1.ASP.NET Core 中向 Razor Pages 应用添加模型

    右键单击“RazorPagesMovie”项目 >“添加” > “新建文件夹”. 将文件夹命名为“Models”.右键单击“Models”文件夹. 选择“添加” > “类”. 将类命 ...

  6. ASP.NET Core:使用Dapper和SwaggerUI来丰富你的系统框架

    一.概述 1.用VS2017创建如下图的几个.NET Standard类库,默认版本为1.4,你可以通过项目属性进行修改,最高支持到1.6,大概五月份左右会更新至2.0,API会翻倍,很期待! 排名分 ...

  7. ASP.NET Core的配置(4):多样性的配置来源[上篇]

    较之传统通过App.config和Web.config这两个XML文件承载的配置系统,ASP.NET Core采用的这个全新的配置模型的最大一个优势就是针对多种不同配置源的支持.我们可以将内存变量.命 ...

  8. C# -- HttpWebRequest 和 HttpWebResponse 的使用 C#编写扫雷游戏 使用IIS调试ASP.NET网站程序 WCF入门教程 ASP.Net Core开发(踩坑)指南 ASP.Net Core Razor+AdminLTE 小试牛刀 webservice创建、部署和调用 .net接收post请求并把数据转为字典格式

    C# -- HttpWebRequest 和 HttpWebResponse 的使用 C# -- HttpWebRequest 和 HttpWebResponse 的使用 结合使用HttpWebReq ...

  9. (9)ASP.NET Core 中的MVC路由二

    1.URL生成 MVC应用程序可以使用路由的URL生成功能,生成指向操作(Action)的URL链接. IUrlHelper 接口用于生成URL,是MVC与路由之间的基础部分.在控制器.视图和视图组件 ...

  10. [ASP.NET Core 3框架揭秘] Options[1]: 配置选项的正确使用方式[上篇]

    依赖注入不仅是支撑整个ASP.NET Core框架的基石,也是开发ASP.NET Core应用采用的基本编程模式,所以依赖注入十分重要.依赖注入使我们可以将依赖的功能定义成服务,最终以一种松耦合的形式 ...

随机推荐

  1. FastAPI权限验证依赖项究竟藏着什么秘密?

    title: FastAPI权限验证依赖项究竟藏着什么秘密? date: 2025/06/12 06:53:53 updated: 2025/06/12 06:53:53 author: cmdrag ...

  2. 阿里云javascript分片上传失败的解决办法

    前端项目:React + Antd mobile + 阿里云OSS Node.js SDK实现文件上传. 在电脑上运行良好,放到手机上大文件就上传失败. 打开Chrome,地址栏输入`chrome:/ ...

  3. HyperWorks实体网格划分

    实体网格剖分 在 HyperMesh 中,使用 Solid Map 功能进行实体网格剖分.该面板如下图所示: 图 4-4 Solid Map 面板 Ø 通过 Solid Map Panel 进行实体网 ...

  4. PowerShell执行命令提示找不到驱动器。名为“xx”的驱动器不存在。

    前言 问题截图 1. VSCode中提示错误 2. PowerShell中提示错误,任何命令都提示此错误(排程变量命令) 网上的解决方案 1. VSCode中提示,修改相关VSCode首选项设置 2. ...

  5. PHP汉字转换拼音的类

    1 网络上类似的代码大多只能在gb2312编码下使用,下面这个类同时能在utf-8编码下将汉字转换为拼音,具体的代码和用法如下: 2 <?php 3 function Pinyin($_Stri ...

  6. FFmpeg开发笔记(七十)Windows给FFmpeg集成AV1编码器libsvtav1

    ​AV1是一种新兴的免费视频编码标准,它由开放媒体联盟(Alliance for Open Media,简称AOM)于2018年制定,融合了Google VP10.Mozilla Daala以及Cis ...

  7. Blazor学习之旅(7)布局

    大家好,我是Edison. 本篇,我们来了解下在Blazor中的布局. 什么是布局 Blazor 中的布局可以让我们编写的页面具有相同的导航菜单和页头页脚部分,提高通用代码的复用性,通过一次性的编写通 ...

  8. MongoDB入门实战教程(13)

    MongoDB的一大特色就在于其原生的横向扩展能力,具体体现就是分片集.本篇,我们来了解一下MongoDB分片集的机制及其原理. 1 为什么要分片? 我们都知道,在关系型数据库如MySQL中,当数据量 ...

  9. 新人如何入门学习 STM32?

    作为一个在嵌入式领域摸爬滚打了近10年的老兵,看到这个问题时我的思绪瞬间回到了当年那个懵懂的自己.说实话,2014年那个夏天,24岁的我刚从机械专业毕业却被调剂到了厦门某马的电子部门,第一次听到&qu ...

  10. VLFeat库实现KD-Tree算法

    VLFeat库实现KD-Tree算法 K-D树(K-Dimensional Tree,即K维二叉树),K=1时,即是一棵普通的二叉树.常被用于高维空间中的搜索,比如范围搜索和最近邻搜索.考虑这样一种情 ...