2010-04-29 21 views
1

我是WCF的新手,並創建了一個簡單的REST服務來接受訂單對象(從XML文件中的一系列字符串),將數據插入數據庫,然後返回一個訂單對象包含結果。爲了測試服務,我創建了一個小型Web項目併發送了一個從xml文檔創建的流。WCF Web服務數據成員默認爲null

問題是,即使xml文檔中的所有項都放入流中,服務在接收到數據時都會使其中的某些項無效。例如lineItemId將有一個值,但裝運狀態將顯示爲空。我逐步通過xml創建並驗證所有值都正在發送。但是,如果我清除數據成員並更改名稱,則可以工作。任何幫助,將不勝感激。

這是界面代碼

[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; } 

} 

這是我用什麼送過來的訂單對象:從程序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

我弄明白了這一點(顯然大約與詹姆斯在同一時間)。

的問題是與DataContractSerializer,這裏是再現它的測試用例:

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; } 
    } 
} 

如果你運行它,你會看到它的Description財產出現空。

發生這種情況是因爲DataContractSerializer期望成員按字母順序排列。當您爲客戶端和服務使用DataContractSerializer時,此功能正常工作......當您手動生成XML時,效果並不好。

如果添加Order性質的DataMember屬性,它的工作原理:

[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等各個領域。

因此,要解決這個問題,你可以做以下任一操作:

  • 添加Order參數給DataMember屬性設置成符合您實際計劃生成XML的順序;或

  • 請確保您在客戶端按字母順序(按元素名稱)添加元素。

我並不特別喜歡這些解決方法。他們看起來很拗口,很容易被打破。我認爲對於POX服務,我傾向於使用XmlSerializer而不是DataContractSerializer,因爲它對此類事情沒那麼挑剔,但它似乎並不像webHttpBinding那樣開箱即用。有更多的時間值得調查。

+0

我確實有爲服務合同和數據合同定義的名稱空間。他們在他們的公司信息,所以我刪除他們張貼。雖然他們都刪除後,我收到服務器的錯誤請求400每個trime我嘗試並提交給它。 – James 2010-04-29 14:05:19

+0

@詹姆斯:你可以在問題中包含這些信息(如果有必要,匿名)?同時發佈您正在使用的綁定/配置 - 如果沒有完整的重現病例,很難診斷。 – Aaronaught 2010-04-29 14:31:51

+0

當然,一旦我找出編輯問題的地方,我會添加它(我是堆棧溢出的新手) – James 2010-04-29 14:37:21