WCF RoutingService - redirect with query string - c#

We are working on WCF Routing Service which redirects different soap actions to different endpoints.
We want to this service rewrite query string included in router url: #router url#?param=param to endpoint: #endpoint url#?param=param.
Our webservices accepts query strings when call directly, this strings are visible in router (context) but on the end this strings are removed from url.
Do you know how add this strings to the end of endpoint url in every request?

We solved the problem.
You must create new binding:
public class QueryHttpBinding : BasicHttpBinding
{
public override BindingElementCollection CreateBindingElements()
{
var result = base.CreateBindingElements();
var http = result.Find<HttpTransportBindingElement>();
if (http != null)
{
http.ManualAddressing = true;
}
var https = result.Find<HttpsTransportBindingElement>();
if (https != null)
{
https.ManualAddressing = true;
}
return result;
}
}
And Client message inspector:
public class CustomInspectorBehavior : IClientMessageInspector
{
object IClientMessageInspector.BeforeSendRequest(ref Message request, IClientChannel channel)
{
UriBuilder builder = new UriBuilder(channel.RemoteAddress.ToString());
builder.Path += "?" + ((HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name]).QueryString;
request.Headers.To = builder.Uri;
return null;
}
void IClientMessageInspector.AfterReceiveReply(ref Message reply, object correlationState)
{
}
}
Next you must create new endpoint Behavior:
public class Behavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
var inspector = new CustomInspectorBehavior();
clientRuntime.MessageInspectors.Add(inspector);
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
}

Related

How to add transform algorithm ("enveloped-signature")

I am stuck with a call to soap service which needs "enveloped-signature" as transform algorithm. And i am getting "xml-exc-c14n#". I am using custom binding to initialize the client for WCF request.
Update:
In the above example, I was trying without Message Inspectors. So I have tried both ways. 1. using WCF call but then I am unable to change the transform algorithm to "enveloped-signature". 2. I tried using Inspector where I try to create signed XML document and add this to the request message. Like explained in this example Message inspectors- WCF call
I failed in both.
Below is the code i am using for WCF call without Inspector
var b = new CustomBinding();
var sec = (AsymmetricSecurityBindingElement)SecurityBindingElement.CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10);
sec.EndpointSupportingTokenParameters.Signed.Add(new UserNameSecurityTokenParameters());
sec.MessageSecurityVersion =
MessageSecurityVersion.
WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12;
sec.IncludeTimestamp = false;
sec.MessageProtectionOrder = System.ServiceModel.Security.MessageProtectionOrder.SignBeforeEncrypt;
sec.DefaultAlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic256Sha256;
X509SecurityTokenParameters x509Params = new X509SecurityTokenParameters
{
X509ReferenceStyle = X509KeyIdentifierClauseType.IssuerSerial,
RequireDerivedKeys = false,
InclusionMode = SecurityTokenInclusionMode.Once,
ReferenceStyle = SecurityTokenReferenceStyle.Internal
};
((AsymmetricSecurityBindingElement)sec).InitiatorTokenParameters = x509Params;
b.Elements.Add(sec);
b.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8));
b.Elements.Add(new HttpsTransportBindingElement() { });
Please help me out if you have got any idea.
On the client side, by implementing the IClientMessageInspector interface to intercept SOAP messages.
public class ClientMessageLogger : IClientMessageInspector
{
public object AfterReceiveRequest(ref Message reply, object correlationState)
{
MessageHeader header = MessageHeader.CreateHeader("UserAgent", "http://User", "User1");
reply.Headers.Add(header);
return null;
}
public void BeforeSendRequest(ref Message request, IClientChannel channel)
{
MessageHeader header1 = MessageHeader.CreateHeader("Testreply", "http://Test", "Test");
request.Headers.Add(header1);
}
}
[AttributeUsage(AttributeTargets.Interface)]
public class CustomBehavior : Attribute, IContractBehavior
{
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
return;
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
return;
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
dispatchRuntime.MessageInspectors.Add(new CustomMessageInspector());
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
return;
}
}
Then, apply the CustContractBehavior feature to the service interface.
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
[CustomBehavior]
public interface IDemo
When the client sends a request to the server, it will call BeforeSendRequest, and when the client receives the server reply message, it will call AfterReceiveReply.

WCF host to add custom HTTP header to response

