在我的WCF服务中,我收到405 method not allowed
错误,然后发现了一条帖子,建议在我的WCF主机的Application_BeginRequest
中包含以下内容:
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();
}
那么如何在控制台应用程序中包含标题。
答案 0 :(得分:9)
在WCF中,可以通过类OperationContext的实例访问标头,可以通过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"));
}
}
为完整起见,用于在控制台应用程序中托管此服务的代码(无需配置)为:
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客户端可以像这样访问标题:
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);
}
如果您有Fiddler,您还可以使用此工具查看标题。
虽然这种方法可以达到你想要的效果,但是你是否想要混合你的业务逻辑(包含在IMyService
的实现中)和控制&#34;带外&的逻辑是值得怀疑的。 #34;信息附带的信息。
通过实施IDispatchMessageInspector
获得更清晰的分离,它允许您拦截服务器上的呼叫并在消息进出时修改消息:
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
参数传递给后者。如果您返回的标头取决于传入邮件的标头,这将非常有用 - 正如您的示例所示。
最后,要在服务上安装此功能,您需要修改托管代码,如下所示:
...
var endpoint = serviceHost.AddServiceEndpoint(typeof(IMyService), new BasicHttpBinding(), "http://localhost:9000");
endpoint.Behaviors.Add(new ServerInterceptor());
serviceHost.Open();
...
我们可以通过ServerInterceptor
实现IEndpointBehavior
答案 1 :(得分:0)
这可以做到。您需要在主机(控制台)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
}
}
}
}
这将在您的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";
}
希望你觉得这很有用。祝好运。