Azure returns 中的 WCF 服务应用服务来自一个地理位置的 502 错误,但在另一个地理位置工作
WCF Service App Service in Azure returns 502 error from one geographic location but works in another geographic location
我在 Azure 中有 2 个资源组,除了位于不同时区的位置外,它们是相同的。每个都有 2 个应用程序服务:一个是 Angular 应用程序,另一个是 WCF 服务。他们还有 WCF 使用的 SQL 服务器和数据库。 Angular 应用调用 WCF 服务。这两个资源组中的应用程序和数据库是相同的。一个工作完美,其他错误。
问题出在 WCF 服务上。在一个位置调用它会导致客户端出现 CORS 错误“从来源 'https://angularapp.mydomain.com' 访问 'https://services.mydomain.com/myService.svc/rest/GetData' 处的 XMLHttpRequest 已被 CORS 策略阻止:不存在 'Access-Control-Allow-Origin' header在请求的资源上。
当我将问题资源组中的 Angular 应用程序指向工作资源组中的 WCF 时,它可以正常工作。当我将工作资源组中的 Angular 应用程序指向 non-working 组中的 WCF 时,我遇到了与上述相同的错误。
我已将 Postman 指向两个 WCF 服务。当指向工作资源组中的一个时,它正确地 return 数据。当指向 non-working 资源组中的一个时,它 return 出现错误“502 - Web 服务器在充当网关或代理服务器时收到无效响应”。
我已将 Azure 中的 CORS“Allowed Origins”配置为“*”,这对两个应用程序都没有影响。
我已经尝试在 Azure 中删除有问题的 WCF 应用服务并重新创建它,但仍然有同样的问题。
请帮忙。
这可能是因为在Azure中设置CORS对WCF不起作用,我们可以实现IDispatchMessageInspector在服务响应之前添加响应头,这里是一个Demo:
public class ServerMessageLogger : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
WebOperationContext ctx = WebOperationContext.Current;
ctx.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
}
}
我们需要实现IDispatchMessageInspector接口,然后在实现中通过WebOperationContext实现跨域请求class.
[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)
{
return;
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
dispatchRuntime.MessageInspectors.Add(new ServerMessageLogger());
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
return;
}
}
然后我们需要在服务行为中添加ServerMessageLogger
这次终于把这个行为应用到service.At,Azure中不需要配置CORS,WCF服务也支持跨域
我解决了这个问题并将详细信息放在这里,以防它对其他人有帮助。我在 Azure 上设置了 .Net 探查器,出现了一个异常,它向我展示了真正的问题并引导我找到了解决方案。错误是“转换为 UTC 时大于 DateTime.MaxValue 或小于 DateTime.MinValue 的日期时间值无法序列化为 JSON。”
问题是由 JSON 序列化程序引起的。当对象中的日期时间序列化为 json 时,它会将值设为 DateTime.MinValue。如果您的时区大于格林威治标准时间(我所在的位置不起作用),它会尝试将值设置为 DateTime.MinValue 减去时区比格林威治标准时间提前多少小时。这是无效的,因为您可以小于 MinValue 并导致异常。要修复它,我必须更改将序列化为 [DataMember(IsRequired = false, EmitDefaultValue = false)] 的对象的所有 DateTime 属性的 DataMember 属性。这解决了问题,两个位置的 WCF 服务现在都在工作。
我在 Azure 中有 2 个资源组,除了位于不同时区的位置外,它们是相同的。每个都有 2 个应用程序服务:一个是 Angular 应用程序,另一个是 WCF 服务。他们还有 WCF 使用的 SQL 服务器和数据库。 Angular 应用调用 WCF 服务。这两个资源组中的应用程序和数据库是相同的。一个工作完美,其他错误。
问题出在 WCF 服务上。在一个位置调用它会导致客户端出现 CORS 错误“从来源 'https://angularapp.mydomain.com' 访问 'https://services.mydomain.com/myService.svc/rest/GetData' 处的 XMLHttpRequest 已被 CORS 策略阻止:不存在 'Access-Control-Allow-Origin' header在请求的资源上。
当我将问题资源组中的 Angular 应用程序指向工作资源组中的 WCF 时,它可以正常工作。当我将工作资源组中的 Angular 应用程序指向 non-working 组中的 WCF 时,我遇到了与上述相同的错误。
我已将 Postman 指向两个 WCF 服务。当指向工作资源组中的一个时,它正确地 return 数据。当指向 non-working 资源组中的一个时,它 return 出现错误“502 - Web 服务器在充当网关或代理服务器时收到无效响应”。
我已将 Azure 中的 CORS“Allowed Origins”配置为“*”,这对两个应用程序都没有影响。
我已经尝试在 Azure 中删除有问题的 WCF 应用服务并重新创建它,但仍然有同样的问题。
请帮忙。
这可能是因为在Azure中设置CORS对WCF不起作用,我们可以实现IDispatchMessageInspector在服务响应之前添加响应头,这里是一个Demo:
public class ServerMessageLogger : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
WebOperationContext ctx = WebOperationContext.Current;
ctx.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
}
}
我们需要实现IDispatchMessageInspector接口,然后在实现中通过WebOperationContext实现跨域请求class.
[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)
{
return;
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
dispatchRuntime.MessageInspectors.Add(new ServerMessageLogger());
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
return;
}
}
然后我们需要在服务行为中添加ServerMessageLogger
这次终于把这个行为应用到service.At,Azure中不需要配置CORS,WCF服务也支持跨域
我解决了这个问题并将详细信息放在这里,以防它对其他人有帮助。我在 Azure 上设置了 .Net 探查器,出现了一个异常,它向我展示了真正的问题并引导我找到了解决方案。错误是“转换为 UTC 时大于 DateTime.MaxValue 或小于 DateTime.MinValue 的日期时间值无法序列化为 JSON。”
问题是由 JSON 序列化程序引起的。当对象中的日期时间序列化为 json 时,它会将值设为 DateTime.MinValue。如果您的时区大于格林威治标准时间(我所在的位置不起作用),它会尝试将值设置为 DateTime.MinValue 减去时区比格林威治标准时间提前多少小时。这是无效的,因为您可以小于 MinValue 并导致异常。要修复它,我必须更改将序列化为 [DataMember(IsRequired = false, EmitDefaultValue = false)] 的对象的所有 DateTime 属性的 DataMember 属性。这解决了问题,两个位置的 WCF 服务现在都在工作。