【问题标题】:Alternate Model Binding On Controllers Post Action控制器后操作中的备用模型绑定
【发布时间】:2021-10-14 16:14:10
【问题描述】:

EDIT: 您可以安全地克隆https://github.com/vslzl/68737969 并运行该示例。如果你发送

{
    "intPropB":3
}

作为 POST 正文发送到:http://localhost:5000/api/Test

您会看到它清楚地将 B 对象绑定到 A 对象。

#EDIT END

我想使用asp.net core 5 实现替代模型绑定正如您将在下面看到的,我有两个替代类可以在单个端点上绑定。每个请求只能包含一个有效的 A 模型或 B 模型,并且 A 和 B 具有不同的属性。

    [HttpPost(Name = Add)]
    public async Task<IActionResult> AddAsync(CancellationToken ct)
    {
        var aModel= new A();
        var bModel= new B();
        if (await TryUpdateModelAsync<A>(aModel))
        {
            _logger.LogDebug($"Model binded to A");
            return Ok(aModel);
        }
        else if (await TryUpdateModelAsync<B>(bModel))
        {
            _logger.LogDebug($"Model binded to B");
            return Ok(bModel);
        }
        _logger.LogDebug("Nothing binded!");
        return BadRequest();
    }

但是这种方法失败了。有没有合适的方法来实施这种解决方案?

顺便说一下,我使用它来降低端点的复杂性,我想部分更新一条记录,通过这样做,每个模型将映射相同的记录但具有不同的逻辑。

任何建议将不胜感激。谢谢。

【问题讨论】:

  • 请提供一个最低限度的工作示例。 stackoverflow.com/help/minimal-reproducible-example
  • @abdusco 给你,真的很简单。
  • 嗨@vslzl,您的代码与您的帖子数据无关。 TryUpdateModelAsy 只是将新实例绑定到默认值,它不会使用您的发布数据更新到模型。并且这里从未使用过 CancellationToken。
  • @Rena 是的,实际上官方文档说 TryUpdateModelAsync 不适合在使用 JSON 的 API 端点中使用它,它旨在与 formdata 一起使用。但我在问并想展示我想要获得的东西。实际项目中也会用到取消令牌,这只是一个演示。如果您能提供任何建议,那就太好了。
  • 我还通过生成一个包含 A 对象和 B 对象作为属性的模型并稍微重新设计了发布数据来解决了这个问题。但这个解决方案对我来说似乎很幼稚。我认为应该有更合适的解决方案。

标签: asp.net-core asp.net-core-mvc model-binding


【解决方案1】:

无法提供优雅的方式来做到这一点,但这是我迄今为止所做的,它有效,但在我看来有点难看。

我把action方法改成这样了:

[HttpPost(Name = Add)]
[AllowAnonymous]
public IActionResult AddSync([FromBody] JObject body)
{  
    var aModel = JsonConvert.DeserializeObject<A>(body.ToString());
    var bModel = JsonConvert.DeserializeObject<B>(body.ToString());
    
    ModelState.Clear();
    var aValid = TryValidateModel(aModel);


    ModelState.Clear();
    var bValid = TryValidateModel(bModel);           

    // some logic here...
    return Ok(new {aModel,bModel, aValid, bValid });
}

我认为以这种方式干扰 ModelState 不是一个好主意。

但这就是我所做的,

  1. 获取请求的原始正文为JObject(需要Newtonsoft.Json 包)
  2. 将该 json 值解析为候选对象
  3. 通过 modelstate 检查它们的有效性并决定使用哪一个。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-07
    • 2013-07-20
    相关资源
    最近更新 更多