首页 > 解决方案 > 核心 3.1 - 绑定 Body 中的一些属性和 Header 中的其他一些属性

问题描述

我有以下模型:

public class Network {
    public string Network { get; set; }
    public string Cidr { get; set; }
    public string TenantId { get; set; }
}

以及以下端点:

public async Task<ActionResult<Network>> PostNetwork(Network network)
{
    ...
}

并且想知道是否可以绑定NetworkandCidr与我的帖子中的值Body,以及TenantId与来自特定标题的值。

我不想把entity.TenantId = HttpContext.Request.Headers["TenantId"];所有的控制器端点都放在我的控制器端点上,因为这种模式对于多个实体/端点是必需的。

我试图创建一个自定义中间件来编辑我的 Body 内容,但这些更改没有反映在我的控制器中。还尝试使用自定义 DataBinder 但没有成功。

标签: c#.netasp.net-core.net-core

解决方案


因此,您需要创建一个自定义模型绑定器并向您的类添加一个属性。

模型绑定器将继承IModelBinder并假设您的数据是 JSON

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

        Network model;

        string bodyAsText = await new StreamReader(bindingContext.HttpContext.Request.Body).ReadToEndAsync();
        model = JsonConvert.DeserializeObject<Network>(bodyAsText);
        model.TenantId = bindingContext.HttpContext.Request.Headers["TenantId"];
        bindingContext.Result = ModelBindingResult.Success(model);
    }
}

然后将ModelBinder属性添加到类中以告诉它使用该模型绑定器

[ModelBinder(typeof(NetworkModelBinder))]
public class Network
{
    public string Network { get; set; }
    public string Cidr { get; set; }
    public string TenantId { get; set; }
}

推荐阅读