2010-04-29 2 views
1

WCF를 처음 사용하고 주문 객체 (XML 파일에서 일련의 문자열)를 받아서 데이터를 데이터베이스에 삽입 한 다음 주문 객체를 반환하는 간단한 REST 서비스를 만들었습니다. 결과가 포함되어 있습니다. 서비스를 테스트하기 위해 작은 웹 프로젝트를 만들고 xml 문서에서 만든 스트림을 보내십시오.WCF 웹 서비스 데이터 멤버 기본값 null null

문제는 XML 문서의 모든 항목이 스트림에 배치 되더라도 서비스에서 데이터를받을 때 일부 서비스가 무효화된다는 것입니다. 예를 들어 lineItemId에는 값이 있지만 배송 상태는 null로 표시됩니다. XML 생성을 단계별로 진행하고 모든 값이 전송되는지 확인합니다. 그러나 datamembers를 지우고 주위의 이름을 변경하면 작동 할 수 있습니다. 어떤 도움을 주시면 감사하겠습니다. 있는 Web.Config

에서

string lineId = txtLineItem.Text.Trim(); 
    string status = txtDeliveryStatus.Text.Trim(); 
    string TrackingNumber = "1x22-z4r32"; 
    string theMethod = "Ground"; 
    string carrier = "UPS"; 
    string ShipmentDate = "04/27/2010"; 

    XNamespace nsOrders = "http://tempuri.org/order"; 
    XElement myDoc = 
     new XElement(nsOrders + "Order", 
      new XElement(nsOrders + "lineItemId", lineId), 
      new XElement(nsOrders + "shipmentStatus", status), 
      new XElement(nsOrders + "trackingNumber", TrackingNumber), 
      new XElement(nsOrders + "delvryMethod", theMethod), 
      new XElement(nsOrders + "shipmentCarrier", carrier), 
      new XElement(nsOrders + "shipmentDate", ShipmentDate) 
    ); 

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:3587/Deposco.svc/wms/Orders/UpdateOrderStatus/"); 
    request.Method = "POST"; 
    request.ContentType = "application/xml"; 

    try 
    { 
     request.ContentLength = myDoc.ToString().Length; 
     StreamWriter sw = new StreamWriter(request.GetRequestStream()); 
     sw.Write(myDoc); 
     sw.Close(); 

     using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 
     { 

      StreamReader reader = new StreamReader(response.GetResponseStream()); 
      string responseString = reader.ReadToEnd(); 

      XDocument.Parse(responseString).Save(@"c:\DeposcoSvcWCF.xml"); 
     } 

    } 
    catch (WebException wEx) 
    { 
     Stream errorStream = ((HttpWebResponse)wEx.Response).GetResponseStream(); 
     string errorMsg = new StreamReader(errorStream).ReadToEnd(); 
    } 

바인딩

<system.serviceModel> 
    <services> 
     <service behaviorConfiguration="DesposcoService.ShippingServiceBehavior" name="DesposcoService.ShippingService"> 
      <endpoint address="wms" binding="webHttpBinding" contract="DesposcoService.IShipping" behaviorConfiguration="REST" bindingNamespace="http://companyname.com/wms"> 
       <identity> 
        <dns value="localhost"/> 
       </identity> 
      </endpoint> 
      <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> 
     </service> 
    </services> 
    <behaviors> 
     <serviceBehaviors> 
      <behavior name="DesposcoService.ShippingServiceBehavior"> 
       <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment --> 
       <serviceMetadata httpGetEnabled="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> 
     <endpointBehaviors> 
      <behavior name="REST"> 
       <webHttp/> 
      </behavior> 
     </endpointBehaviors> 
    </behaviors> 
</system.serviceModel> 

답변

4

I :

이것은 내가 주문 개체를 보내하기 위해 사용하고 무엇

[ServiceContract(Namespace="http://companyname.com/wms/")] 
public interface IShipping 
{ 

    [OperationContract] 
    [WebInvoke(Method = "POST", UriTemplate = "/Orders/UpdateOrderStatus/", BodyStyle=WebMessageBodyStyle.Bare)] 
    ReturnOrder UpdateOrderStatus(Order order); 
} 


[DataContract(Namespace="http://companyname.com/wms/order")] 
public class Order 
{ 
    [DataMember] 
    public string lineItemId { get; set; } 

