根据 post 请求将路由和正文值绑定到同一模型

Bind route and body values to same model on post request

是否可以在 post 请求期间将 URL 路由和主体的值绑定到同一模型?

例如:

[Route("test")]
public class TestController : ControllerBase
{
    [HttpPost("{valueFromRoute}/post")]
    public IActionResult Post(Model model)
    {
        return new JsonResult(model);
    }
}

public class Model
{
    [FromRoute]
    public string ValueFromRoute { get; set; }

    [FromBody]
    public string ValueFromBody { get; set; }
}

我想按如下方式调用此端点:

但是使用此代码,只有 ValueFromRoute 被填充:

{
    "valueFromRoute": "some-route-value",
    "valueFromBody": null
}

我猜答案可能是 "no",并且必须使用两个单独的模型,例如:

[Route("test")]
public class TestController : ControllerBase
{
    [HttpPost("{valueFromRoute}/post")]
    public IActionResult Post([FromRoute] RouteModel routeModel, [FromBody] BodyModel bodyModel)
    {
        return new JsonResult(new 
        { 
            ValueFromRoute = routeModel.ValueFromRoute, 
            ValueFromBody = bodyModel.ValueFromBody
        });
    }
}

public class RouteModel
{
    public string ValueFromRoute { get; set; }
}

public class BodyModel 
{
    public string ValueFromBody { get; set; }
}

以与上面屏幕截图完全相同的方式调用它,按预期工作,将两个值填充到各自的对象上,并输出以下内容:

{
    "valueFromRoute": "some-route-value",
    "valueFromBody": "Some value from body"
}

所以我有一个潜在的解决方案,但它不是我的首选解决方案。理想情况下,如果可能的话,我想将路由和主体值绑定到同一个模型。

我在 GitHub 上找到了 this related question,这帮助我理解了正文必须反序列化为一个 class 对象,即使它只包含一个 属性,就像我上面的例子。

我上面示例的解决方案只是为要反序列化的主体创建一个新的 class,并将其添加到我的操作方法所期望的主模型中。

[Route("test")]
public class TestController : ControllerBase
{
    [HttpPost("{valueFromRoute}/post")]
    public IActionResult Post(Model model)
    {
        return new JsonResult(model);
    }
}

public class Model
{
    [FromRoute]
    public string ValueFromRoute { get; set; }

    // Map body to simple class object rather than a primitive type
    [FromBody]
    public BodyModel BodyModel { get; set; }
}

public class BodyModel 
{
    public string ValueFromBody { get; set; }
}