2010-01-06 1 views
8

다양한 xml serialization 특성으로 장식 된 클래스를 사용하는 WCF 서비스를 노출 할 때 인터페이스에서 XmlSerializerFormat 특성을 사용 했음에도 불구하고 모든 작업 매개 변수의 모든 XmlRoot 특성은 완전히 무시됩니다. 매개 변수의 네임 스페이스는 항상 우리가 지정하는 것이 아니라 서비스의 네임 스페이스입니다.WCF에서 XmlRoot 특성이 무시되는 이유 및이를 극복하는 방법

이렇게하면 ASMX와 호환되지 않는 것처럼 보이며 우리가 BizTalk를 사용하고 있으며 교환 된 XML의 모양을보다 엄격하게 제어해야하기 때문에 문제가 발생합니다.

몇 가지 질문에 다음 -

  1. 아무도이 결정 뒤에 근거 이 무엇인지 아는 사람?
  2. 아무도 모른다. 어때? 나는 이 경우가 오는 방법 XmlRoot 을 제안 WCF에서, XmlSerializerFormat 속성과 함께, 가 유형에는 직렬화하기 위해 XmlSerialiser를 사용하는 인상이 고려되어야한다, 아래에 있었다? (이 계정으로 는 SOAP 봉투를 복용 만 인해 그 사실에 되면, 매개 변수는 근절되지 않는 이유는 무엇입니까?)
  3. 대부분의 을 중요하게 - - 즉, 사람은 '문제를 강제'할 수있는 방법이 경우 알고 매개 변수를 우리가 선택한 네임 스페이스가되도록하십시오.

나는 this 게시물을 본 적이 있지만 나는 내 질문에 관련이 생각하지 않는다 - 바그너 실 베이라의 요청에 따라

-

[ServiceContract(Namespace = "http://servicecontract"), 
XmlSerializerFormat(Style = OperationFormatStyle.Document)] 
public interface ITestService 
{ 
    [OperationContract] 
    MyOtherType MyTestMethod(MyType obj); 
} 

// Composite class for DCS and XMLS 
[Serializable, XmlType, XmlRoot(Namespace = "http://datacontract")] 
public class MyType 
{ 
    [XmlAttribute] 
    public string StringValue { get; set; } 
} 

// Composite class for DCS and XMLS 
[Serializable, XmlType, XmlRoot(Namespace = "http://datacontract")] 
public class MyOtherType 
{ 
    [XmlAttribute] 
    public string OtherStringValue { get; set; } 
} 
- 내가 사용하는 계약이이 테스트

답변

2

SOAP을 메시지 형식으로 사용한다고 가정합니다. 이 경우 직렬화하려는 객체가 XML의 루트가 아니며 비누 봉투가 있습니다. 따라서 XmlRoot가 무시된다는 것은 의미가 있습니다. 기본적으로 WCF는 메시지 계약을 만들고 응답의 이름을 지정하며 서비스의 네임 스페이스를 갖습니다. 할 수있는 일은 SOAP를 완전히 제어 할 수있는 create your own message contract입니다.

는 다음과 같은 두 가지 클래스를 만듭니다

[MessageContract] 
public class MyTestMethodRequest 
{ 
    [MessageBodyMember(Namespace = "http://datacontract")] 
    public MyType MyType; 
} 

[MessageContract] 
public class MyTestMethodResponse 
{ 
    [MessageBodyMember(Namespace = "http://datacontract")] 
    public MyOtherType MyOtherType; 
} 

는 다음에 서비스 작업의 서명을 변경합니다.

요청

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> 
    <s:Header> 
    <Action xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none" 
      s:mustUnderstand="1">http://servicecontract/TestService/MyTestMethod</Action> 
    </s:Header> 
    <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <MyTestMethodRequest xmlns="http://servicecontract"> 
     <MyType StringValue="foo" xmlns="http://datacontract" /> 
    </MyTestMethodRequest> 
    </s:Body> 
</s:Envelope> 

응답

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> 
    <s:Header /> 
    <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <MyTestMethodResponse xmlns="http://servicecontract"> 
     <MyOtherType OtherStringValue="bar" xmlns="http://datacontract" /> 
    </MyTestMethodResponse> 
    </s:Body> 
</s:Envelope> 
+1

Thanks John 우리는 MessageContract 옵션을 찾았습니다. 그냥 ASMX에서 작동했던 뭔가에 대한 번거 로움처럼 보입니다. 그 이유는 루트가 아닌 노드 인수에 대해서는 확신 할 수 없었지만, 말이된다. 개인적으로 저는 그것이 이전 버전과의 호환성에 큰 타격이라고 생각합니다. –

1

