2017-05-11 4 views
5

오래된 비누 서비스의 WSDL을 기반으로 WCF 서비스를 작성하고 있습니다. svcutil을 사용하여 서비스 계약을 생성하고 호스팅하고있는 사이트와 일치하는 몇 가지 변경 사항을 만들었지 만 테스트 클라이언트에서 서비스를 호출하면 요청 객체가 null로 처리됩니다.XmlSerializerFormat을 사용할 때 WCF 서비스 요청이 Null입니다.

서비스가 반환하는 응답도 분명히 관련성이있는 것으로 직렬화되고 있습니다. 하지만 왜 그것의 직렬화 및 deserializing 제대로 이해할 수 없습니다.

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] 
[System.ServiceModel.ServiceContractAttribute(Namespace = ApuConstants.Namespace)] 
public interface IApuService 
{ 
    [System.ServiceModel.OperationContractAttribute(Action = "*", ReplyAction = "*")] 
    [System.ServiceModel.XmlSerializerFormatAttribute(Style = System.ServiceModel.OperationFormatStyle.Rpc, Use = System.ServiceModel.OperationFormatUse.Encoded)] 
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(Part))] 
    [return: System.ServiceModel.MessageParameterAttribute(Name = "return")] 
    Brock.Web.Apu.Response check(Brock.Web.Apu.Request request); 
} 

/// <remarks/> 
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")] 
[System.SerializableAttribute()] 
[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Xml.Serialization.SoapTypeAttribute(Namespace = ApuConstants.Namespace)] 
public partial class Request 
{ 

    private RequestHeader headerField; 

    private Lookup lookupField; 

    /// <remarks/> 
    public RequestHeader header 
    { 
     get 
     { 
      return this.headerField; 
     } 
     set 
     { 
      this.headerField = value; 
     } 
    } 

    /// <remarks/> 
    public Lookup lookup 
    { 
     get 
     { 
      return this.lookupField; 
     } 
     set 
     { 
      this.lookupField = value; 
     } 
    } 
} 

/// <remarks/> 
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")] 
[System.SerializableAttribute()] 
[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Xml.Serialization.SoapTypeAttribute(Namespace = ApuConstants.Namespace)] 
public partial class RequestHeader 
{ 

    private string accountField; 

    private string idField; 

    /// <remarks/> 
    public string account 
    { 
     get 
     { 
      return this.accountField; 
     } 
     set 
     { 
      this.accountField = value; 
     } 
    } 

    /// <remarks/> 
    public string id 
    { 
     get 
     { 
      return this.idField; 
     } 
     set 
     { 
      this.idField = value; 
     } 
    } 
} 

/// <remarks/> 
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")] 
[System.SerializableAttribute()] 
[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Xml.Serialization.SoapTypeAttribute(Namespace = ApuConstants.Namespace)] 
public partial class Part 
{ 

    private string oemField; 

    private string hicField; 

    private string skuField; 

    private string descField; 

    private int daysField; 

    private string availField; 

    private string branchField; 

    private float listField; 

    private float netField; 

    private string typeField; 

    private string certField; 

    private string statusField; 

    /// <remarks/> 
    public string oem 
    { 
     get 
     { 
      return this.oemField; 
     } 
     set 
     { 
      this.oemField = value; 
     } 
    } 

    /// <remarks/> 
    public string hic 
    { 
     get 
     { 
      return this.hicField; 
     } 
     set 
     { 
      this.hicField = value; 
     } 
    } 

    /// <remarks/> 
    public string sku 
    { 
     get 
     { 
      return this.skuField; 
     } 
     set 
     { 
      this.skuField = value; 
     } 
    } 

    /// <remarks/> 
    public string desc 
    { 
     get 
     { 
      return this.descField; 
     } 
     set 
     { 
      this.descField = value; 
     } 
    } 

    /// <remarks/> 
    public int days 
    { 
     get 
     { 
      return this.daysField; 
     } 
     set 
     { 
      this.daysField = value; 
     } 
    } 

    /// <remarks/> 
    public string avail 
    { 
     get 
     { 
      return this.availField; 
     } 
     set 
     { 
      this.availField = value; 
     } 
    } 

    /// <remarks/> 
    public string branch 
    { 
     get 
     { 
      return this.branchField; 
     } 
     set 
     { 
      this.branchField = value; 
     } 
    } 

    /// <remarks/> 
    public float list 
    { 
     get 
     { 
      return this.listField; 
     } 
     set 
     { 
      this.listField = value; 
     } 
    } 

    /// <remarks/> 
    public float net 
    { 
     get 
     { 
      return this.netField; 
     } 
     set 
     { 
      this.netField = value; 
     } 
    } 

    /// <remarks/> 
    public string type 
    { 
     get 
     { 
      return this.typeField; 
     } 
     set 
     { 
      this.typeField = value; 
     } 
    } 

