我正在使用 aspnet core 开发 WebApi。我已经能够设置一个基本项目并且获取请求运行良好。
现在我正在尝试使用 postman 将复杂的 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; }
}
尝试用 postman 进行相同的测试。
请求 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 方法中接受它们作为单独的参数吗?
请您参考如下方法:
另一种发布多个对象的解决方案是使用 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;
}
}
Action 将是:
public IActionResult Action1(
[FromForm][ModelBinder(BinderType = typeof(FormDataJsonBinder))] TokenRequest request,
[FromForm][ModelBinder(BinderType = typeof(FormDataJsonBinder))] TokenRequest request1)
{
return Ok();
}
虽然我会选择包装类选项。