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 服务现在都在工作。