    /// <remarks/> 
    public string cert 
    { 
     get 
     { 
      return this.certField; 
     } 
     set 
     { 
      this.certField = value; 
     } 
    } 

    /// <remarks/> 
    public string status 
    { 
     get 
     { 
      return this.statusField; 
     } 
     set 
     { 
      this.statusField = value; 
     } 
    } 
} 

/// <remarks/> 
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")] 
[System.SerializableAttribute()] 
[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Xml.Serialization.SoapTypeAttribute(Namespace = ApuConstants.Namespace)] 
public partial class ResponseHeader 
{ 

    private string statusField; 

    private string reasonField; 

    private string accountField; 

    private string idField; 

    /// <remarks/> 
    public string status 
    { 
     get 
     { 
      return this.statusField; 
     } 
     set 
     { 
      this.statusField = value; 
     } 
    } 

    /// <remarks/> 
    public string reason 
    { 
     get 
     { 
      return this.reasonField; 
     } 
     set 
     { 
      this.reasonField = value; 
     } 
    } 

    /// <remarks/> 
    public string account 
    { 
     get 
     { 
      return this.accountField; 
     } 
     set 
     { 
      this.accountField = value; 
     } 
    } 

    /// <remarks/> 
    public string id 
    { 
     get 
     { 
      return this.idField; 
     } 
     set 
     { 
      this.idField = value; 
     } 
    } 
} 

/// <remarks/> 
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")] 
[System.SerializableAttribute()] 
[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Xml.Serialization.SoapTypeAttribute(Namespace = ApuConstants.Namespace)] 
public partial class Response 
{ 

    private ResponseHeader headerField; 

    private Part[] itemsField; 

    /// <remarks/> 
    public ResponseHeader header 
    { 
     get 
     { 
      return this.headerField; 
     } 
     set 
     { 
      this.headerField = value; 
     } 
    } 

    /// <remarks/> 
    public Part[] items 
    { 
     get 
     { 
      return this.itemsField; 
     } 
     set 
     { 
      this.itemsField = value; 
     } 
    } 
} 

/// <remarks/> 
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")] 
[System.SerializableAttribute()] 
[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.ComponentModel.DesignerCategoryAttribute("code")] 
[System.Xml.Serialization.SoapTypeAttribute(Namespace = ApuConstants.Namespace)] 
public partial class Lookup 
{ 

    private string oemField; 

    private string hicField; 

    private int qtyField; 

    private string zipField; 

    /// <remarks/> 
    public string oem 
    { 
     get 
     { 
      return this.oemField; 
     } 
     set 
     { 
      this.oemField = value; 
     } 
    } 

    /// <remarks/> 
    public string hic 
    { 
     get 
     { 
      return this.hicField; 
     } 
     set 
     { 
      this.hicField = value; 
     } 
    } 

    /// <remarks/> 
    public int qty 
    { 
     get 
     { 
      return this.qtyField; 
     } 
     set 
     { 
      this.qtyField = value; 
     } 
    } 

    /// <remarks/> 
    public string zip 
    { 
     get 
     { 
      return this.zipField; 
     } 
     set 
     { 
      this.zipField = value; 
     } 
    } 
} 

및 구현 : 여기에

는 서비스 계약의

[ServiceBehavior(Namespace = ApuConstants.Namespace)] 
public class ApuService : IApuService 
{ 
    private readonly IApuServiceHandler _handler; 
    private readonly ISettingService _settingService; 

    public ApuService() 
    { 
     _handler = EngineContext.Current.Resolve<IApuServiceHandler>(); 
     _settingService = EngineContext.Current.Resolve<ISettingService>(); 
    } 

    public Response check(Request request) 
    { 
     if (Authorized(request)) 
      return _handler.ProcessRequest(request); 
     return _handler.ErrorResponse("Invalid credentials"); 
    } 

    protected bool Authorized(Request request) 
    { 
     if (request == null || request.header == null) 
      return false; 

     var settings = _settingService.LoadSetting<ApuSettings>(0); 

     if (!string.Equals(request.header.account, settings.Username, StringComparison.InvariantCultureIgnoreCase)) 
      return false; 

     if (!string.Equals(request.header.id, settings.Password)) 
      return false; 

     return true; 
    } 
} 

Configuration (구성) :

<configuration> 
    <system.web> 
    <compilation targetFramework="4.5.1" /> 
    </system.web> 

    <system.serviceModel> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior name="ApuBehavior"> 
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/> 
      <serviceDebug includeExceptionDetailInFaults="true"/> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <bindings> 
    </bindings> 
    <services> 
     <service name="Apu.WebService.ApuService" behaviorConfiguration="ApuBehavior"> 
     <endpoint address="" binding="basicHttpBinding" contract="Web.Apu.IApuService" bindingNamespace="http://www.testurl.com/apu" /> 
     <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> 
     </service> 
    </services> 
    </system.serviceModel> 
