Привязка модели 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
    }
} 

Потребитель моего сервиса ничего не знает о CoolClass, поэтому, по моему мнению, добавление "$type" в Json, который они передают, было бы хаком. Я хотел бы быть в состоянии справиться с этим в службе. Если я укажу CoolClass в качестве параметра действия, он будет работать нормально.

РЕДАКТИРОВАТЬ: Таким образом, я нашел частичное решение моего вопроса здесь Внедрение зависимостей для параметров метода действия ASP.NET Web API, но есть последующая проблема. Это решение не разрешает свойства интерфейса. Смотрите мой пример ниже.

IConcreteClass будет разрешен, а ISubtype - нет.

public class SubConcreteClass : ISubtype
{
    // properties
}

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

Как только средство форматирования мультимедиа видит, что оно может разрешить тип в IConcreteClass, оно затем читает весь поток. Таким образом, я предполагаю, что нет никаких шансов разрешить членов интерфейса.

2 ответа

Решение

Так что в случае, если это может помочь кому-то еще, я отправлю решение, которое придумал.

Как я уже упоминал выше, параметры интерфейса метода действия могут быть разрешены с помощью DI. Но члены интерфейса этого объекта должны обрабатываться по-разному.

Я создал 2 типа 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; }
}

Вот метод действия контроллера

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

Смотреть на Model Binders раздел здесь. Я думаю, что это ваш случай.

Другие вопросы по тегам