    [DataMember] 
    public string shipmentStatus { get; set; } 

    [DataMember] 
    public string trackingNumber { get; set; } 

    [DataMember] 
    public string shipmentDate { get; set; } 

    [DataMember] 
    public string delvryMethod { get; set; } 

    [DataMember] 
    public string shipmentCarrier { get; set; } 
} 

[DataContract] 
public class ReturnOrder 
{ 
    [DataMember(Name = "Result")] 
    public string Result { get; set; } 

} 

인터페이스 코드 이것을 알아 냈습니다 (제임스가 그랬던 것처럼 보입니다).

문제는 DataContractSerializer로하고, 여기를 재현 테스트 케이스이다 : 당신이 실행하는 경우는 Description 속성에 빈 온다, 당신이 볼 수

class Program 
{ 
    static void Main(string[] args) 
    { 
     XNamespace ns = "http://tempuri.org/"; 
     XElement element = 
      new XElement(ns + "MyRequest", 
       new XElement(ns + "ID", 5), 
       new XElement(ns + "Name", "Test"), 
       new XElement(ns + "Description", "This is a test")); 

     DataContractSerializer serializer = new 
      DataContractSerializer(typeof(MyRequest)); 
     using (XmlReader reader = element.CreateReader()) 
     { 
      MyRequest request = (MyRequest)serializer.ReadObject(reader); 
      Console.WriteLine("ID: {0}, Name: {1}, Description: {2}", 
       request.ID, request.Name, request.Description); 
     } 
     Console.ReadLine(); 
    } 

    [DataContract(Name = "MyRequest", Namespace = "http://tempuri.org/")] 
    public class MyRequest 
    { 
     [DataMember] 
     public int ID { get; set; } 

     [DataMember] 
     public string Name { get; set; } 

     [DataMember] 
     public string Description { get; set; } 
    } 
} 

은.

DataContractSerializer은 멤버가 알파벳 순서로 있어야하기 때문에 이러한 현상이 발생합니다. 클라이언트와 서비스 모두에 대해 DataContractSerializer을 사용할 때 제대로 작동합니다 ... XML을 수동으로 생성 할 때 그렇게 좋지는 않습니다. 당신이 DataMember 속성에 Order 속성을 추가하는 경우

, 작동 :

[DataContract(Name = "MyRequest", Namespace = "http://tempuri.org/")] 
    public class MyRequest 
    { 
     [DataMember(Order = 0)] 
     public int ID { get; set; } 

     [DataMember(Order = 1)] 
     public string Name { get; set; } 

     [DataMember(Order = 2)] 
     public string Description { get; set; } 
    } 

Description 및 다른 모든 필드를 찾습니다이 시간.

그래서이 문제를 해결하려면 다음 중 하나를 수행 할 수 있습니다

  • 는에 DataMember가 실제로 XML을 생성하기 위해 계획하는 순서와 일치하는 속성 Order 인수를 추가; 또는

  • 요소를 클라이언트 측에 알파벳 순서 (요소 이름 기준)로 추가해야합니다.

특히 이러한 대안 중 하나가 마음에 들지 않습니다. 그들은 hackish하고 쉬기 쉬운 것처럼 보입니다. POX 서비스에 대해서는 DataContractSerializer 대신 XmlSerializer을 사용하는 것이 더 좋을 것이라고 생각합니다. 그런 것들에 대해서는 신경 쓰지 않아도 되겠지만, webHttpBinding과 함께 작동하지 않는 것 같습니다. 더 많은 시간이있을 때 조사 할만한 가치가있는 것.

+0

실제로 서비스 계약 및 데이터 계약에 대해 정의 된 네임 스페이스가 있습니다. 그들에게는 회사 정보가있어 게시를 위해 회사 정보를 삭제했습니다.그들을 모두 제거한 후에, 나는 서버에서 각각의 트라이밍을 시도하고 복종시키는 나쁜 요청을받습니다. – James

+0

@James : 질문에 필요한 정보 (익명 처리)를 포함시킬 수 있습니까? 또한 사용중인 바인딩/구성을 게시하십시오. 완벽하게 재현 할 수없는 경우 진단하기가 어렵습니다. – Aaronaught

+0

물론, 질문을 편집하기 위해 어디로 가야할지 생각해 보면 추가 할 것입니다. 오버플로 스택이 새로 생겼습니다. – James