C#OData使用嵌套项创建(POST)请求

时间:2011-10-31 20:30:08

标签: c# post odata

希望我可以让别人帮我解决我遇到的问题。我们正在使用一种新产品,它与我们的ERP系统交互,并使用OData通过REST服务公开业务对象。他们有一些样本和我所经历过的所有内容,但我仍然坚持使用该产品的关键流程,即在一个请求中创建包含许多项目的销售文档。

我已经让服务器端的后端接受请求,因为我可以在Firefox中使用REST客户端手动创建POST请求,ERP系统接受请求并创建文档没问题。

问题是,我正在尝试用一个简单的C#控制台应用程序以编程方式创建请求,但我无法正确创建请求。

以下是OData服务的$元数据:

<edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" xmlns:gp="http://www.sap.com/Protocols/SAPData/GenericPlayer" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:sap="http://www.sap.com/Protocols/SAPData" Version="1.0">
  <edmx:DataServices m:DataServiceVersion="2.0">
    <Schema xmlns="http://schemas.microsoft.com/ado/2008/09/edm" Namespace="SALES_ORDER">
      <EntityType Name="SalesOrderHeader" sap:content-version="1">
        <Key>
          <PropertyRef Name="OrderId"/>
        </Key>
        <Property Name="OrderId" Type="Edm.String" Nullable="false" MaxLength="10" sap:label="Sales Document" sap:filterable="false"/>
        <Property Name="DocumentType" Type="Edm.String" MaxLength="4" sap:label="Sales Doc. Type" sap:filterable="false"/>
        <Property Name="DocumentDate" Type="Edm.DateTime" Precision="10" sap:label="Document Date" sap:filterable="false"/>
        <Property Name="CustomerId" Type="Edm.String" MaxLength="10" sap:label="Sold-to party" sap:filterable="true"/>
        <Property Name="SalesOrg" Type="Edm.String" MaxLength="4" sap:label="Sales Org." sap:filterable="false"/>
        <Property Name="DistChannel" Type="Edm.String" MaxLength="2" sap:label="Distr. Channel" sap:filterable="false"/>
        <Property Name="Division" Type="Edm.String" MaxLength="2" sap:label="Division" sap:filterable="false"/>
        <Property Name="OrderValue" Type="Edm.Decimal" Precision="21" Scale="2" sap:label="Net value" sap:filterable="false"/>
        <Property Name="Currency" Type="Edm.String" MaxLength="5" sap:label="Doc. Currency" sap:filterable="false" sap:semantics="currency-code"/>
        <NavigationProperty Name="SalesOrderItems" Relationship="SALES_ORDER.SalesOrderHeader_SalesOrderItems" FromRole="FromRole_SalesOrderHeader_SalesOrderItem" ToRole="ToRole_SalesOrderItem_SalesOrderHeader"/>
      </EntityType>
      <EntityType Name="SalesOrderItem" sap:content-version="1">
        <Key>
          <PropertyRef Name="OrderId"/>
          <PropertyRef Name="Item"/>
        </Key>
        <Property Name="OrderId" Type="Edm.String" Nullable="false" MaxLength="10" sap:label="Sales Document" sap:filterable="false"/>
        <Property Name="Item" Type="Edm.String" Nullable="false" MaxLength="6" sap:label="Item" sap:filterable="false"/>
        <Property Name="Material" Type="Edm.String" MaxLength="18" sap:label="Material" sap:filterable="false"/>
        <Property Name="Description" Type="Edm.String" MaxLength="40" sap:label="Description" sap:filterable="false"/>
        <Property Name="Plant" Type="Edm.String" MaxLength="4" sap:label="Plant" sap:filterable="false"/>
        <Property Name="Quantity" Type="Edm.Decimal" Precision="19" Scale="3" sap:label="Order quantity" sap:filterable="false"/>
        <Property Name="UOM" Type="Edm.String" MaxLength="3" sap:label="Sales unit" sap:filterable="false" sap:semantics="unit-of-measure"/>
        <Property Name="Value" Type="Edm.Decimal" Precision="21" Scale="2" sap:label="Net value" sap:filterable="false"/>
        <NavigationProperty Name="SalesOrderHeader" Relationship="SALES_ORDER.SalesOrderItem_SalesOrderHeader" FromRole="FromRole_SalesOrderItem_SalesOrderHeader" ToRole="ToRole_SalesOrderHeader_SalesOrderItem"/>
      </EntityType>
      <Association Name="SalesOrderHeader_SalesOrderItems" sap:content-version="1">
        <End Type="SALES_ORDER.SalesOrderHeader" Multiplicity="1" Role="FromRole_SalesOrderHeader_SalesOrderItem"/>
        <End Type="SALES_ORDER.SalesOrderItem" Multiplicity="*" Role="ToRole_SalesOrderItem_SalesOrderHeader"/>
      </Association>
      <Association Name="SalesOrderItem_SalesOrderHeader" sap:content-version="1">
        <End Type="SALES_ORDER.SalesOrderItem" Multiplicity="1" Role="FromRole_SalesOrderItem_SalesOrderHeader"/>
        <End Type="SALES_ORDER.SalesOrderHeader" Multiplicity="1" Role="ToRole_SalesOrderHeader_SalesOrderItem"/>
      </Association>
      <EntityContainer Name="SALES_ORDER" m:IsDefaultEntityContainer="true">
        <EntitySet Name="SalesOrderHeaders" EntityType="SALES_ORDER.SalesOrderHeader" sap:content-version="1"/>
        <EntitySet Name="SalesOrderItems" EntityType="SALES_ORDER.SalesOrderItem" sap:content-version="1"/>
        <AssociationSet Name="AssocSet_SalesOrderHeader_SalesOrderItems" Association="SALES_ORDER.SalesOrderHeader_SalesOrderItems" sap:content-version="1">
          <End EntitySet="SalesOrderHeaders" Role="FromRole_SalesOrderHeader_SalesOrderItem"/>
          <End EntitySet="SalesOrderItems" Role="ToRole_SalesOrderItem_SalesOrderHeader"/>
        </AssociationSet>
        <AssociationSet Name="AssocSet_SalesOrderItem_SalesOrderHeader" Association="SALES_ORDER.SalesOrderItem_SalesOrderHeader" sap:content-version="1">
          <End EntitySet="SalesOrderItems" Role="FromRole_SalesOrderItem_SalesOrderHeader"/>
          <End EntitySet="SalesOrderHeaders" Role="ToRole_SalesOrderHeader_SalesOrderItem"/>
        </AssociationSet>
      </EntityContainer>
    </Schema>
  </edmx:DataServices>
