Я пытаюсь кодировать клиента веб-службы в Silverlight для RESTful-службы WCF, которую я разработал. В Silverlight я создаю тело WebRequest с использованием экземпляра DataContractSerializer.
Этот подход прекрасно работает, если для OperationContract есть единственный аргумент. Это не так хорошо работает, если в OperationContract определены несколько аргументов. Я полагаю, что это потому, что WCF создает динамический тип, который назван в честь OperationContract, а члены этого типа названы в честь параметров, определенных для операции. Назначение динамического типа состоит в том, чтобы обеспечить наличие единственного элемента XML в теле сообщения, передаваемого службе WCF ... имеет смысл. Вопрос в том, как мне самому построить этот динамический тип, чтобы я мог сам отправить его в DataContractSerializer.
Первый пример - это рабочий пример, который определяет один параметр. Второй пример - сценарий, который я пытаюсь решить (несколько параметров).
Пример 1:
[OperationContract,
WebInvoke(Method = HttpMethodType.Post,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "UnregisterProvider"),
WebHelp(Comment = "Unregistered the provider type with the specified URI.")]
void UnregisterProvider(RdfUri providerUri);
Код, используемый для сериализации тела сообщения:
StringBuilder msgBody = new StringBuilder(250);
using (XmlWriter xw = XmlWriter.Create(msgBody))
{
var serializer = new DataContractSerializer(typeof(RdfUri));
serializer.WriteObject(xw, providerUri);
}
Результирующее тело:
<RdfUri xmlns="http://schemas.datacontract.org/2004/07/Intellidimension.Rdf">esp:semanticserver</RdfUri>
Пример 2:
[OperationContract,
WebInvoke(Method = HttpMethodType.Post,
BodyStyle = WebMessageBodyStyle.WrappedRequest, /* WrappedRequest must somehow signal WCF to create the anonymous type as it is required for multiple parameter OperationContracts */
UriTemplate = "RegisterProvider"),
WebHelp(Comment = "Registered a provider type with the specified URI.")]
void RegisterProvider(PoolableEntityServiceProviderDescriptor descriptor, RdfUri providerUri);
Код, используемый для сериализации тела сообщения:
//?????
Результирующее тело:
<RegisterProvider xmlns="http://tempuri.org/">
<descriptor i:type="a:SemanticServerProviderDescriptor" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:a="http://schemas.datacontract.org/2004/07/Intellidimension.RdfEntity.Service.DataContracts">
<a:ConnectionString>Data Source=.\sqlexpress;Initial Catalog=RdfTest1;Persist Security Info=True;User ID=sa;Password=password</a:ConnectionString>
<a:ProviderGraphUri>http://entitystore/graph-provider</a:ProviderGraphUri>
</descriptor>
<providerUri>esp:semanticserver</providerUri>
</RegisterProvider>
Обновление 1 :
Вот парень на форумах MSDN, задающий аналогичный вопрос: Могу ли я использовать DataContractSerializerOperationFormatter для форматирования списка параметров от клиента к серверу?
DataContractSerializerOperationFormatter является внутренним классом. Похоже, мне пришлось реализовать это поведение для моего клиента.
Обновление 2 :
Некоторые спрашивают, почему я не просто использую обычный клиент Silverlight WCF, созданный ссылкой на службу. Причина в том, что служба WCF на сервере является службой RESTful. Из документов :
Аналогов для WebHttpBinding, предоставляемых в WCF, нет. Для доступа к чистым службам HTTP, REST, RSS / Atom или AJAX из Silverlight 2 используйте методы, описанные в разделе «Прямой доступ к службам на основе HTTP», такие как класс WebClient. Чтобы получить доступ к службам ASP.NET AJAX, см. Доступ к службам ASP.NET AJAX.