2010-08-06 4 views
5

Visual Studio에서 웹 서비스 프록시를 생성하는 데 사용하는 도구 인 wsdl.exe에 알려진 버그가있는 것 같습니다. 특정 XSD 스키마의 경우이 도구는 XML에서 직렬화 할 수없는 클래스를 생성합니다.Visual Studio에서 들쭉날쭉 한 배열을 처리하기 위해 생성 한 웹 참조 프록시를 어떻게 수정합니까?

필자는 그것이 받아 들일 수 없다고 우려하고 있지만 어떻게 수정해야할지 모르겠다.

세부 사항을 설명하고 누군가가 나를 도와 줄 수 있기를 바랍니다. 일반적인 응답이 스키마에 따라 웹 서비스

에서

스키마

<!-- return type from the service operation --> 
<xs:complexType name="listAssetsQueryResults"> 
    <xs:sequence> 
     <xs:element name="assets" type="tns:asset" minOccurs="0" maxOccurs="unbounded"/> 
    </xs:sequence> 
</xs:complexType> 

<!-- a sequence of attributes --> 
<xs:complexType name="asset"> 
    <xs:sequence> 
     <xs:element name="attributes" type="tns:multiValuedAttribute" minOccurs="0" maxOccurs="unbounded"/> 
    </xs:sequence> 
</xs:complexType> 

<xs:complexType name="multiValuedAttribute"> 
    <!-- not relevant--> 
</xs:complexType> 

XML 응답은 다음과 같습니다

<assets-query-result> 
    <assets> 
     <attributes> 
      <name>Keywords</name> 
      <values>Desert</values> 
     </attributes> 
     <attributes> 
      <name>Filename</name> 
      <values>Desert.jpg</values> 
     </attributes> 
    </assets> 
    <assets>...</assets> 
    <assets>...</assets> 
</assets-query-result> 

코드의 형식을 사용하여

나는이 같은 CLR 유형을 사용할 수있을 것으로 예상했을 것이다

:

result.assets[0].attributes[0].name 

대신, 결과에 대해 생성 된 유형은 다음과 같습니다

[SerializableAttribute()] 
public partial class listAssetsQueryResults { 
    private multiValuedAttribute[][] assetsField; 

    [XmlArrayAttribute(Form=XmlSchemaForm.Unqualified, IsNullable=true)] 
    [XmlArrayItemAttribute("attributes", typeof(multiValuedAttribute), Form=XmlSchemaForm.Unqualified)] 
    public multiValuedAttribute[][] assets { 
     get { return this.assetsField; } 
     set { this.assetsField = value; } 
    } 
} 

도하지 않는 직렬화 어셈블리가 생성되도록 허용하십시오! Portfolio.WebService.multiValuedAttribute에 유형 에게 []

가 수정을 Portfolio.WebService.multiValuedAttribute 변환 할

수 없습니다 그것을

1 - 프로퍼티 및 필드

의 유형 변경

이제 온라인에서 찾은 수정 중 하나는 gen의 유형에서 한 쌍의 대괄호를 제거하는 것입니다 erated 특성 : 직렬화 어셈블리를 구축 할 수 있습니다, 그것은 제대로 데이터를 직렬화하지 않습니다를 제외하고는 자산의 목록을 '생략'과 제의 특성을 역 직렬화 예외없이 실행

// No longer a jagged array, but this doesn't deserialize all data 
public multiValuedAttribute[] assets; 

assets 요소. 따라서이 픽스를 사용하면 데이터를 소비 할 수 없으므로 전혀 문제가되지 않습니다. 700 개 이상의 애셋의 경우 result.assetsmultiValuedAttribute[2]과 같습니다 (두 요소는 첫 번째 애셋의 이름 및 키워드 속성 임). -

2 XML 요소

내가 시도 두 번째 것은 디시리얼라이저 다른 지침을 제공하는 것입니다의 유형 지정 : 그래서

[XmlArrayItemAttribute("attributes", typeof(multiValuedAttribute[]), Form=XmlSchemaForm.Unqualified)] 
public multiValuedAttribute[][] assets { ... } 

지금은 그것을 말하고를 그 각 요소 시퀀스는 multiValuedAttribute[]입니다.이는 attributes 요소를 여전히보고 있으므로 multiValuedAttribute 유형 (배열이 아닌 단일 형식)이기 때문에 잘못되었습니다. 그러나 지금은 result.assetsmultiValuedAttribute[2][0]과 같으며 여전히 데이터를 가져올 수 없습니다.

