【问题标题】:Custom Model binding mixing Route and Body data自定义模型绑定混合 Route 和 Body 数据
【发布时间】:2020-02-14 03:57:55
【问题描述】:

我有一个具有 3 个属性的模型,我想使用 ASP.NET Core 进行绑定和验证。从这 3 个属性中,2 个应该从 POSTed JSON 正文绑定,第三个应该从路由参数绑定:

public class CustomModel
{
    public string Id_Model { get; set; } //Bind it from RouteData
    public string Value { get; set; } //Bind it from Body
    public string Type { get; set; } //Bind it from Body
}

[Route("[controller]")]
public CustomController : ControllerBase
{
    [HttpPost("{Id_Model}")]
    public IActionResult Post(CustomModel model)
    {
        return Ok();
    }
}

问题也是我不想在模型本身上添加任何属性(它将在另一个程序集中声明,并且我不希望在此程序集中来自 Microsoft.AspNetCore 的依赖项)。

我尝试创建一个 CustomModelBinder,但我只能使用来自 bindingContext.ValueProvider 的 Route 数据,而且我不知道如何获取 Body/Json 数据。

我尝试使用FormValueProviderFactory,并用new ValueProviderFactoryContext(bindingContext.ActionContext) 实例化一个,但结果提供者始终是null

知道如何进行这种混合绑定吗?

【问题讨论】:

  • 如果你发现你需要使用绑定属性,你总是可以派生一个类和/或使用适配器模式。

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


【解决方案1】:

我尝试创建一个 CustomModelBinder,但我只能使用 bindingContext.ValueProvider 提供的路由数据,而且我不知道如何获取 Body/Json 数据。

您可以在自定义模型绑定器中读取请求正文:

public class testDtoEntityBinder : IModelBinder
    {
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
            {
                throw new ArgumentNullException(nameof(bindingContext));
            }

            bindingContext.HttpContext.Request.EnableBuffering();
            var body = bindingContext.HttpContext.Request.Body;
            body.Position = 0;


            string raw = new System.IO.StreamReader(body).ReadToEnd();

            //now read content from request content and fill your model 
            var result = new testDto
            {
                A = "",
                B = 1,
            };


            bindingContext.Result = ModelBindingResult.Success(result);
            return Task.CompletedTask;
        }
    }

在您的模型上使用如下:

[ModelBinder(BinderType = typeof(testDtoEntityBinder))]

您也可以从bindingContext.HttpContext.Request获取路线数据。

【讨论】:

    【解决方案2】:

    我不确定你是不是这个意思:

    [HttpPost("{Id_Model}")]
    public IActionResult Post([FromBody] CustomModel model, string Id_Model)
    {
        model.Id_Model = Id_Model;
    
        // rest of the code as you wish
    
        return Ok(model);
    }
    

    因此,您可以在将以下内容 POST 到此端点时捕获它:http://localhost:63676/Custom/100

    希望这会有所帮助。

    【讨论】:

    • 差不多了,但我想使用IValidatableObject 中的模型验证,包含在[ApiControllerAttribute] 中,而CustomModel 的验证需要设置Id_Model。这就是为什么我想在执行 Action 之前绑定它。
    • 你会发现这个帖子很有用:stackoverflow.com/questions/50481226/…
    • 这很有用,但模型验证仍然发生在执行操作本身之前(有或没有[ApiControllerAttribute],所以即使我手动设置了Id_Model,ModelState 也将是false .
    猜你喜欢
    • 1970-01-01
    • 2018-10-13
    • 1970-01-01
    • 2011-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-08
    • 1970-01-01
    相关资源
    最近更新 更多