c# - 使用默认行为将模型绑定(bind)到接口(interface)

标签 c# asp.net-mvc asp.net-web-api parameters model-binding

我正在尝试将 Controller 操作绑定(bind)到接口(interface),但仍保持默认绑定(bind)行为。

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 中是一种黑客行为。我希望能够在服务中处理它。如果我将 CoolClass 指定为 Action 参数,它就可以正常工作。

我在这里找到了问题的部分解决方案 Dependency injection for ASP.NET Web API action method parameters但有一个后续问题。该解决方案不解析接口(interface)属性。请参阅下面的示例:

IConcreteClass 将被解析,但 ISubtype 不会。

public class SubConcreteClass : ISubtype
{
    // properties
}

public class ConcreteClass : IConcreteClass
{
    public ISubtype Subtype {get;set;}
}

一旦媒体格式化程序发现可以解析 IConcreteClass 中的类型,它就会读取整个流。所以我猜没有机会解析接口(interface)成员。

最佳答案

正如我上面提到的,action方法的接口(interface)参数可以使用DI来解析。但是该对象的接口(interface)成员需要以不同的方式处理。

我创建了 2 种类型的 JSON 转换器,一种是单一实体类型,另一种是集合类型,用于修饰接口(interface)属性。

这里有一个类需要解析为action接口(interface)参数。

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; }
}

这是 Controller 的 Action 方法

public HttpResponseMessage PostEnvelope(ICreateEnvelopeCommand model)
{
    // do stuff
}

这是 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>));
    }
}

关于c# - 使用默认行为将模型绑定(bind)到接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18324070/

相关文章:

c# - 如何使用 JQuery Ajax 调用从 Web 方法发送和检索数据?

c# - 基于条件的linq语法调用方法

c# - 如何安排数据库任务?

c# - 通过带有 params 关键字的 GET 将多个参数传递给 MVC Controller 操作

c# - 在 WebAPI 构造函数中访问请求 (HttpRequestMessage)

mysql - 无法使用 nuget 在 Visual Studio 中安装 MySql.Data

c# - 从具有整数值的 jwt 有效负载解码编码的 JSON 字符串时,Convert.FromBase64string 抛出无效的 Base-64 异常

asp.net-mvc - 为什么 ASP.NET MVC 路径会出现变量?

c# - MVC3 模型绑定(bind)问题

azure - 只有一个选项 : Connect to an existing user store in the cloud