How to call WCF Service that requires Headers from Silverlight
WCF 3.5 SP1 Services / Called from Silverlight 4
In the situation where vendor has created a WCF API, both as svc services, as well as a custom proxy client.
Both aspects of this API sit on top of a core four-layer abstraction.
First there is are two abstract MessageContract classes: WcfRequest and WcfResponse.
The abstract WcfRequest type contains properties decorated with the MessageHeader attribute, and contain things such as a custom authentication identifier and timezone.
Then there is the second layer of the onion where each method is divided into two classes: GetSomethingRequest and a GetSomethingResponse, both of which inherit from WcfRequest and WcfReponse, respectively.
Next comes the implementation layer, where the WcfRequest and WcfResponse based types bubble up and get invoked by a custom WcfClient type, which controls all the ChannelFactory construction, establishes the binding, and most importantly, sets the identifier header in the WcfReq开发者_如何学运维uest type based on a previously set value in memory (like a session key).
Lastly comes the view to the ouside world, where you request POCO types via id values.
Now, the API is written in such a way that if I use the vendor supplied proxy, things will work as expected - authentication occurs and this identifier is set, and then I can call a method call without a problem.
If you've made it this far, thanks for sticking with me.
Now, the problem occurs when I want to write a Silverlight client, using either "Add Service Reference" or SLSvcUtil, none of the proxy client types generated have these header properties from the WcfRequest header to set, and are not defined in the message prototype as parameters to pass in.
To set these headers, I've looked at the WCFExtras project on Codeplex and tried to use the ClientSoapHeaderHelper routines, but that doesn't work for Silverlight (No extension capability).
I've tried to look into the OperationContext - to see if I could set the header there, but that's null - at least if I inspect it in the client proxy method.
Are you a person that knows how to manually (hack) these headers into place?
Thanks for any assistance...but totally understand if this gets no hits.
I ran in to the problem of custom headers a while ago... I basically needed to write headers a little differently than the internal classes wanted to (it was an apache service).
Here is the way I got around this (three classes).
Inside the operation context i create a new instance of my HeaderSerializer class. This class is based on HeaderSerializerBase (my class too) which is based on XmlObjectSerializer. HeaderSerializerBase uses WriteRaw to basically write any string in to the header that you like (in my case it was stored in the app, but you could build this dynamically no problems).
HTH :)
using (OperationContextScope ocs = new OperationContextScope(client.InnerChannel))
{
var ser = new HeaderSerializer();
OperationContext.Current.OutgoingMessageHeaders.Add(MessageHeader.CreateHeader("SecurityHeader",
"http://somesite.com/schema",
authHeader, ser));
var req = new GetPredefinedSearchResultsRequest()
{
Someproperty = somevalue
};
client.GetPredefinedSearchResultsAsync(req);
}
public class HeaderSerializer : HeaderSerializerBase
{
public EPGHeaderSerializer()
{
base.autheHeaderString = XamlingCore.Infrastructure.Resource.ResourceLoader.LoadStringResource("Assembly.Data", "RawHeaderData.txt");
}
}
public class HeaderSerializerBase : XmlObjectSerializer
{
protected string autheHeaderString;
public override void WriteStartObject(XmlDictionaryWriter writer, object graph)
{
throw new NotImplementedException();
}
public override void WriteObjectContent(XmlDictionaryWriter writer, object graph)
{
writer.WriteRaw(autheHeaderString.ToCharArray(), 0, autheHeaderString.Length);
}
public override void WriteEndObject(XmlDictionaryWriter writer)
{
throw new NotImplementedException();
}
public override object ReadObject(XmlDictionaryReader reader, bool verifyObjectName)
{
throw new NotImplementedException();
}
public override bool IsStartObject(XmlDictionaryReader reader)
{
throw new NotImplementedException();
}
}
精彩评论