WCF主机添加自定义HTTP标头以响应

时间:2020-03-10 10:33:30

标签: c# wcf

我有一个作为Windows服务运行的独立C#WCF服务。我要求向所有响应中添加自定义标头,例如 X-Frame-Options 。我试图将以下类的实例添加到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) { }
}

尽管由于调试器可以进入BeforeSendReply函数,所以调用了该类,但这并未在响应中添加任何HTTP标头。此外,如果我将 reply.Properties 替换为 reply.Headers ,则会添加标头,而不是HTTP标头,而是SOAP标头。

如何向响应中添加诸如 X-Frame-Options 之类的HTTP标头?

1 个答案:

答案 0 :(得分:1)

我举了一个示例,该示例用于添加额外的CORS HTTP标头,希望它对您有帮助。
邮件检查器。

        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);

            }
    }

自定义合同属性。

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)
        {

        }
}

应用合同行为。

[ServiceContract(Namespace = "mydomain")]
[MyBehavior]
public interface IService
{
    [OperationContract]
    [WebGet]
    string SayHello();
}

结果。
enter image description here

请随时告诉我是否有什么可以帮忙的。