是否可以在发布请求期间将 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
}
我猜答案可能是“否”,并且必须使用两个单独的模型,例如:
[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 相关问题,这帮助我理解主体必须反序列化为类对象,即使它只包含一个属性,就像我上面的示例一样。
上面示例的解决方案只是为要反序列化的主体创建一个新类,并将其添加到我的操作方法所需的主模型中。
[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; }
}
此外,如果您想将路由参数和正文内容映射到嵌套在同一对象内的不同对象,也可以这样做:
[Route("test")]
public class TestController : ControllerBase
{
[HttpPost("{value1FromRoute}/{value2FromRoute}/post")]
public IActionResult Post(Model model)
{
return new JsonResult(model);
}
}
public class Model
{
[FromBody]
public BodyModel BodyModel { get; set; }
[FromRoute, BindProperty(Name = "")]
public RouteModel RouteModel { get; set; }
}
public class RouteModel
{
public string Value1FromRoute { get; set; }
public string Value2FromRoute { get; set; }
}
public class BodyModel
{
public string ValueFromBody { get; set; }
}