</configuration> 

OperationContext.Current.RequestContext에서 (서비스 수신 요청 .RequestMessage) :

<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"> 
    <s:Header xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> 
    <To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://localhost:15555/Plugins/Brock.Apu/Remote/ApuService.svc</To> 
    </s:Header> 
    <Body> 
     <check xmlns="http://www.testurl.com/apu"> 
      <request> 
       <header> 
        <account>apu</account> 
        <id>apu001!</id> 
       </header> 
       <lookup> 
        <hic>323-01327</hic> 
        <oem>5014351AB</oem> 
        <qty>2</qty> 
        <zip>85304</zip> 
       </lookup> 
      </request> 
     </check> 
    </Body> 
</Envelope> 

(잘못 직렬화) 서비스에 의해 전송 된 응답 : Response이 부분 클래스처럼

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> 
    <s:Body s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
     <q1:checkResponse xmlns:q1="http://www.testurl.com/apu"> 
      <return href="#id1"/> 
     </q1:checkResponse> 
     <q2:Response id="id1" xsi:type="q2:Response" xmlns:q2="http://www.testurl.com/apu"> 
      <header href="#id2"/> 
     </q2:Response> 
     <q3:ResponseHeader id="id2" xsi:type="q3:ResponseHeader" xmlns:q3="http://www.testurl.com/apu"> 
      <status xsi:type="xsd:string">no</status> 
      <reason xsi:type="xsd:string">Invalid credentials</reason> 
      <account xsi:type="xsd:string"/> 
      <id xsi:type="xsd:string"/> 
     </q3:ResponseHeader> 
    </s:Body> 
</s:Envelope> 
+0

누군가가 '약간의 변경'을했다고 말하면 나는 그것이 문제라고 생각하는 경향이 있습니다. –

+0

wsdl.exe를 체크 아웃 했습니까? https://msdn.microsoft.com/en-us/library/7h3ystb6(v=vs.100).aspx. 이전 .asmx 서비스가 프록시 생성에 사용하는 것입니다. 서비스의 나이에 따라 다른 결과가 나올 수 있습니다. –

+0

@JssDwt - 전혀 아닙니다. 데이터 계약 직렬화를 사용하도록 서비스를 추가로 수정할 수 있었으며 정상적으로 작동했습니다. 그러나 XML 직렬화를 사용해야합니다. 문제는 수정이 아닙니다. 그것을 수정하는 올바른 방법을 알고 있습니다. 우리가 필요로하는 오래된 코드 (또는이 경우 미리 생성 된 코드)를 바꿀 수 없다는 말을 시작할 때 프로그래밍 세계에 대한 열등한 경계가됩니다. –

답변

0

후속 조치 : 서비스 계약을 처음에 게시 한 것으로 나타났습니다. 요청 형식이 잘못되었습니다. 대신 간단한 인라인 XML 구조, 디시리얼라이저이 기다리고 있었다 :

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <soapenv:Body> 
     <ns1:check xmlns:ns1="http://www.testurl.com/apu" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> 
      <request href="#id0"/> 
     </ns1:check> 
     <multiRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="http://www.testurl.com/apu" id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns2:Request"> 
      <header href="#id1"/> 
      <lookup href="#id2"/> 
     </multiRef> 
     <multiRef xmlns:ns3="http://www.testurl.com/apu" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id1" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns3:RequestHeader"> 
      <account xsi:type="xsd:string"></account> 
      <id xsi:type="xsd:string"></id> 
     </multiRef> 
     <multiRef xmlns:ns4="http://www.testurl.com/apu" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id2" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns4:Lookup"> 
      <oem xsi:type="xsd:string">6C3Z13008BB</oem> 
      <hic xsi:type="xsd:string"/> 
      <qty href="#id3"/> 
      <zip xsi:type="xsd:string">70764</zip> 
     </multiRef> 
     <multiRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id3" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:int">1</multiRef> 
    </soapenv:Body> 
</soapenv:Envelope> 

나는 우리의 고객이 클라이언트에서 전송하기 원시 요청을 로그 가진 후이 알아 냈어.

1

것 같습니다. 다른 파일에 다른 파일이 있습니까? 그 다른 부분은 직렬화 가능합니까? ResponseHeaderPart에 대해 동일한 질문이 있습니까?

나는 보통 [Serializable] 데코레이터를 사용합니다.

public float list에있는 키워드 목록에 Part 클래스 내에 문제가있을 수 있습니다.

+0

부분품에는 다른 부분이 없습니다. 데이터 개체는 이미 Serializable ([System.SerializableAttribute()])로 표시되어 있습니다. C#은 대소 문자를 구별하는 언어이므로 소문자 "list"는 List 클래스와 혼동하지 않습니다. 또한 "List"도 "list"도 C#의 예약 키워드는 아닙니다. –