I'm trying to code a web service client in Silverlight for a RESTful WCF service that I have developed. In Silverlight I am constructing the body of the WebRequest using a DataContractSerializer instance.
This approach works great if there is a single argument for the OperationContract. It doesn't work so well if there are multiple arguments defined in the OperationContract. I believe this is because a dynamic type is being created by WCF that is named after the OperationContract and the members of that type are named after the parameters defined for the operation. The purpose of the dynamic type is to ensure that a single XML element exists in the message body being submitted to the WCF service... makes sense. Question is how do I construct this dynamic type myself so that I can submit it to the DataContractSerializer myself.
First example is a working example that defines a single parameter. Second example is the scenario that I am trying to solve (multiple parameters).
Example 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);
Code used to serialize message body:
StringBuilder msgBody = new StringBuilder(250);
using (XmlWriter xw = XmlWriter.Create(msgBody))
{
var serializer = new DataContractSerializer(typeof(RdfUri));
serializer.WriteObject(xw, providerUri);
}
Resulting body:
<RdfUri xmlns="http://schemas.datacontract.org/2004/07/Intellidimension.Rdf">esp:semanticserver</RdfUri>
Example 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);
Code used to serialize message body:
//?????
Resulting body:
<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>
Update 1:
Here is a guy on the MSDN forums asking a similar question: Can I use DataContractSerializerOperationFormatter to format a list of parameters from client to server?
DataContractSerializerOperationFormatter is an internal class. So looks like I may have to implemented it's behavior for my client.
Update 2:
Some are asking why I am not just using the normal Silverlight WCF client generated by a service reference. The reason is that the WCF service on the server is a RESTful service. From the docs:
No analog to the WebHttpBinding provided in WCF is provided. To access pure HTTP, REST, RSS/Atom, or AJAX services from Silverlight 2, use the techniques described in Accessing HTTP-Based Services Directly, such as the WebClient class. To access ASP.NET AJAX services, see Accessing ASP.NET AJAX Services.