绑定WebAPI控制器模型的指定属性

时间:2015-02-27 19:55:25

标签: asp.net .net c#-4.0 asp.net-web-api

我想只绑定WebAPI控制器模型的指定属性,并跳过DefaultModelBinder的所有其他属性。

例如我有json,应该传递给WebAPI控制器:

{
   prop1: 1,
   prop2: "b",
   prop3: "c",
   currentTime: "Fri Feb 27 2015",
   references: 
   [
      { name: "Name 1", type: "Info"  },
      { name: "Name 2", type: "Warn" }
   ]
}

在服务器端,有一个HttpPost操作,其中包含以下签名:

[HttpPost]
public void SaveObject(ReferenceModel model)
{
   ...
} 

ReferenceModel的位置:

public class ReferenceModel
{
   public int Prop1 {get; set;}
   public string Prop2 {get; set;}
   public string Prop3 {get; set;}
   public DateTime CurrentTime {get; set;}
   public List<BaseReferenceItem> References {get; set;}
}

我需要References属性的自定义绑定,因为我想在运行时使用派生类型的对象初始化此属性。

例如,如果我的Prop1值为1,那么我需要使用DerivedReferenceType1类型的对象初始化此集合:

Model.References = new List<BaseReferenceItem>()
   {
     new DerivedReferenceType1(){...},
     new DerivedReferenceType1(){...}
   }

如果我的Prop1值为2 - 类型为DerivedReferenceType2,依此类推。

我在ModelBinder找到了可能的解决方案,但我不想绑定模型中的所有属性。

我知道可以通过调用

在MVC模型绑定器中轻松实现它
base.BindModel(controllerContext, bindingContext);

但是如何在WebAPI中做到这一点?

谢谢!

1 个答案:

答案 0 :(得分:1)

一种可能性是编写自定义JsonConverter来处理这种情况:

public class MyConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(ReferenceModel);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var jsonObject = JObject.Load(reader);
        var result = new ReferenceModel();
        serializer.Populate(jsonObject.CreateReader(), result);

        result.References = new List<BaseReferenceItem>();
        foreach (var obj in jsonObject.GetValue("references", StringComparison.InvariantCultureIgnoreCase))
        {
            if (result.Prop1 == 1)
            {
                result.References.Add(obj.ToObject<DerivedReferenceType1>(serializer));
            }
            else if (result.Prop1 == 2)
            {
                result.References.Add(obj.ToObject<DerivedReferenceType2>(serializer));
            }
            else
            {
                throw new NotSupportedException(result.Prop1 + " is not supported value for Prop1");
            }
        }

        return result;
    }

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

然后您可以使用此自定义转换器装饰主视图模型:

[JsonConverter(typeof(MyConverter))]
public class ReferenceModel
{
    public int Prop1 { get; set; }
    public string Prop2 { get; set; }
    public string Prop3 { get; set; }
    public DateTime CurrentTime { get; set; }
    public List<BaseReferenceItem> References { get; set; }
}

或者如果您希望在不修改视图模型的情况下执行此操作,则可以始终在引导过程中注册自定义转换器:

public static void Register(HttpConfiguration config)
{
    // Web API routes
    ...

    var jsonFormatter = config.Formatters.JsonFormatter;

    jsonFormatter.SerializerSettings.Converters.Add(new MyConverter());
}