C# 如何在console服务主机中包括WCF自定义头

C# 如何在console服务主机中包括WCF自定义头,c#,wcf,cross-domain,same-origin-policy,C#,Wcf,Cross Domain,Same Origin Policy,在我的WCF服务中,我收到了405 method not allowed错误,然后遇到一篇帖子,建议在我的WCF主机的应用程序中设置以下内容: protected void Application_BeginRequest(object sender, EventArgs e) { if (HttpContext.Current.Request.HttpMethod == "OPTIONS") { HttpContext.Current.Response.AddH

在我的WCF服务中,我收到了
405 method not allowed
错误,然后遇到一篇帖子,建议在我的WCF主机的
应用程序中设置以下内容:

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");
    }
} 
但我使用控制台应用程序托管我的服务

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

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

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

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

这是可以做到的。您需要一个在主机(控制台)exe和web服务类之间运行的共享变量。在调用WebService.Open()并检查此共享变量的输入后,必须运行一个连续循环。代码如下所示:

//this would be your console host class
public class HostInterface
{
    string sHeaderString;
    public static string HeaderString {
        get { return sHeaderString; }
        set { sHeaderString += value; }


   public void main()
   {
      //code to start the web service
      System.ServiceModel.ServiceHost myWebService = default(System.ServiceModel.ServiceHost);

      //configure myWebService stuff
      myWebService.open();

      // here loop every second until the communication is stopped
      //check for new text in the shared sHeaderString 
      //written to by your web service class
      while (true) {
        if (myWebService.state != Communicationsstate.Opened){
            break; 
        }
        //write message out through console
        console.writeline("Headers:" + sHeaderString);
        Threading.Thread.Sleep(1000);
        //sleep 1 second before going trying next
      }
    }
  }
}
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);
}
这将在web服务的主类中,从控制台引用和更新“HeaderString”共享变量

public void WriteHeadersToSharedVariable()
{
        //here, setting the headers into the shared variable instanced back on the console program
        HostInterface.Headerstring = GetHeadersFromRequest();
}

public string GetHeadersFromRequest()
{
    //some code to get the headers from inbound request
    return "blah blah blah";
}

希望你觉得这有用。祝你好运

在WCF中,可以通过类的实例访问头,该实例可以通过OperationContext.Current(如果可用)访问

解决此问题的简单方法是在服务的方法中使用此属性:

[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"));
    }
}
为完整起见,用于在控制台应用程序中承载此服务(无需配置)的代码为:

.NET客户端将访问如下标题:

//this would be your console host class
public class HostInterface
{
    string sHeaderString;
    public static string HeaderString {
        get { return sHeaderString; }
        set { sHeaderString += value; }


   public void main()
   {
      //code to start the web service
      System.ServiceModel.ServiceHost myWebService = default(System.ServiceModel.ServiceHost);

      //configure myWebService stuff
      myWebService.open();

      // here loop every second until the communication is stopped
      //check for new text in the shared sHeaderString 
      //written to by your web service class
      while (true) {
        if (myWebService.state != Communicationsstate.Opened){
            break; 
        }
        //write message out through console
        console.writeline("Headers:" + sHeaderString);
        Threading.Thread.Sleep(1000);
        //sleep 1 second before going trying next
      }
    }
  }
}
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);
}
从.NET客户端以与以前相同的方式访问头。值得注意的是,您可以将信息从
AfterReceiveRequest
方法传递到
BeforeSendReply
,因为在前一个方法中返回的对象在后一个方法中作为
correlationState
参数传递。如果您返回的头依赖于传入消息的头,这将非常有用—正如您的示例所示

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

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

我们可以这样做,因为
ServerInterceptor
实现了
IEndpointBehavior

我完全处于相同的情况,你找到解决方案了吗?可能你误解了这个问题。我无意中发现了这篇文章,想寻找一个更好的解决方案,将“访问控制允许来源”添加到我的服务的响应头中。这让我很接近,但必须更改BeforeSendReply to HttpResponseMessageProperty prop=(HttpResponseMessageProperty)reply.Properties[“httpResponse”]中的代码;prop.Headers.Add(“访问控制允许原点)”;BeforeSendReply中的Message对象不包含HTTP头信息,只包含SOAP消息(至少对我来说是这样)。如果使用reply.Headers.Add()方法,则会将头添加到SOAP消息中。使用reply.Properties.Add()时,不会发生任何事情。也没有reply.Properties[“httpResponse”]属性。我做错了什么?