我可以添加具有向后兼容性的 [FromBody] 参数吗?

Posted

技术标签:

【中文标题】我可以添加具有向后兼容性的 [FromBody] 参数吗?【英文标题】:Can I add [FromBody] parameter with backward compatibility? 【发布时间】:2020-06-02 10:11:30 【问题描述】:

我有没有 [FromBody] 参数的端点:

    [HttpPost("id:int/publish")]
    public async Task<IActionResult> Publish()
    
        <do some stuff>
        return Ok();
    

但是现在我需要添加 [FromBody] 参数,使旧代码仍然能够在没有参数的情况下使用此端点:

    [HttpPost("id:int/publish")]
    public async Task<IActionResult> Publish([FromBody] PublishRequest request)
    
        <do some stuff>
        return Ok();
    

但如果我以这种方式添加它并尝试用空主体调用此端点,我会得到 415 (Unsupported Media Type) 响应。

我想让这个更改向后兼容。因此,应该可以在没有请求正文和内容类型标头的情况下使用此端点。有可能吗?

【问题讨论】:

只是好奇:ID参数去哪了?你是如何在你的中提到它的?我会在方法签名上期待它。 ATM 似乎不支持可选的FromBody 参数,但似乎在this github 问题中发布了解决方法。 您的问题看起来很像这样:***.com/questions/44538772/…您的解决方案是否允许使用 [FromForm] 而不是 [FromBody]? @GuruStron,这正是我所需要的!您可以发表您的评论作为答案,我会投赞成票! @ant 很高兴它有帮助!添加为答案。 【参考方案1】:

ATM 似乎不支持可选的FromBody 参数,但在这个github 问题中发布了一个可能的解决方法:

public class SomeClassModelBinder : IModelBinder

    public async Task BindModelAsync(ModelBindingContext bindingContext)
    
        var stream = bindingContext.HttpContext.Request.Body;
        string body;
        using (var reader = new StreamReader(stream))
        
            body = await reader.ReadToEndAsync();
        
        var someClass = JsonConvert.DeserializeObject<SomeClass>(body);

        bindingContext.Result = ModelBindingResult.Success(someClass);
    


[FromBody, ModelBinder(BinderType = typeof(SomeClassModelBinder))] SomeClass request,

【讨论】:

【参考方案2】:

您可以将 PublishRequest 设为可选。

[HttpPost("id:int/publish")]
public async Task<IActionResult> Publish([FromBody] PublishRequest? request)

    // <do some stuff>
    return Ok();

【讨论】:

以上是关于我可以添加具有向后兼容性的 [FromBody] 参数吗?的主要内容,如果未能解决你的问题,请参考以下文章

具有向后兼容性的数据快照维护和开发

MediaSession 和 MediaSessionManager 是不是具有向后兼容性?

UIRefreshControl 向后兼容

EF 自动迁移向后兼容

WCF 向后兼容性问题

ConstraintLayout,子视图的提升和向后兼容性