web api模型绑定到接口

chr*_*l91 8 c# asp.net-mvc parameterbinding asp.net-web-api

我正在尝试将控制器操作绑定到接口,但仍然保持默认绑定行为.

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
    }
} 
Run Code Online (Sandbox Code Playgroud)

我的服务的消费者对CoolClass一无所知,所以让他们为他们正在传递的Json添加"$ type"在我看来是个黑客.我希望能够在服务中处理它.如果我将CoolClass指定为动作参数,它可以正常工作.

编辑:所以我发现我的问题的部分解决方案在这里为ASP.NET Web API操作方法参数的依赖注入,但有一个后续问题.该解决方案无法解析接口属性.请参阅下面的示例.

IConcreteClass将被解析,但ISubtype不会.

public class SubConcreteClass : ISubtype
{
    // properties
}

public class ConcreteClass : IConcreteClass
{
    public ISubtype Subtype {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

一旦媒体格式化程序看到它可以解析IConcreteClass中的类型,它就会读取整个流.所以我猜我没有机会解决界面成员.

chr*_*l91 14

所以如果这可以帮助其他人,我会继续发布我提出的解决方案.

如上所述,可以使用DI解决操作方法的接口参数.但是该对象的接口成员需要以不同方式处理.

我创建了两种类型的Json转换器,一个实体类型和一个集合类型来装饰接口属性.

这是一个需要作为动作接口参数解析的类.

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; }
}
Run Code Online (Sandbox Code Playgroud)

这是控制器动作方法

public HttpResponseMessage PostEnvelope(ICreateEnvelopeCommand model)
{
    // do stuff
}
Run Code Online (Sandbox Code Playgroud)

这是2个json转换器

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>));
    }
}
Run Code Online (Sandbox Code Playgroud)