Как выставить интерфейс с WCF REST? - PullRequest
0 голосов
/ 19 апреля 2011
// Service file

   [WebInvoke(UriTemplate = "Send/{country}", Method = "POST")]
    public int Send(IFoo item, string country)

// Interface file
    public interface IFoo
    {
        string firstMember { get; set; }
        string secondMember { get; set; }
    }

// Implementation file
public class FooImpl : IFoo
{
  string specificMember { get; set; }
}

Я вызываю службу REST с сообщением о http://example.com/MyService/Send/{COUNTRY}/
Я хочу иметь возможность предоставлять реализацию IFoo в виде параметра text / xml, например:

<FooImpl xmlns="http://schemas.datacontract.org/2004/07/Hello">
  <firstMember>Hello</firstMember>
  <secondMember>World</secondMember>
  <SpecificMember>!</SpecificMember>
</FooImpl>

Это работает, когда я объявляю тип FooImpl в объявлении метода Send, но не работает, когда я использую тип IFoo. (Ошибка 400: Неверный запрос)
Отображается служебный помощник:

<anyType xmlns:d1="http://www.w3.org/2001/XMLSchema" i:type="d1:schema" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2003/10/Serialization/" />

Итак, я не знаю, является ли это проблемой XML в моем параметре или проблемой реализации ...

1 Ответ

0 голосов
/ 20 апреля 2011

Обновление :
Хорошо, похоже, мое первоначальное предположение было неверным.Даже при правильной установке известных типов я получаю ту же ошибку, что и вы.По-видимому, DataContractSerializer не используется по умолчанию, и добавление поведения для выбора настраиваемого сериализатора не влияет на конечные точки REST.Мне нужно еще немного покопаться ...

Исходное сообщение :
Немного сложно использовать интерфейс в контракте на обслуживание, потому что в конце концов данные должны бытьдесериализован в конкретный тип: интерфейсы не могут быть созданы.

Ключом к решению является то, что называется известные типы .DataContractSerializer должен знать о любом конкретном типе, с которым он может столкнуться во время (де) сериализации.

Я создал небольшой пример, который состоит из 4 различных проектов.ClientApp, Интерфейс, Библиотека и Сервис.

Интерфейс содержит IFoo и IService.

Библиотека содержит FooImpl, поскольку как клиенту, так и серверу необходим доступ к этому типу,Эта библиотека, однако, «подключаемая».Вы можете добавить больше реализаций IFoo на лету.

Угадайте, что Service и ClientApp содержат:)

Для контракта на обслуживание требуетсяspecial KnownTypeAttribute:

[ServiceContract]
[ServiceKnownType(typeof(IFoo))]
public interface IService
{
    [OperationContract]
    string GetData(IFoo value);
}

Теперь вы можете настроить конкретные типы, реализующие IFoo, в вашем App.config (или как он там называется) на клиенте и сервере:

<system.runtime.serialization>
    <dataContractSerializer>
        <declaredTypes>
            <add type="Interface.IFoo, Interface">
                <knownType type="Library.FooImpl, Library" />
            </add>
        </declaredTypes>
    </dataContractSerializer>
</system.runtime.serialization>

вам не нужна эта подключаемая структура, вы должны иметь возможность использовать

[KnownType(typeof(FooImpl))]

вместо всей этой сложной структуры.

Если я смогу найти время завтра, я протестирую WCFОстановитесь на этом и сделайте образец доступным для загрузки.

...