Web API模型绑定到接口 [英] web api model binding to an interface
问题描述
我试图将控制器操作绑定到接口,但仍保持默认的绑定行为.
I'm trying to bind a controller action to an interface but still maintain the default binding behavior.
public class CoolClass : ISomeInterface
{
public DoSomething {get;set;} // ISomeInterface
}
public class DosomethingController : ApiController
{
public HttpResponseMessage Post(ISomeInterface model)
{
// do something with model which should be an instance of CoolClass
}
}
我的服务的使用者对CoolClass一无所知,因此,我认为让他们将"$ type"添加到他们正在传递的Json上将是一个hack.我希望能够在服务中处理它.如果我将CoolClass指定为action参数,则效果很好.
The consumer of my service knows nothing of CoolClass so having them add "$type" to the Json they are passing would be a hack in my opinion. I'd like to be able to handle it in the service. If I specify CoolClass as the action parameter it works fine.
So I found a partial solution to my question here Dependency injection for ASP.NET Web API action method parameters but there is a follow up issue. That solution does not resolve interface properties. See my example below.
IConcreteClass将被解析,但ISubtype将无法解析.
IConcreteClass will be resolved, but ISubtype will not.
public class SubConcreteClass : ISubtype
{
// properties
}
public class ConcreteClass : IConcreteClass
{
public ISubtype Subtype {get;set;}
}
一旦媒体格式化程序看到可以解析IConcreteClass中的类型,则它将读取整个流.因此,我猜测没有机会解析接口成员.
Once the media formatter sees that is can resolve the type in IConcreteClass, it then reads the entire stream. So I'm guessing there is no chance to resolve interface members.
推荐答案
因此,如果这可以对其他人有所帮助,我将继续发布我想出的解决方案.
So in case this can help anyone else, I'll go ahead and post the solution I came up with.
如上所述,可以使用DI解析action方法的接口参数.但是该对象的接口成员需要以不同的方式处理.
As I mentioned above, the interface parameters of the action method can be resolved using DI. But the interface members of that object need to be handled differently.
我创建了两种类型的Json转换器(一个实体类型和一个集合类型)来装饰接口属性.
I created 2 types of Json converters, a single entity type and a collection type, to decorate the interface properties.
这是一个需要作为操作界面参数解析的类.
Here's a class that needs to be resolved as an action interface parameter.
public class CreateEnvelopeModel : ICreateEnvelopeCommand
{
[JsonConverter(typeof(EntityModelConverter<CreateEmailModel, ICreateEmailCommand>))]
public ICreateEmailCommand Email { get; set; }
[JsonConverter(typeof(CollectionEntityConverter<CreateFormModel, ICreateFormCommand>))]
public IList<ICreateFormCommand> Forms { get; set; }
}
这是控制器操作方法
public HttpResponseMessage PostEnvelope(ICreateEnvelopeCommand model)
{
// do stuff
}
这是2个json转换器
Here's the 2 json converters
public class EntityModelConverter<T, Tt> : JsonConverter where T : Tt
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(Tt));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return serializer.Deserialize<T>(reader);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value, typeof(T));
}
}
public class CollectionEntityConverter<T, Tt> : JsonConverter where T : Tt
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(IList<Tt>));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
IList<Tt> items = serializer.Deserialize<List<T>>(reader).Cast<Tt>().ToList();
return items;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value, typeof(IList<T>));
}
}
这篇关于Web API模型绑定到接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!