I have a standalone C# WCF service running as a Windows service. I have the requirement to add custom headers like X-Frame-Options to all responses. I have tried to add an instance of the following class to ServiceEndpoint.Behaviors
internal class ServerInterceptor : IDispatchMessageInspector, IEndpointBehavior
{
object IDispatchMessageInspector.AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
return null;
}
void IDispatchMessageInspector.BeforeSendReply(ref Message reply, object correlationState)
{
reply.Properties.Add("X-Frame-Options", "deny");
}
void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
}
void IEndpointBehavior.Validate(ServiceEndpoint endpoint) { }
void IEndpointBehavior.AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { }
}
This doesn't add any HTTP header to the response although the class gets called as the debugger can step into the BeforeSendReply function. Furthermore if I replace reply.Properties with reply.Headers then the header is added, but not to the HTTP headers but to the SOAP headers.
How can I add a HTTP header like X-Frame-Options to the response?
I made an example, which is used to add extra CORS HTTP header, wish it is instrumental for you.
Message Inspector.
public class CustomHeaderMessageInspector : IDispatchMessageInspector
{
Dictionary<string, string> requiredHeaders;
public CustomHeaderMessageInspector(Dictionary<string, string> headers)
{
requiredHeaders = headers ?? new Dictionary<string, string>();
}
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
string displayText = $"Server has received the following message:\n{request}\n";
Console.WriteLine(displayText);
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
if (!reply.Properties.ContainsKey("httpResponse"))
reply.Properties.Add("httpResponse", new HttpResponseMessageProperty());
var httpHeader = reply.Properties["httpResponse"] as HttpResponseMessageProperty;
foreach (var item in requiredHeaders)
{
httpHeader.Headers.Add(item.Key, item.Value);
}
string displayText = $"Server has replied the following message:\n{reply}\n";
Console.WriteLine(displayText);
}
}
Custom Contract Attribute.
public class MyBehaviorAttribute : Attribute, IContractBehavior, IContractBehaviorAttribute
{
public Type TargetContract => typeof(MyBehaviorAttribute);
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
var requiredHeaders = new Dictionary<string, string>();
requiredHeaders.Add("Access-Control-Allow-Origin", "*");
requiredHeaders.Add("Access-Control-Request-Method", "POST,GET,PUT,DELETE,OPTIONS");
requiredHeaders.Add("Access-Control-Allow-Headers", "X-Requested-With,Content-Type");
dispatchRuntime.MessageInspectors.Add(new CustomHeaderMessageInspector(requiredHeaders));
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
}
}
Apply the contract behavior.
[ServiceContract(Namespace = "mydomain")]
[MyBehavior]
public interface IService
{
[OperationContract]
[WebGet]
string SayHello();
}
Result.
Feel free to let me know if there is anything I can help with.

How to pass winform custom user credentials to WCF services in every requests?

What I'm trying to achieve is passing credentials/token to WCF services in every requests. BTW, this credential IS NOT windows credentials, they are fetched from custom db, and the authentication logic is quite simple, tenantId+username+password.
I'm currently using message inspector to insert these kind of information in the headers and fetch them from server-side inspector(using OperationContext).
But in order to stay thread-safe,I have to wrap the requests in every winform request like this:
using (new OperationContextScope((WcfService as ServiceClient).InnerChannel))
{
MessageHeader hdXXId = MessageHeader.CreateHeader("XXId", "CustomHeader", WinformSomeVariable.XXId);
OperationContext.Current.OutgoingMessageHeaders.Add(hdXXId);
_objXX = WcfService.GetXXById(id);
}
Like showed above, this is quite heavy and obviously not a smart way to handle this situation. So is there any way to hold these kind of information safely and can as well fetch them in the WCF Inspectors?
Many thanks!
PS. Thanks to #Abraham Qian, I was being silly the whole time. Just put the client inspector within the same winform project will solve this issue.
Just ignore the question of how to refactor your authentication for a moment.
As for how to use the IClientMessageInspector interface to create a persistent message header, the following code snippet might be useful (Assume that invocation by using Channel Factory)
class Program
{
static void Main(string[] args)
{
Uri uri = new Uri("http://localhost:1300");
IService service = ChannelFactory<IService>.CreateChannel(new BasicHttpBinding(), new EndpointAddress(uri));
try
{
Console.WriteLine(service.SayHello());
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
[ServiceContract(Namespace = "mydomain")]
[CustomContractBehavior]
public interface IService
{
[OperationContract]
string SayHello();
}
public class ClientMessageLogger : IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState)
{
string displayText = $"the client has received the reply:\n{reply}\n";
Console.Write(displayText);
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
//Add custom message header
request.Headers.Add(MessageHeader.CreateHeader("myheader","mynamespace",2000));
string displayText = $"the client send request message:\n{request}\n";
Console.WriteLine(displayText);
return null;
}
}
public class CustomContractBehaviorAttribute : Attribute, IContractBehavior, IContractBehaviorAttribute
{
public Type TargetContract => typeof(IService);
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
return;
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.ClientMessageInspectors.Add(new ClientMessageLogger());
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
return;
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
return;
}
}

Adding Http Header in an existing WCF SOAP Service is not working

