Я пытаюсь закодировать клиент веб-службы в Silverlight для службы RESTful WCF, которую я разработал. В Silverlight я создаю тело WebRequest, используя экземпляр DataContractSerializer.
Этот подход отлично работает, если есть единственный аргумент для OperationContract. Это не работает так хорошо, если в OperationContract определено несколько аргументов. Я считаю, что это связано с тем, что WCF создает динамический тип, который назван в честь OperationContract, а члены этого типа названы в соответствии с параметрами, определенными для операции. Цель динамического типа - гарантировать, что в теле сообщения, отправляемого в службу WCF, существует единственный элемент XML ... имеет смысл. Вопрос в том, как мне самому создать этот динамический тип, чтобы я мог сам отправить его в 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.