将 JSON 数据发布到 Dotnet Core webapi
Posted
技术标签:
【中文标题】将 JSON 数据发布到 Dotnet Core webapi【英文标题】:Post JSON data to Dotnet Core webapi 【发布时间】:2019-01-30 04:32:46 【问题描述】:我正在使用 aspnet 核心开发一个 WebApi。我已经能够设置一个基本项目并且请求运行良好。
现在我正在尝试使用邮递员将复杂的 JSON 对象发布到 API。 API 代码如下:
//controller class
public class DemoController : ControllerBase
[HttpPost]
public IActionResult Action1([FromBody]TokenRequest request)
/* This works. I get request object with properties populated */
[HttpPost]
public IActionResult Action2(TokenRequest request)
/* The request is received. But properties are null */
//TokenRequest Class
public class TokenRequest
public string Username get; set;
public string Password get; set;
试图用邮递员进行测试。
请求 1:(Action1 和 Action2 均失败)
POST /Demo/Action2 HTTP/1.1
Host: localhost:5001
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 42642430-bbd3-49ca-a56c-cb3f5f2177cc
"request":
"Username": "saurabh",
"Password": "******"
请求 2:(Action1 成功,Action2 失败)
POST /User/Register HTTP/1.1
Host: localhost:5001
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 94141e01-7fef-4847-953e-a9acb4e6c445
"Username": "saurabh",
"Password": "******"
由于 [FromBody[ 标记,这些东西与 Action1 一起工作。但是如果我需要接受多个参数呢?喜欢
public IActionResult Action1(int param1, TokenRequest request)
选项 1:使用包装类(由 Francisco Goldenstein 建议)
[FromBody] 不能与两个不同的参数一起使用。有什么优雅的解决方案可以让我接受它们作为 Action 方法中的单独参数吗?
【问题讨论】:
param1 在哪里?查询参数? 我们也可以说它在正文中。 【参考方案1】:另一种发布多个对象的解决方案是使用 Form 并将每个 json 对象发布在表单的分隔字段中。将JsonBinder
应用到它,我们可以像[FromBody]
一样在参数中使用模型。
public class FormDataJsonBinder : IModelBinder
public Task BindModelAsync(ModelBindingContext bindingContext)
if (bindingContext == null) throw new ArgumentNullException(nameof(bindingContext));
// Fetch the value of the argument by name and set it to the model state
string fieldName = bindingContext.FieldName;
var valueProviderResult = bindingContext.ValueProvider.GetValue(fieldName);
if (valueProviderResult == ValueProviderResult.None) return Task.CompletedTask;
else bindingContext.ModelState.SetModelValue(fieldName, valueProviderResult);
// Do nothing if the value is null or empty
string value = valueProviderResult.FirstValue;
if (string.IsNullOrEmpty(value)) return Task.CompletedTask;
try
// Deserialize the provided value and set the binding result
object result = JsonConvert.DeserializeObject(value, bindingContext.ModelType);
bindingContext.Result = ModelBindingResult.Success(result);
catch (JsonException)
bindingContext.Result = ModelBindingResult.Failed();
return Task.CompletedTask;
动作将是:
public IActionResult Action1(
[FromForm][ModelBinder(BinderType = typeof(FormDataJsonBinder))] TokenRequest request,
[FromForm][ModelBinder(BinderType = typeof(FormDataJsonBinder))] TokenRequest request1)
return Ok();
虽然我会选择包装类选项。
【讨论】:
这可能有效,但解决简单问题相当复杂。 感谢您,我需要在隐藏的输入字段(由 angularjs 作为组件生成)中发布复杂的 JSON 作为整体表单提交的一部分,并且不想将其作为字符串接收然后该操作在控制器中反序列化它。【参考方案2】:如果在 JSON 文档中传递 param1,则必须在 TokenRequest 类中定义 param1。你得到的错误已经是这个意思了。
您不必在 JSON 文档中传递 param1。您可以通过 Query params OR Http headers
传递 param1我更喜欢将 param1 作为查询参数传递。
POST /User/Register?param1=Param1
POST /User/Register?param1=Param1 HTTP/1.1
Host: localhost:5001
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 94141e01-7fef-4847-953e-a9acb4e6c445
"Username": "saurabh",
"Password": "******"
与
public IActionResult Action1([FromQuery] int param1, [FromBody] TokenRequest request)
【讨论】:
看起来不错。我们可以在 Header 或 body 以外的其他地方有复杂的 JSON 对象吗?本例中的示例 TokenRequest。【参考方案3】:如果您需要接受更多参数,则需要创建另一个包含您需要的所有内容的类。一个包装类,像这样:
public class X
public TokenRequest TokenRequest get; set;
public int Param1 get; set;
控制器的动作是这样的:
[HttpPost] 公共 IActionResult Action1([FromBody]X 请求) // 你的代码
在 ASP.NET Core 中,您需要指出请求的值是否是正文、表单等的一部分。这与 ASP.NET MVC 的工作方式不同,其中每个部分(正文、表单等)被考虑。
附注:
您还可以考虑使用继承,定义一个从 TokenRequest 继承的新类,但这不是一个好习惯,因为新类型不尊重“是 TokenRequest”。最好说“有一个TokenRequest”。
【讨论】:
这是我的第一个想法。但是是否有可能在没有包装类的情况下处理这种情况? 不,这行不通。你需要包装器。我知道这是更多的课程,但在我看来它更干净。 好的。明天将在这方面尝试更多的东西。希望有别的办法。并感谢您的回答。如果我在一两天内找不到/锻炼任何其他解决方案,我将继续使用这个。 一个月前我将一个大型应用程序从 ASP.NET MVC 迁移到 ASP.NET Core MVC,所以我知道您面临什么。我希望微软写了一个迁移指南。昨天我不得不使用 ASP.NET MVC 编写一个 API 以继续使用没有 Core 版本的 PDF 库。祝你好运! 是的,即使我已经习惯了 ASP.NET MVC。新到核心。我想我需要更多地了解 http 的工作原理。以上是关于将 JSON 数据发布到 Dotnet Core webapi的主要内容,如果未能解决你的问题,请参考以下文章
Dotnet Core 3.1:如何将 AddJsonFile 与文件的绝对路径一起使用?
dotnet core 5 Webapi 向 HTTPPOST 发送 Json 响应
dotnet core 不包括在launchSettings.json 中构建的测试项目
在 Visual Studio 16.6 中将仅内容包导入 DotNet Core 3.1 项目