【问题标题】:WCF Service App Service in Azure returns 502 error from one geographic location but works in another geographic locationAzure 中的 WCF 服务应用服务从一个地理位置返回 502 错误,但在另一个地理位置工作
【发布时间】:2020-07-24 00:36:37
【问题描述】:

我在 Azure 中有 2 个资源组,除了位于不同时区的位置之外,它们是相同的。每个都有 2 个应用服务:一个是 Angular 应用,另一个是 WCF 服务。他们还拥有 WCF 使用的 SQL Server 和数据库。 Angular 应用程序调用 WCF 服务。这两个资源组中的应用程序和数据库是相同的。一个完美运行,其他错误。

问题出在 WCF 服务上。在一个位置调用它会导致客户端出现 CORS 错误“从源“https://angularapp.mydomain.com”访问“https://services.mydomain.com/myService.svc/rest/GetData”的 XMLHttpRequest已被 CORS 策略阻止:请求的资源上不存在“Access-Control-Allow-Origin”标头”。

当我将问题资源组中的 Angular 应用程序指向工作资源组中的 WCF 时,它可以工作。当我将工作资源组中的 Angular 应用程序指向非工作资源组中的 WCF 时,我得到了上述相同的错误。

我已将 Postman 指向这两个 WCF 服务。当指向工作资源组中的一个时,它会正确返回数据。当指向非工作资源组中的资源组时,它返回错误“502 - Web 服务器在充当网关或代理服务器时收到无效响应”。

我已将 Azure 中的 CORS“Allowed Origins”配置为两个应用程序的“*”,这没有任何区别。

我已尝试在 Azure 中删除有问题的 WCF 应用服务并重新创建它,但仍然存在同样的问题。

请帮忙。

【问题讨论】:

    标签: angular azure wcf


    【解决方案1】:

    这可能是因为在 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实现跨域请求。

    [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。

    最后我们把这个行为应用到服务上。这个时候我们不需要在Azure中配置CORS,WCF服务也会支持跨域。

    【讨论】:

    • 感谢您的回复 Ding,但它正在使用 WCF 在 Azure 中工作。我有 2 个具有完全相同代码和配置的资源组。唯一的区别是一个指向一个地理位置,另一个指向另一个地理位置。一个正在工作,另一个给出 CORS 错误。它必须是 Azure 中的一些设置,但我找不到什么。我经历了所有事情,它们看起来都一样。
    • 我的意思是直接通过 Azure 配置 WCF CORS 可能行不通。
    • 如果WCF服务是自托管的,我们只能通过IDispatchMessageInspector解决跨域问题。
    【解决方案2】:

    我解决了这个问题并将详细信息放在这里,以防它帮助其他人。我在 Azure 上设置了 .Net 分析器,但有一个异常向我展示了真正的问题并引导我找到了解决方案。错误是“转换为 UTC 时大于 DateTime.MaxValue 或小于 DateTime.MinValue 的 DateTime 值无法序列化为 JSON。”

    问题是由 JSON 序列化程序引起的。当对象中的日期时间序列化为 json 时,它会将值作为 DateTime.MinValue。如果您的时区大于 GMT(我的位置不起作用的情况就是这种情况),它会尝试将值设置为 DateTime.MinValue 减去时区比 GMT 提前多少小时。这是无效的,因为您可能小于 MinValue 并导致异常。为了解决这个问题,我必须更改将被序列化为 [DataMember(IsRequired = false, EmitDefaultValue = false)] 的对象的所有 DateTime 属性的 DataMember 属性。这解决了问题,两个位置的 WCF 服务现在都可以正常工作了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多