다음은?

나는 이것을 작성한 이유가 없습니다. .NET은이 웹 서비스를 사용할 수 없기 때문에 .NET이이를 수용 할 수 없습니다.

+0

혹시 더 나은 솔루션을 찾으러 왔습니까? 정확한 문제에 직면하고 있지만 수정할 필요가있는 수백 가지 유형이 있습니다. –

답변

3

여러분은 multiValuedAttribute [] 유형의 속성을 가질 별도의 Asset 클래스를 정의해야한다고 생각합니다. 그래서,

public class Asset 
{ 
    public multiValuedAttribute[] attributes {get; set;} 
} 

public partial class listAssetsQueryResults { 
    private Asset[] assetsField; 

    public Asset[] assets { 

그럼 당신은 자산 유형을 장식 할 필요가

과 같이 갈이 작업을 진행 속성 XMLELEMENT/XmlArrayElement/XmlArrayItemElement의 조합으로 & 자산 속성을 속성 것입니다.

물론 프록시 코드를 다시 생성해야 할 때마다 위의 변경 사항을 다시 적용해야합니다 (빌드 동작으로 배치 스크립트를 만들 수 있음).

0

웹 서비스가 wsdl 프로세서에 친숙한 것을 반환하도록 항상 형식을 변경할 수 있습니다. 그래서 예를 들어, 당신이 준 예제를 기반으로, 당신은 쉽게 KeyValuePair<string, string> 또는 뭔가 웹 서비스에서 반환하기 전에 배열로 변환 할 수 있어야합니다.

이것은 아마 가변 배열을 드러내는 것보다 더 나은 API 일 것입니다. 내가 그 .NET을 받아 들일 수 없다

내 친구 테레사 수녀가 말한대로 이

글쎄,이 웹 서비스

소비 할 을 수 없습니다 "인생은 투쟁이다, 이용 약관을 읽고 동의를." ;-)

+1

웹 서비스를 변경할 수 없으며 구입 한 서버 소프트웨어의 일부입니다. 웹 서비스를 사용할 수 없다는 사실을 받아 들일 수없는 이유이기도하다. –

2

이 문제는 Java로 작성된 후 WCF, C#, .Net 등에서 들쭉날쭉 한 배열 (배열 배열)이 사용되는 SOAP 웹 서비스를 사용할 때 매우 일반적입니다. VinayC의 글은 도움이되었지만,이 문제를 겪는 다른 사람들을 도울 수있는 좀 더 명확한 코드가 있습니다.

이러한 클래스는 간략하게 표시되어 있습니다. WSDL로 생성 된 코드는 분명 더 복잡해질 것입니다.

public partial class assests{ 
    private multiValuedAttribute[] attributesField; 
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] 
    public multiValuedAttribute[] attributes{ 
    get {return this.attributesField;} 
    set {this.attributesField = value;} 
    } 
} 

public partial class listAssetsQueryResults{ 
    private assests[] assetsField; 
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] 
    public assets[] assets{ 
     get {return this.assetsField;} 
     set {this.assetsField = value;} 
    } 
} 

열쇠는 여기에 multiValuedAttribute와 listAssetsQueryResults 클래스 사이의 링크 인 새로운 '자산'클래스를 만든 다음 XmlElementAttribute를 사용하여 필드를 직렬화하는 것입니다. 자신의 프로젝트에서이 작업을 수행하는 좋은 방법은 multiValuedAttribute 클래스와 비슷한 클래스를 복사하여 붙여 넣는 것부터 시작하는 것입니다 (클래스 구현은 여기에 표시되지 않지만). 그런 다음 복사 된 multiValuedAttribute 클래스의 이름을 'assets'로 바꾸고 구현을 변경하여 둘 사이의 링크로 작동하도록합니다. listAssetsQueryResults 클래스의 [] []을 포함하는 명령.에서 여분의 []를 제거하십시오. XmlArrayItem 대신 XmlElement를 사용하여 직렬화하십시오.

물론 다른 서비스에는 서로 다른 요구 사항이 있습니다. Fiddler 응용 프로그램 (http://fiddler2.com/)을 사용하면 직렬화를 검사하여 올바르게 작성되었는지 확인할 수 있습니다. Fiddler는 정말로 나를 도왔습니다.다음은 저를 도운 데 도움이되었던 몇 가지 추가 정보입니다. http://msdn.microsoft.com/en-us/library/2baksw0z.aspx

관련 문제