如何包括控制台服务主机WCF自定义页眉 [英] How to include WCF Custom Headers in console Service Host

查看:176
本文介绍了如何包括控制台服务主机WCF自定义页眉的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的WCF服务我得到 405方法不被允许错误,然后在一个帖子里面建议在的Application_BeginRequest 我的WCF主机:

In my WCF service I was getting 405 method not allowederror and then came across a post which suggest to have the following in Application_BeginRequest of my WCF host:

protected void Application_BeginRequest(object sender, EventArgs e)
{
    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    {
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers",
                    "Accept, Content-Type,customHeader");

        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods",
                    "POST,GET,OPTIONS");

        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age",
                    "172800");

        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials",
                    "true");

        HttpContext.Current.Response.AddHeader("Access-Control-Expose-Headers",
                    "customHeader");

        HttpContext.Current.Response.AddHeader("Content-type",
                    "application/json");

        HttpContext.Current.Response.End();
    }
    else
    {
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers",
                    "Accept, Content-Type,customHeader");

        HttpContext.Current.Response.AddHeader("Access-Control-Expose-Headers",
                    "customHeader");

        HttpContext.Current.Response.AddHeader("Content-type",
                    "application/json");
    }
} 



但我使用一个控制台应用程序托管我的服务。

But I am hosting my service using a console application.

using (ServiceHost sc = new ServiceHost(typeof(DataRetriever)))
{
    sc.Open();

    foreach (var endPoints in sc.Description.Endpoints)
    {
        Console.WriteLine(endPoints.Address);
    }

    Console.ReadKey();
    sc.Close();
}



那么,如何包含在控制台应用程序的标头。

So how do I include the headers in the console app.

推荐答案

在WCF,头部可以通过类的的OperationContext ,这是通过OperationContext.Current

In WCF, headers can be accessed via an instance of the class OperationContext, which is accessible via the OperationContext.Current (when available).

要解决这个问题的天真的方式就是你的服务的方法中使用这个属性:

The naive way to approach this problem is to simply use this property within the method of your service:

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    void MyMethod();
}

internal class MyService: IMyService
{
    public void MyMethod()
    {
        Console.WriteLine("My Method");
        OperationContext.Current.OutgoingMessageHeaders.Add(MessageHeader.CreateHeader("headerFromMethod", "namespace", "headerFromMethodValue"));
    }
}

有关完整性,所使用的代码中托管这个服务控制台应用程序(无需配置)是:

For completeness, the code used to host this service within the Console Application (no config required) is:

using (var serviceHost = new ServiceHost(typeof(MyService)))
{
    var endpoint = serviceHost.AddServiceEndpoint(typeof(IMyService), new BasicHttpBinding(), "http://localhost:9000");

    serviceHost.Open();

    Console.WriteLine("Open for business");
    Console.ReadLine();

    serviceHost.Close();
}

一个.NET客户端将访问这样的标题:

A .NET client would access the headers like this:

var channel = ChannelFactory<IMyService>.CreateChannel(new BasicHttpBinding(), new EndpointAddress("http://localhost:9000"));

var contextChannel = channel as IContextChannel;
using (new OperationContextScope(contextChannel))
{
    channel.MyMethod();

    var incommingHeaders = OperationContext.Current.IncomingMessageHeaders;
    var header = incommingHeaders.GetHeader<string>("headerFromMethod", "namespace");
    Console.WriteLine("Header from server: " + header);
}

如果你的提琴手,你还可以看到使用此工具头。

If you have Fiddler, you can also see the headers using this tool.

虽然这种方法会做你想要什么,这是值得商榷的你是否想混业务逻辑(包含实施在 IMyService ),逻辑控制附加到消息的出带外的信息。

Whilst this method will do what you want, it is questionable whether you want to mix your business logic (contained within the implementation of IMyService), and the logic controlling the "out-of-band" information attached to the message.

一个更清洁的分离是通过实施的 IDispatchMessageInspector ,它允许你拦截在服务器上调用,因为它来进出修改消息:

A cleaner separation is gained by implementing IDispatchMessageInspector, which allows you to intercept calls on the server and modify the message as it comes in and out:

public 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.Headers.Add(MessageHeader.CreateHeader("header", "namespace", "headervalue"));
    }

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



头文件是由.NET客户端相同的方式和以前访问。值得注意的是,你可以传递信息 AfterReceiveRequest 方法的 BeforeSendReply ,作为对象在前方法返回作为后者 correlationState 参数传递。如果返回头都依赖于输入消息的头这将是有益的 - 因为你的例子说明

The headers are accessed from a .NET client in the same way as before. It's worth noting that you can pass information from the AfterReceiveRequest method to the BeforeSendReply, as the object returned in the former method is passed as the correlationState parameter in the latter. This would be useful if the headers you return are dependent on the headers of the incoming message - as your example suggests.

最后,在其上安装服务此功能,您需要修改托管代码如下:

Finally, to install this functionality on the service, you need to modify the hosting code as follows:

...
var endpoint = serviceHost.AddServiceEndpoint(typeof(IMyService), new BasicHttpBinding(), "http://localhost:9000");
endpoint.Behaviors.Add(new ServerInterceptor());
serviceHost.Open();
...



,我们可以凭借这一事实做 ServerInterceptor 工具 IEndpointBehavior

这篇关于如何包括控制台服务主机WCF自定义页眉的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