我有一个供应商试图与我的 WCF api 通信,他们收到 http:500 错误,但 IIS 日志记录未显示详细信息

Posted

技术标签:

【中文标题】我有一个供应商试图与我的 WCF api 通信,他们收到 http:500 错误,但 IIS 日志记录未显示详细信息【英文标题】:I have a vendor trying to communicate with my WCF api, and they are receiving an http:500 error, but IIS logging shows no details 【发布时间】:2020-01-04 01:08:52 【问题描述】:

高级:我有一个 Web API,根据供应商的规格构建。它通过了所有测试,甚至供应商的“样本”请求也可以通过 SOAPUI 完美运行。但是,当他们的 IBM DataPower 软件尝试发送请求时,他们会收到 HTTP:500 错误。 IIS 日志显示 HTTP:500,但没有错误描述和其他信息。

我已将 API 设置为通过围绕所有内容的端点类的 try/catch 捕获代码执行期间的任何错误。没有记录。我也尝试过 fiddler,但我无法让这个供应商按需向我发送测试请求(我得到的答案是,“我们将在大约 2 小时内发送它”)。我只有错误、IP 地址和时间戳的 IIS 日志。

这里是终点。所有调用的方法和类都按规范工作。当 DataPower 进行调用时,此代码永远不会执行。

Web.Config:

<system.web>
    <webServices>

      <protocols>
        <add name="HttpPost" />
      </protocols>
    </webServices>
    <compilation debug="true" targetFramework="4.5.2" />
    <httpRuntime targetFramework="4.5.2" maxRequestLength="10240" maxUrlLength="10240" executionTimeout="1200" />
  </system.web>
  <system.serviceModel>
    <system.serviceModel>
    <services>
        <service behaviorConfiguration="claims" name="ISO_ClaimsResponse.ClaimsResponse">
                <endpoint address="" binding="basicHttpsBinding" contract="ISO_ClaimsResponse.IClaimsResponse" />
        </service>
        <behaviors>
          <serviceBehaviors>
            <behavior name="claims">
              <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
              <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
              <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
              <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <protocolMapping>
          <add binding="basicHttpsBinding" scheme="https" />
        </protocolMapping>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    </services>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <!--
        To browse web app root directory during debugging, set the value below to true.
        Set to false before deployment to avoid disclosing web app folder information.
      -->
    <directoryBrowse enabled="true"/>
  </system.webServer>

这是接口/数据合约:

using System.ServiceModel;
using System.ServiceModel.Web;

namespace ISO_ClaimsResponse
    
    [ServiceContract(Namespace = "")] -- This is intentional and required per the vendor
    public interface IClaimsResponse
    
        [WebInvoke(Method ="POST", UriTemplate = "xml")]
        [OperationContract(Action = "http://tempuri.org/IClaimsResponse/ProcessResponse", ReplyAction = "http://tempuri.org/IClaimsResponse/ProcessResponse")]
        string ProcessResponse(string xml);        
        

这里是端点代码,我已经确认在 DataPower 进行调用时永远不会到达:

using System;
using System.Collections.Generic;
using ISOClaims;
using System.Runtime.Serialization.Formatters;
using System.Web;
using System.IO;

namespace ISO_ClaimsResponse

    public class ClaimsResponse : IClaimsResponse
           
        public string ProcessResponse(string xml)
          
            LogRequestModel request = new LogRequestModel();

            try
            
                ClaimInvestigationAddRs receivedObj = LogData.Serialize<ClaimInvestigationAddRs>(xml);
                request.ClaimInvestigationAddRqID = receivedObj.RqUID.Value;
                request.CD_ID = LogData.GetCDID(request.ClaimInvestigationAddRqID);

                Validation validator = new Validation();
                receivedObj.TransactionResponseDt = validator.DTString(receivedObj.TransactionResponseDt);
                request.TransactionRequestDateTime = DateTime.Parse(receivedObj.TransactionResponseDt);
                request.ResponseXML = "SUCCESS";

                Log.ReceivedRequest(request);
                return "SUCCESS";
            
            catch (Exception ex)
            
                Dictionary<string, object> additionalDetails = new Dictionary<string, object>();
                additionalDetails.Add("Received XML", xml);

                Log.Error(ex, additionalDetails);
                request.ResponseXML = "INTERNAL ERROR LOGGED" + ex.ToString();
                Log.ReceivedRequest(request);
                return "INTERNAL ERROR LOGGED";
            

            return "SUCCESS";
        
    


