首页 > 解决方案 > 自定义模型绑定 - ASP.NET Core

问题描述

我有这个带有这个有效载荷的传入请求

{
    count : 10,
    supplier : {
        id : 342,
        name : 'test'
    },
    title : 'some title'
}

我的 C# 代码中有这个模型

class SomeModel 
{
    public string Title { get; set; } 
    public int SupplierId { get; set; }
    public double Amount { get; set; }
}

这是我的控制器方法

public IActionResult Foo(SomeModel data) 
{
    //...
}

我想将count请求有效负载中的Amount属性映射到我的 c# 模型中的属性并将值映射supplier.idSupplierId.

我正在使用 Newtonsoft Json.NET 库进行绑定

标签: c#asp.net-core

解决方案


显然,最简单的方法是像这样创建一个与有效载荷结构相对应的类

public class SomeModel
{
    public string Title { get; set; }

    public double Count { get; set; }

    public Supplier Supplier { get; set; }
}

public class Supplier
{
    public int Id { get; set; }

    public string Name { get; set; }
}

另一个迭代可能是使用JsonProperty属性 forAmountSupplierId属性利用Supplier

class SomeModel
{
    public string Title { get; set; }

    [JsonProperty("count")]
    public double Amount { get; set; }

    public int SupplierId => Supplier.Id;

    public Supplier Supplier { get; set; }
}

class Supplier
{
    public int Id { get; set; }

    public string Name { get; set; }
}

但是,如果您想坚持使用当前模型,则需要创建一个自定义转换器。我能建议你什么

public class NestedPropertyConverter : JsonConverter
{
    private string[] _properties;

    public NestedPropertyConverter(string propertyChain)
    {
        //todo: check if property chain has valid structure
        _properties = propertyChain.Split('.');
    }

    public override bool CanWrite => false;

    public override bool CanConvert(Type objectType) => true;

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken token = (JToken)serializer.Deserialize(reader);
        foreach (string property in _properties)
        {
            token = token[property];
            if (token == null) //if property doesn't exist
                return existingValue; //or throw exception
        }
        return token.ToObject(objectType);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

基本上,转换器允许绑定嵌套属性。用法

class SomeModel
{
    public string Title { get; set; }

    [JsonConverter(typeof(NestedPropertyConverter), "id")]
    [JsonProperty("supplier")] //its necessary to specify top level property name
    public int SupplierId { get; set; }

    [JsonProperty("count")]
    public double Amount { get; set; }
}

笔记

我还测试了以下有效载荷

{
    count : 10,
    supplier : {
        id : 342,
        name : "test",
        test: {
            val: 55
        }
    },
    title : "some title"
}

和配置属性

[JsonConverter(typeof(NestedPropertyConverter), "test.val")]
[JsonProperty("supplier")]
public int SupplierId { get; set; }

它工作正常。


推荐阅读