</edmx:Edmx>

现在,如果我手动创建请求(按照软件供应商的说明),服务器接受请求并在ERP系统中创建文档。这就是该请求的样子:

<?xml version="1.0" encoding="UTF-8"?>
<atom:entry
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
  <atom:content type="application/xml">
    <m:properties>
      <d:DocumentType>ZCSH</d:DocumentType>
      <d:CustomerId>0001008657</d:CustomerId>
      <d:SalesOrg>1100</d:SalesOrg>
      <d:DistChannel>10</d:DistChannel>
      <d:Division>40</d:Division>
    </m:properties>
  </atom:content>
  <atom:link
  href="SalesOrderHeaders(0000004970)/SalesOrderItems"
  rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/SalesOrderItems"
  type="application/atom+xml;type=feed"
  title="SALES_ORDER.SalesOrderHeader_SalesOrderItems">
    <m:inline>
      <atom:feed>
        <atom:entry>
          <atom:content type="application/xml">
            <m:properties>
              <d:Item>000010</d:Item>
              <d:Material>70000559</d:Material>
              <d:Plant>570B</d:Plant>
              <d:Quantity m:Type="Edm.Decimal">1.000</d:Quantity>
            </m:properties>
          </atom:content>
        </atom:entry>
        <atom:entry>
          <atom:content type="application/xml">
            <m:properties>
              <d:Item>000020</d:Item>
              <d:Material>70000559</d:Material>
              <d:Plant>570B</d:Plant>
              <d:Quantity m:Type="Edm.Decimal">5</d:Quantity>
            </m:properties>
          </atom:content>
        </atom:entry>
      </atom:feed>
    </m:inline>
  </atom:link>
</atom:entry>

但是,在C#中使用以下代码,我无法让Items成为请求的一部分。他们只是没有露面。这是C#:

ServiceReference4.SALES_ORDER ser = new ServiceReference4.SALES_ORDER(uri);
        NetworkCredential c = nc;

        ser.WritingEntity += new EventHandler<System.Data.Services.Client.ReadingWritingEntityEventArgs>(ser_WritingEntity);
        ser.SendingRequest += new EventHandler<System.Data.Services.Client.SendingRequestEventArgs>(ser_SendingRequest);
        ser.Credentials = c;

        ServiceReference4.SalesOrderHeader soHeader = new ServiceReference4.SalesOrderHeader();
        ServiceReference4.SalesOrderItem soItem = new ServiceReference4.SalesOrderItem();

        soHeader = ServiceReference4.SalesOrderHeader.CreateSalesOrderHeader("");
        soHeader.DocumentType = "ZCSH";
        soHeader.DistChannel = "10";
        soHeader.Division = "40";
        soHeader.SalesOrg = "1100";            

        soItem = ServiceReference4.SalesOrderItem.CreateSalesOrderItem("", "10".PadLeft(6, '0'));
        soItem.Material = "70000559".PadLeft(18, '0');
        soItem.Plant = "570B";
        soItem.Quantity = 1;

        soItem.SalesOrderHeader = soHeader;
        soHeader.SalesOrderItems.Add(soItem);

        ser.AddToSalesOrderHeaders(soHeader);

        try
        {                
            System.Data.Services.Client.DataServiceResponse resp = ser.SaveChanges();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message + Environment.NewLine + ex.InnerException);
        }

但这是生成的请求:

<entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
  <category scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" term="SALES_ORDER.SalesOrderHeader" />
  <title />
  <author>
    <name />
  </author>
  <updated>2011-10-31T20:27:42.5387007Z</updated>
  <id>http://.../sap/opu/sdata/sap/SALES_ORDER/SalesOrderHeaders('')</id>
  <content type="application/xml">
    <m:properties>
      <d:Currency m:null="true" />
      <d:CustomerId m:null="true" />
      <d:DistChannel>10</d:DistChannel>
      <d:Division>40</d:Division>
      <d:DocumentDate m:type="Edm.DateTime" m:null="true" />
      <d:DocumentType>ZCSH</d:DocumentType>
      <d:OrderId m:null="false" />
      <d:OrderValue m:type="Edm.Decimal" m:null="true" />
      <d:SalesOrg>1100</d:SalesOrg>
    </m:properties>
  </content>
</entry>

我希望这是有道理的...非常感谢任何帮助。

由于

2 个答案:

答案 0 :(得分:0)

您需要明确告诉数据服务上下文(ser)这些对象之间存在链接。请查看AddLinkSetLink方法。这些页面上的示例与您尝试的内容非常接近。

底线,我认为你需要添加:

ser.AddLink(soHeader, "SalesOrderItems", soItem);
ser.SetLink(soItem, "SalesOrderHeader", soHeader);

希望这有帮助。

答案 1 :(得分:0)

嗯,据MS论坛上的人说,目前WCF DS客户端不支持这种类型的深插入请求。

巨无霸。