我正在使用 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(); 
} 

虽然我会选择包装类选项。


评论关闭
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!