WCF 主机将自定义 HTTP header 添加到响应

WCF host to add custom HTTP header to response

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

这不会将任何 HTTP header 添加到响应中,尽管 class 被调用,因为调试器可以进入 BeforeSendReply 函数。此外,如果我将 reply.Properties 替换为 reply.Headers,则会添加 header,但不会添加到 HTTP headers 但到 SOAP headers.

如何向响应中添加 HTTP header,例如 X-Frame-Options

我做了一个例子,用来添加额外的CORS HTTPheader,希望对你有帮助。
消息检查器。

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

结果。

如果有什么我可以帮忙的,请随时告诉我。