我有一个Angular应用程序在我的开发机器上本地运行,试图向运行在另一台机器上IIS上的WCF Web服务发出请求。
使用邮递员,我可以使用POST和OPTIONS动词向服务提出请求。
但是,当我的Angular应用发出请求时,我从发出的CORS预检OPTIONS请求中得到了400错误。
请求是这样的:
// passed-in url is https://myserver/myservice/Hello
public hello( url: string, name: string )
{
const headers = new HttpHeaders()
headers.append('Content-Type', 'application/json');
headers.append('Test', 'TestyTest');
return this.httpClient.post<string>( url,
{ name: name },
{ headers: headers }
);
}
在“网络”面板上的Chrome调试工具中,我看到了一个请求的两个条目:
Hello (failed) xhr zone.js:2935 0 B 188 ms
Hello 400 text/html Other 0 B 176 ms
如果我检查了这两个条目的请求标头,则看不到我的代码尝试添加的Test
标头。这不是问题(我不需要该标头),但这可能是一个线索。
请注意,第二个Content-Type
标头是text/html
。
我在Web服务的日志中看不到任何条目,或者在IIS日志或服务器上的事件查看器中看不到任何错误。
什么可能导致此问题,如何解决或获取更多信息?
答案 0 :(得分:1)
这是由CORS引起的。不要使用全局文件来解决跨域问题。您可以尝试使用IDispatchMessageInspector解决跨域问题。
将SOAP.cs添加到您的项目:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Web;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Xml;
namespace Demo_rest_ConsoleApp
{
public class ServerMessageLogger : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
Console.WriteLine(request);
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
WebOperationContext ctx = WebOperationContext.Current;
ctx.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
ctx.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.OK;
if (ctx.IncomingRequest.Method == "OPTIONS")
{
ctx.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.OK;
ctx.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "GET,POST,PUT,PATCH,POST,DELETE,OPTIONS");
ctx.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type");
}
}
}
public class ClientMessageLogger : IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState)
{
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
return null;
}
}
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class, AllowMultiple = false)]
public class CustContractBehaviorAttribute : Attribute, IContractBehavior, IContractBehaviorAttribute
{
public Type TargetContract => throw new NotImplementedException();
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
return;
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.ClientMessageInspectors.Add(new ClientMessageLogger());
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
dispatchRuntime.MessageInspectors.Add(new ServerMessageLogger());
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
return;
}
}
}
最后,将CustContractBehavior应用于服务:
如果问题仍然存在,请随时告诉我。
答案 1 :(得分:0)
尝试实现代理配置文件
const HttpsProxyAgent = require('https-proxy-agent');
/*
* API proxy configuration.
* This allows you to proxy HTTP request like `http.get('/api/stuff')` to another server/port.
* This is especially useful during app development to avoid CORS issues while running a local server.
* For more details and options, see https://angular.io/guide/build#using-corporate-proxy
*/
const proxyConfig = [
{
context: '/api',
pathRewrite: { '^/api': '' },
target: 'https://api.chucknorris.io',
changeOrigin: true,
secure: false,
},
];
/*
* Configures a corporate proxy agent for the API proxy if needed.
*/
function setupForCorporateProxy(proxyConfig) {
if (!Array.isArray(proxyConfig)) {
proxyConfig = [proxyConfig];
}
const proxyServer = process.env.http_proxy || process.env.HTTP_PROXY;
let agent = null;
if (proxyServer) {
console.log(`Using corporate proxy server: ${proxyServer}`);
agent = new HttpsProxyAgent(proxyServer);
proxyConfig.forEach((entry) => {
entry.agent = agent;
});
}
return proxyConfig;
}
module.exports = setupForCorporateProxy(proxyConfig);
接下来,打开您的angular.json
文件,并在serve->options
下添加一个proxyConfig密钥,该密钥指向您刚刚创建的src/proxy.conf.json
文件,如下所示:
"architect": {
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "your-application-name:build",
"proxyConfig": "src/proxy.conf.json"
}