2010-04-29 43 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