I would like to an HTTP header to my WCF SOAP Service. My end goal is to send API keys through this HTTP header.
Below is my code:
[ServiceBehavior(Namespace = "http://****.com/**/1.1")]
public class MyWcfSvc : IMyVerify
{
const int MaxResponseSize = 0xffff; // 64K max size - Normally it will be MUCH smaller than this
private static readonly NLogLogger Logger;
static MyWcfSvc()
{
Logger = new NLogLogger();
// Add an HTTP Header to an outgoing request
HttpRequestMessageProperty requestMessage = new HttpRequestMessageProperty();
requestMessage.Headers["User-Auth"] = "MyHttpHeaderValue";
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestMessage;
}
}
I do not see User-Auth header under HTTP request headers.
I also tried with another way.
public AnalyzeResponse Analyze(AnalyzeRequest analyzeRequest)
{
HttpRequestMessageProperty requestMessage = new HttpRequestMessageProperty();
requestMessage.Headers["User-Auth"] = "MyHttpHeaderValue";
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestMessage;
.
.
. Rest of the service implementation
.
.
.
}
But, still, I don't see any HTTP header information with the request message. I am using SOAP UI to send the requests and to view the responses.
How should I go about this? Am I suppose to make changes to the Service related to class? Or I need to make some changes to web.config file?
SOAP Header
To add a SOAP header, use the following code client-side:
using (OperationContextScope scope = new OperationContextScope((IContextChannel)channel))
{
MessageHeader<string> header = new MessageHeader<string>("MyHttpHeaderValue");
var untyped = header.GetUntypedHeader("User-Auth", ns);
OperationContext.Current.OutgoingMessageHeaders.Add(untyped);
// now make the WCF call within this using block
}
And then, server-side, grab it using:
MessageHeaders headers = OperationContext.Current.IncomingMessageHeaders;
string identity = headers.GetHeader<string>("User-Auth", ns);
NB. ns is The namespace URI of the header XML element.
HTTP Header
To add an Http header:
// Add a HTTP Header to an outgoing request
HttpRequestMessageProperty requestMessage = new HttpRequestMessageProperty();
requestMessage.Headers["MyHttpHeader"] = "MyHttpHeaderValue";
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestMessage;
And to grab it server-side
IncomingWebRequestContext request = WebOperationContext.Current.IncomingRequest;
WebHeaderCollection headers = request.Headers;
Console.WriteLine(request.Method + " " + request.UriTemplateMatch.RequestUri.AbsolutePath);
foreach (string headerName in headers.AllKeys)
{
Console.WriteLine(headerName + ": " + headers[headerName]);
}
If you are trying to add an HTTP request header to the client request, you can follow the procedure below.
Create a client message inspector. For example:
public class CustomInspector : IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState)
{
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
HttpRequestMessageProperty reqProps = request.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
if(reqProps == null)
{
reqProps = new HttpRequestMessageProperty();
}
reqProps.Headers.Add("Custom-Header", "abcd");
request.Properties[HttpRequestMessageProperty.Name] = reqProps;
return null;
}
}
Create an endpoint behavior to load this inspector:
public class CustomBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.ClientMessageInspectors.Add(new CustomInspector());
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
Finally add this behavior to the endpoint.
class Program
{
static void Main(string[] args)
{
ChannelFactory<ICalculator> factory = new ChannelFactory<ICalculator>("BasicHttpsBinding_ICalculator");
factory.Endpoint.EndpointBehaviors.Add(new CustomBehavior());
var client = factory.CreateChannel();
var number = client.Add(1, 2);
Console.WriteLine(number.ToString());
}
}
The above example works on my side. I could see the request header with Fiddler.
There is better solution on client-side than Leonardo's. His solution requires to manually modify each request. Here is solution with ClientMessageInspector, which automatically adds header to each outgoing request.
1: Define MessageInspector with overrides:
Bellow is the only one override method, the rest is empty.
public class ClientMessageInspector : IClientMessageInspector
{
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
HttpRequestMessageProperty property = new HttpRequestMessageProperty();
property.Headers["User-Agent"] = "value";
request.Properties.Add(HttpRequestMessageProperty.Name, property);
return null;
}
...
}
Bind this Message inspector to EndPointBehavior.
Bellow is the only one override method, the rest is empty.
public class CustomEndpointBehavior : IEndpointBehavior
{
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.ClientMessageInspectors.Add(new ClientMessageInspector());
}
...
}
The last step is to add the new behavior to the WCF endpoint:
Endpoint.EndpointBehaviors.Add(new CustomEndpointBehavior());

wcf :custom message inspector does not get wired up

