我有 WCF 自托管服务来与本地连接的打印机通信以打印徽章。我们基于浏览器的应用程序调用本地服务来打印徽章。所有 GET 调用都工作正常,但 POST 请求总是给出 CORS 错误。
获取呼叫(工作正常)
POST 调用 - 因 CORS 错误而失败,飞行前请求正常
private void startService_HTTPS(System.Diagnostics.EventLog eventLog)
{
eventLog.WriteEntry("Begin startService.......");
string serviceUrl = Config.protocol_https + "://" + Config.host + ":" + Config.portNumber_https;
WebServiceHost webServiceHost = new WebServiceHost(typeof(Service), new Uri(serviceUrl));
try
{
ServicePointManager.SecurityProtocol = ServicePointManager.SecurityProtocol | SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
KeyedByTypeCollection<IServiceBehavior> behaviors = webServiceHost.Description.Behaviors;
ServiceMetadataBehavior serviceMetadataBehavior = new ServiceMetadataBehavior()
{
HttpGetEnabled = false,
HttpsGetEnabled = true
};
behaviors.Add(serviceMetadataBehavior);
ServiceDebugBehavior serviceDebugBehavior = webServiceHost.Description.Behaviors.Find<ServiceDebugBehavior>();
if (serviceDebugBehavior == null)
{
webServiceHost.Description.Behaviors.Add(new ServiceDebugBehavior()
{
IncludeExceptionDetailInFaults = true
});
}
else
{
serviceDebugBehavior.IncludeExceptionDetailInFaults = true;
}
WebHttpBinding webHttpBinding = new WebHttpBinding(WebHttpSecurityMode.Transport)
{
HostNameComparisonMode = HostNameComparisonMode.Exact,
MaxReceivedMessageSize = (long)2147483647,
TransferMode = TransferMode.Streamed,
// CrossDomainScriptAccessEnabled = true
};
ServiceEndpoint serviceEndpoint = webServiceHost.AddServiceEndpoint(typeof(IService), webHttpBinding, serviceUrl);
serviceEndpoint.Behaviors.Add(new WebHttpBehavior());
serviceEndpoint.Behaviors.Add(new EnableCrossOriginResourceSharingBehavior());
webServiceHost.Open();
eventLog.WriteEntry("Started HTTPS services successfully......"+serviceUrl);
// CertManager certs = new CertManager();
// certs.setupCerts(eventLog);
}
catch (CommunicationException cex)
{
Console.WriteLine("An exception occurred: {0}", cex.Message);
eventLog.WriteEntry("Exception "+cex.Message);
eventLog.WriteEntry(cex.StackTrace);
webServiceHost.Abort();
}
}
public class EnableCrossOriginResourceSharingBehavior : BehaviorExtensionElement, IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
{
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");
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new CustomHeaderMessageInspector(requiredHeaders));
}
public void Validate(ServiceEndpoint endpoint)
{
}
public override Type BehaviorType
{
get { return typeof(EnableCrossOriginResourceSharingBehavior); }
}
protected override object CreateBehavior()
{
return new EnableCrossOriginResourceSharingBehavior();
}
}
public class CustomHeaderMessageInspector : IDispatchMessageInspector
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
Dictionary<string, string> requiredHeaders;
public CustomHeaderMessageInspector(Dictionary<string, string> headers)
{
requiredHeaders = headers ?? new Dictionary<string, string>();
}
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
return null;
}
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
var httpHeader = reply.Properties["httpResponse"] as System.ServiceModel.Channels.HttpResponseMessageProperty;
httpHeader.StatusCode = System.Net.HttpStatusCode.OK;
foreach (var item in requiredHeaders)
{
log.Debug("BeforeSendReply add header " + item.Key + ", val " + item.Value);
httpHeader.Headers.Add(item.Key, item.Value);
}
}
}
我在这里寻求帮助......
我尝试向服务添加自定义行为,但总是失败,正在寻求一些帮助来解决此问题。
我不认为你可以使用 endpointDispatcher.DispatchRuntime.MessageInspectors.Add 来配置Cros策略。它是一种在服务端点或客户端回调端点的运行时行为中插入、修改或扩展自定义消息检查器的方法。
我的建议:
1.新建一个Global.asax文件
2.添加代码
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://127.0.0.1:47756");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST, PUT, DELETE");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}