这是我为测试而提供的示例 SOAP XML,它工作正常。我已经混淆了 PII,以防万一。

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header/>
   <soapenv:Body>
      <ProcessResponse>
         <!--Optional:-->
         <xml xmlns="">
            <![CDATA[
         <ClaimInvestigationAddRs>
            <RqUID>ccbd5f5eb53e4b8d8357f5873c8ec9bb</RqUID>
            <TransactionResponseDt>2019-01-18T11:18:28</TransactionResponseDt>
            <CurCd>US</CurCd>
            <CodeList id="PolicyTypeCdList">
            <CodeListName>PolicyTypeCd</CodeListName>
            <CodeListOwnerCd>ISOUS</CodeListOwnerCd>
            </CodeList>
            <CodeList id="ClaimsPartyRoleCdList">
            <CodeListName>ClaimsPartyRoleCd</CodeListName>
            <CodeListOwnerCd>ISOUS</CodeListOwnerCd>
            </CodeList>
            <MsgStatus>
            <MsgStatusCd>Rejected</MsgStatusCd>
            <MsgErrorCd>DataError</MsgErrorCd>
            <MsgStatusDesc>TEST</MsgStatusDesc>
            </MsgStatus>
            <Policy>
            <PolicyNumber>NGNV0001921-00</PolicyNumber>
            <LOBCd codelistref="PolicyTypeCdList">PAPP</LOBCd>
            <MiscParty id="Reject_MiscParty_1">
            <ItemIdInfo>
            <AgencyId>XXXXXXXXXX</AgencyId>
            </ItemIdInfo>
            <MiscPartyInfo>
            <MiscPartyRoleCd>CarrierInsurer</MiscPartyRoleCd>
            </MiscPartyInfo>
            </MiscParty>
            </Policy>
            <ClaimsOccurrence id="Reject_ClaimsOccurence_1">
            <ItemIdInfo>
            <InsurerId>XXXXXXXX</InsurerId>
            </ItemIdInfo>
            <LossDt>2018-10-31</LossDt>
            </ClaimsOccurrence>
            <ClaimsParty id="Reject_IP_1">
            <GeneralPartyInfo>
            <NameInfo>
            <PersonName>
            <Surname>Doe</Surname>
            <GivenName>John</GivenName>
            </PersonName>
            </NameInfo>
            </GeneralPartyInfo>
            <ClaimsPartyInfo>
            <ClaimsPartyRoleCd codelistref="ClaimsPartyRoleCdList">IN</ClaimsPartyRoleCd>
            </ClaimsPartyInfo>
            </ClaimsParty>
            <ClaimsParty id="Reject_IP_2">
            <GeneralPartyInfo>
            <NameInfo>
            <PersonName>
            <Surname>Doe</Surname>
            <GivenName>Jane</GivenName>
            </PersonName>
            </NameInfo>
            </GeneralPartyInfo>
            <ClaimsPartyInfo>
            <ClaimsPartyRoleCd codelistref="ClaimsPartyRoleCdList">CD</ClaimsPartyRoleCd>
            </ClaimsPartyInfo>
            </ClaimsParty>
            </ClaimInvestigationAddRs>]]></xml>
      </ProcessResponse>
   </soapenv:Body>
</soapenv:Envelope>

如果我能拿到他们寄给我的信封和正文的副本,我会很高兴。供应商说他们不知道该怎么做。

我想要什么?

    在 IIS 或 WCF 拒绝之前捕获整个请求的简单方法 或者设置 IIS 或 WCF 让任何东西通过我的代码 或者我忽略的代码或设置中的某处有什么明显的地方?

这是一个测试环境。我已经验证了 TLS 设置并消除了可能存在的网络连接问题。

这是我们的供应商说他们收到的实际响应(我对 URL 进行了一些混淆)。这也与 IIS 日志文本匹配(包含在之后):

The Frontside Handler CSUF-DPN120-REJECT-FSH
on Datapower appliance (isoappgwa2)
has been disabled due to the following error
<?xml version="1.0" encoding="UTF-8"?> --> Message Failed with HTTP Error Response Code 500 or Status Code 15. It was trying to send SOAP response to https://********.com/ISOSvc/ClaimsResponse.svc , SOAP method is ProcessResponse

IIS 日志:

#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status time-taken
2019-09-04 00:07:08 172.16.6.40 POST /ISOSvc/ClaimsResponse.svc - 443 - 206.208.170.60 - - 500 19 50 171