I have made a custom error handler on the service side:
public class GlobalErrorHandler : Attribute, IErrorHandler, IServiceBehavior
{
public void AddBindingParameters(
ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase,
Collection<ServiceEndpoint> endpoints,
BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
IErrorHandler errorHandler = new GlobalErrorHandler();
foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
if (channelDispatcher != null)
{
channelDispatcher.ErrorHandlers.Add(errorHandler);
}
}
}
public bool HandleError(Exception error)
{
Trace.TraceError(error.ToString());
if (error is FaultException)
return false; // Let WCF do normal processing
else
return true; // Fault message is already generated
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
if (error is FaultException)
{
// Let WCF do normal processing
}
else
{
// Generate fault message manually
MessageFault messageFault = MessageFault.CreateFault(
new FaultCode("Sender"), new FaultReason(error.Message),
error, new NetDataContractSerializer());
fault = Message.CreateMessage(version, messageFault, null);
}
}
}
public class ErrorHandlerElement : BehaviorExtensionElement
{
protected override object CreateBehavior()
{
return new GlobalErrorHandler();
}
public override Type BehaviorType
{
get { return typeof (GlobalErrorHandler); }
}
}
I have defined a custom message inspector on the client side :
public class MessageInspector : IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState)
{
if (reply.IsFault)
{
//do some processing
}
}
public object BeforeSendRequest(ref Message request, System.ServiceModel.IClientChannel channel)
{
return null;
}
}
I have a custom behaviour which wire ups the message inspector :
public class NewtonsoftJsonBehavior : WebHttpBehavior
{
public override void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(new MessageInspector());
}
}
and this behaviour is applied programatically through a factory :
public class JsonWebServiceHostFactory : WebServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
var host = base.CreateServiceHost(serviceType, baseAddresses);
//return host;
//ServiceEndpoint ep = host.AddServiceEndpoint(serviceType, new WebHttpBinding(), "");
//host.Description.Endpoints[0].Behaviors.Add(new WebHttpBehavior { HelpEnabled = true });
//return host;
WebHttpBinding webBinding = new WebHttpBinding();
host.AddServiceEndpoint(serviceType, webBinding, "").Behaviors.Add(new NewtonsoftJsonBehavior());
return host;
}
}
However when I debug and I generate a faultexception in the service, the globalerrorhandler gets called , but the debugger never steps into the message inspector.
Any idea why?
To create a Message Inspector on WCF service side, use an implementation of IDispatchMessageInspector instead of: IClientMessageInspector.
An example:
Service:
EndpointAddress endpoint = new EndpointAddress("http://localhost:9001/Message");
WebServiceHost svcWebHost = new WebServiceHost(typeof(Service.Message), endpoint.Uri);
CustomServiceBehavior serviceBehavior = new CustomServiceBehavior();
svcWebHost.Description.Behaviors.Add(serviceBehavior);
Binding webHttpBinding = new WebHttpBinding();
ServiceEndpoint serviceEndpoint = svcWebHost.AddServiceEndpoint(typeof(Service.IMessage), webHttpBinding, endpoint.Uri);
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
svcWebHost.Description.Behaviors.Add(smb);
ServiceDebugBehavior sdb = svcWebHost.Description.Behaviors.Find<ServiceDebugBehavior>();
sdb.IncludeExceptionDetailInFaults = true;
svcWebHost.Open();
Service Contract
[ServiceContract]
public interface IMessage
{
[OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
Model.TestResponse Test();
}
Service Implementation
public class Message : IMessage
{
public Model.TestResponse Test()
{
return new Model.TestResponse() { success = true, message = "OK!" };
}
}
CustomServiceBehavior implements IServiceBehavior:
public class CustomServiceBehavior : IServiceBehavior
{
public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{
CustomEndpointBehavior endpointBehavior = new CustomEndpointBehavior();
foreach (var endpoint in serviceDescription.Endpoints)
endpoint.EndpointBehaviors.Add(endpointBehavior);
}
public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{
}
}
CustomEndpointBehavior implements IEndpointBehavior
public class CustomEndpointBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
{
var inspector = new CustomDispatchMessageInspector();
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
CustomDispatchMessageInspector implements IDispatchMessageInspector
public class CustomDispatchMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
return null;
}
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
var httpResponse = ((HttpResponseMessageProperty)reply.Properties["httpResponse"]);
httpResponse.Headers.Add("user-agent", "My Browser");
}
}
This example is a WCF Self Hosted without configuration file (Configuring WCF Services in Code) that return a Json and send a custom header in HTTP Response (user-agent:My Browser).
To test this code:
Create a Windows Console Application
Insert the code (each
block in one Class)
Run the applcation
Using browser open url:
http://localhost:9001/Message/Test
The response is a Json:
{"message":"OK!","success":true}
You can inspect the Response and
see the custom header: "user-agent:My Browser"
You only put your message inspector on the client side using ApplyClientBehavior. There is another method for the service side:
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
if (endpointDispatcher != null)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new MessageInspector());
}
}

Categories

Resources