0

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?

2
  • Dİd you try HttpRequestMessageProperty requestMessage = new HttpRequestMessageProperty(); requestMessage.Headers["X-Frame-Options"] = "deny"; OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestMessage;? Commented Mar 11, 2020 at 5:24
  • I also found this code snippet and it doesn't work (cannot work, to be exact), as there's no "X-Frame-Options" header. Commented Mar 11, 2020 at 8:18

1 Answer 1

1

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.
enter image description here

Feel free to let me know if there is anything I can help with.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks but the line var httpHeader = reply.Properties["httpResponse"] as HttpResponseMessageProperty; throws this exception: System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]: A property with the name 'httpResponse' is not present.
If you modify your code and add if (!reply.Properties.ContainsKey("httpResponse")) reply.Properties.Add("httpResponse", new HttpResponseMessageProperty()); to the beginning of BeforeSendReply() then I'll accept your answer.
My bad. I forget the binding type used in WCF, if the WCF isn’t created by Webhttpbinding, we should add your code segment. It will work perfectly. I have updated it.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.