对于验证,ProcessResponse 端点处于活动状态并且可以工作。我可以通过内部网络上的 SOAPUI 和我的家用 PC(面向公众)调用它。

我已尝试启用跟踪,但没有获得任何已接收请求的跟踪文件。我已验证此测试服务器上的所有用户(包括运行应用程序的用户)都具有对该文件夹的读/写访问权限。我也验证了端口。

更新:我终于让供应商告诉我一些新东西。显然,他们对我进行的所有调用在 XML 中都有一个常见错误(无效字符),这可以解释 HTTP:500 错误在如此高的级别上被捕获,因为它会被标记为无效的 SOAP 格式。我希望这是根本原因,尽管我现在不确定。我还在 web.config 中看到了一些主要的不匹配的 XML 标记。我不确定它们出现在哪里或何时出现,但我修复了它们。除了它在其他测试中没有引起问题之外,我会更有信心这是问题所在。

另外,我在 web.config 中添加了端点更改。

【问题讨论】:

我可以看到问题的两个可能原因,1. web.config 中缺少服务端点标记或 2. 请求长度可能超过 web.config (10240) 中允许的长度 启用跟踪和消息记录:docs.microsoft.com/en-us/dotnet/framework/wcf/samples/… 我将启用跟踪。我相信我已经解决了长度问题。这是在最初的开发过程中出现的。我希望追踪能提供更多的见解。谢谢。 【参考方案1】:

web.config 中缺少服务配置。如果可行,请尝试以下操作。

在 web.config 中,在 system.serviceModel 标签内添加以下行为标签:

<services>
   <service behaviorConfiguration="claims" name="ISO_ClaimsResponse.ClaimsResponse">
   <endpoint address="" binding="basicHttpBinding" 
   contract="ISO_ClaimsResponse.IClaimsResponse" />
   </service>
<services>

并将name属性添加到行为标签中,使其看起来像:

<behavior name="claims">

【讨论】:

我喜欢这种反应,但我没有看到行为发生变化。 我进行了更改,但似乎没有任何改变。 您可以在进行此更改后发布更新的 web.config 代码 已更新。我开始怀疑问题是否实际上是来自我的供应商的格式错误的 XML。如果他们在邮件正文中发送无效字符,您会期待这种行为吗?【参考方案2】:

当我们使用默认配置时,WCF 在 SOAP Web 服务上运行良好,即调用服务的方式只有在我们使用服务代理时才有效。不建议发送 SOAP 信息(XML 文档)并与服务器端的服务进行通信。因此,我怀疑对服务的调用有问题。 在您上面的描述中,我没有看到调用服务和服务端点的方式。请注意此行代码。

[WebInvoke(Method ="POST", UriTemplate = "xml")]

这没有意义,因为 SOAP Web 服务是由 HTTP 请求中的 SOAPAction 字段路由的。

SOAPAction: "http://tempuri.org/IService1/GetData"

服务地址只是基地址,http://myip:port/service1.svc

如果有什么我可以帮忙的,请随时告诉我。

【讨论】:

我们的供应商要求更改。他们一直告诉我们“命名空间”必须是一个空字符串。当我们进行更改时,他们给我们的测试 xml 在 SOAP UI 中工作。他们从未能够成功调用我们的端点。最初,我使用了所有默认设置,一切都很好(除了他们的测试 xml)。假设我无权修改传入的请求,存在错误(很可能在信封中),并且我正在尝试识别该错误。【参考方案3】:

所以供应商终于给我发了一份他们寄给我的副本.......

问题是他们发送的 XML 需要一个 RESTful API。请注意,在大约 12 个月的时间里,他们坚持认为这是他们需要的 SOAP 端点。即使现在他们也称它为 SOAP。他们一直将这些选项称为 HTTPS POST 或 SOAP。他们告诉我他们不提供 RESTful。

感谢您的所有意见。这是我对整个情况的感受的照片(见附件)

Angry Dilbert

【讨论】:

以上是关于我有一个供应商试图与我的 WCF api 通信,他们收到 http:500 错误,但 IIS 日志记录未显示详细信息的主要内容,如果未能解决你的问题,请参考以下文章

试图重用Java客户端套接字时不成功。

如何在 net 5.0 中使用服务通信?

最兼容的进程间通信协议

强制 WCF 通道到 IP 地址

ASP.Net Web API 与 WCF - Web API 能否用于向单例 WCF 服务提供基于 REST 的通信?

WCF 服务中的自定义证书验证