왜 WCF가 XmlRoot를 무시하는지 모르겠으므로 그 질문에 대답 할 수 없습니다. 하지만 문제를 해결할 수있는 몇 가지 방법이 있습니다.

  1. WSDL로 시작하십시오.
    보내고받는 메시지에 적용하려는 특정 XML 네임 스페이스 집합이있는 경우 WSDL 및 XML 스키마를 사용하여이를 명시 적으로 지정하십시오.

    그런 다음 the svcutil.exe tool을 통해 해당 WSDL에서 직접 서버 측 스텁 코드 또는 클라이언트 측 프록시 코드를 생성하십시오.

  2. use a custom ServiceHost
    this link에 설명 당신에게 열려있는 다른 옵션은,의 XmlRoot을 무시하거나 XMLTYPE는 메시지 유형에 속성에 WCF의 결정을 재정의하는 사용자 지정 ServiceHost를 사용하는 것입니다.당신은 WSDL-첫 번째 접근 방식으로 이동을 선택하면


의 WSDL은 다음과 같아야합니다

<?xml version="1.0" encoding="utf-8" ?> 

<definitions 
    xmlns="http://schemas.xmlsoap.org/wsdl/" 
    targetNamespace="urn:The-Service-namespace" 
    xmlns:tns="urn:The-Service-namespace" 
    xmlns:s="http://www.w3.org/2001/XMLSchema" 
    xmlns:n0="urn:The-Request-namespace" 
    xmlns:n1="urn:The-Response-namespace" 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    elementFormDefault= "unqualified" 
    > 

    <types> 
     <s:schema targetNamespace="urn:The-Request-namespace" > 
     <s:complexType name="Type1"> 
      <s:sequence> 
      <s:element name="x" minOccurs="1" maxOccurs="1" type="s:string"/> 
      </s:sequence> 
     </s:complexType> 
     <s:element name="Type1" type="n0:Type1" /> 
     </s:schema> 


     <s:schema targetNamespace="urn:The-Response-namespace" > 
     <s:complexType name="Type2"> 
      <s:sequence> 
      <s:element name="x" minOccurs="1" maxOccurs="1" nillable="false" type="s:string"/> 
      <s:element name="y" minOccurs="1" maxOccurs="1" nillable="false" type="s:int"/> 
      <s:element name="z" minOccurs="1" maxOccurs="1" nillable="false" type="s:boolean" /> 
      </s:sequence> 
     </s:complexType> 
     <s:element name="Type2" type="n1:Type2" /> 
     </s:schema> 

    </types> 



<message name="RequestMessage"> 
    <part name="inPart1" element="n0:Type1" /> 
</message> 
<message name="ResponseMessage"> 
    <part name="outPart1" element="n1:Type2" /> 
</message> 



<portType name="PortTypeName"> 
    <operation name="Method1"> 
     <input message="tns:RequestMessage" /> 
     <output message="tns:ResponseMessage" /> 
    </operation> 
</portType> 



<binding name="InterfaceName" type="tns:PortTypeName"> 
    <soap:binding 
     transport="http://schemas.xmlsoap.org/soap/http" 
     style="rpc" /> 

    <operation name="Method1"> 
     <soap:operation soapAction="" style="document" /> 
     <input> <soap:body use="literal" /> </input> 
     <output> <soap:body use="literal" /> </output> 
    </operation> 
</binding> 

</definitions> 

이 WSDL은 매우 간단합니다 - 그것은 하나의 동작을 정의 단일 요청 메시지와 단일 응답 메시지로 구성됩니다.

공지 사항 세 가지 XML 네임 스페이스가 있습니다 :

  • 항아리 : 요청과 응답을 래핑 요소에 사용되는 - 서비스 - 네임 스페이스
    - < SOAP 내부의 첫 번째 요소 : 몸 >
  • URN : 타입 1의 인스턴스를 탈 직렬화으로 가도록 요청 포장지 안에 감싸 소자에 사용되는 공간 - 요청 -
    .
  • URN 다음 반응 네임 스페이스 타입 2의 인스턴스로 역 직렬화 가도록 응답 포장지 안에 감싸 소자에 사용
    .

웹 서비스 인터페이스가 더 복잡하고 더 많은 작업과 더 많은 요청 및 응답 메시지 유형이있는 경우 모든 추가 유형에 대해 네임 스페이스를 추가 할 수 있습니다.

+0

감사 Cheeso :

[OperationContract] public MyTestMethodResponse MyTestMethod(MyTestMethodRequest request) { return new MyTestMethodResponse { MyOtherType = new MyOtherType { OtherStringValue = "bar" } }; } 

지금 당신은 다음을 참조해야 당신이 예를 SOAP 메시지를합니다. 저는 사용자 지정 호스트 접근 방식에 익숙합니다. 실제로 이것은 몇 곳에서 한 것이지만, 이것은 상호 운용성의 깃발을 가진 기술에 대한 큰 질문입니다. 어쨌든 - 내 질문의 목적은 동작을 이해하는 것입니다. 답장 시간을내어 주셔서 감사합니다. –

관련 문제