I have a need to pass an HTTP header for each an every RIA Service request being made from a Silverlight app. The value of the header needs to come from the app instance, and not from a cookie. I know this can be accomplished by putting it in the DTOs, but it's not an option because a lot of our service calls use Entities and change sets, so there's no base class to tie into for all requests. So I'm looking for a centralized and safe means to pass something back with each request so the developers do not have to worry with it. A custom HTTP header would work fine, but I don't know how to intercept the outbound request to set it.
Anyone have any ideas I can try?
On the lower level you can add HTTP headers with the help of an IClientMessageInspector
. Try starting from this post on SL forum.
The next step depends on your use cases.
If the value of the header must be the same for any method called by the DomainContext
, then you may just extend the context using partial class, add a property for the header value and use that property in the inspector.
If you need to pass a different value for each method call, you'd probably need to wrap your DomainContext
into another class and add an argument to each method of the context that will accept the header value and pass it to the inspector somehow. Needless to say, without a code-generator this would be hard.
Here's an adapted sample from the SL forum for the first case:
public sealed partial class MyDomainContext
{
public string HeaderValue { get; set; }
partial void OnCreated()
{
WebDomainClient<IMyDomainServiceContract> webDomainClient = (WebDomainClient<IMyDomainServiceContract>)DomainClient;
CustomHeaderEndpointBehavior customHeaderEndpointBehavior = new CustomHeaderEndpointBehavior(this);
webDomainClient.ChannelFactory.Endpoint.Behaviors.Add(customHeaderEndpointBehavior);
}
}
public class CustomHeaderEndpointBehavior : IEndpointBehavior
{
MyDomainContext _Ctx;
public CustomHeaderEndpointBehavior(MyDomainContext ctx)
{
this._Ctx = ctx;
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(new CustomHeaderMessageInspector(this._Ctx));
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher) { }
public void Validate(ServiceEndpoint endpoint) { }
}
public class CustomHeaderMessageInspector : IClientMessageInspector
{
MyDomainContext _Ctx;
public CustomHeaderMessageInspector(MyDomainContext ctx)
{
this._Ctx = ctx;
}
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState) {}
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)
{
string myHeaderName = "X-Foo-Bar";
string myheaderValue = this._Ctx.HeaderValue;
HttpRequestMessageProperty property = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
property.Headers[myHeaderName] = myheaderValue;
return null;
}
}