1

私はWCFを初めて使用し、注文オブジェクト(XMLファイルからの一連の文字列)を受け入れ、そのデータをデータベースに挿入して、結果を含む注文オブジェクトを返す単純なRESTサービスを作成しました。サービスをテストするために、小さなWebプロジェクトを作成し、xmlドキュメントから作成されたストリームを送信しました。

問題は、xmlドキュメント内のすべてのアイテムがストリームに配置されていても、サービスがデータを受信したときにそれらの一部を無効にしていることです。たとえば、lineItemIdには値がありますが、出荷ステータスにはnullが表示されます。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; }

}

これは、私がOrderオブジェクトを送信するために使用しているものです。

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

Web.Configからのバインディング

<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

1 に答える 1

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および他のすべてのフィールドが検索されます。

したがって、この問題を解決するには、次のいずれかを実行できます。

  • 実際に XML を生成する予定の順序に一致するようOrderに、属性に引数を追加します。DataMemberまた

  • クライアント側では、必ず要素をアルファベット順に (要素名で) 追加してください。

私はこれらの回避策のどちらも特に好きではありません。それらはハック的で壊れやすいようです。POX サービスの場合、 のXmlSerializer代わりにを使用するDataContractSerializerことをお勧めします。これは、そのようなことについてはあまり面倒ではありませんが、そのままでは では機能しないようですwebHttpBinding。時間があるときに調査する価値のあるもの。

于 2010-04-29T13:44:31.317 に答える