【问题标题】:WCF host to add custom HTTP header to responseWCF 主机将自定义 HTTP 标头添加到响应
【发布时间】:2020-03-10 10:33:30
【问题描述】:

我有一个独立的 C# WCF 服务作为 Windows 服务运行。我需要向所有响应添加自定义标头,例如 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) { }
}

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

如何在响应中添加像 X-Frame-Options 这样的 HTTP 标头?

【问题讨论】:

  • 你试过HttpRequestMessageProperty requestMessage = new HttpRequestMessageProperty(); requestMessage.Headers["X-Frame-Options"] = "deny"; OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestMessage;吗?
  • 我还发现了这段代码 sn-p 并且它不起作用(确切地说是不起作用),因为没有“X-Frame-Options”标头。

标签: c# wcf


【解决方案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();
}

结果。

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

【讨论】:

  • 谢谢,但var httpHeader = reply.Properties["httpResponse"] as HttpResponseMessageProperty; 行抛出此异常:System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]: 名为“httpResponse”的属性不存在。
  • 如果您修改代码并将if (!reply.Properties.ContainsKey("httpResponse")) reply.Properties.Add("httpResponse", new HttpResponseMessageProperty()); 添加到 BeforeSendReply() 的开头,那么我会接受您的回答。
  • 我的错。我忘记了 WCF 中使用的绑定类型,如果 WCF 不是由 Webhttpbinding 创建的,我们应该添加您的代码段。它将完美地工作。我已经更新了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-18
  • 2019-02-06
  • 2018-10-04
  • 2019-06-10
  • 2018-02-26
  • 2012-04-23
相关资源
最近更新 更多