简体   繁体   中英

Pass value to SOAP API complex type

I'm calling a SOAP API using Server Reference, there is a complex type which requires weight values. I'm setting the values using the following code:

parcel objpcl = new parcel();
objpcl.weight = 10;
objpcl.length = 10;
objpcl.width = 10;
objpcl.depth = 10;
objpcl.girth = 10;
objpcl.combinedDimension = 10;
objpcl.volume = 10;
objpcl.value = 100;

The response returns and error stating "Invalid Weight". Here are the WSDL details:

  <xs:complexType name="parcel">
    <xs:sequence>
      <xs:element minOccurs="0" name="weight" type="xs:decimal" />
      <xs:element minOccurs="0" name="length" type="xs:decimal" />
      <xs:element minOccurs="0" name="width" type="xs:decimal" />
      <xs:element minOccurs="0" name="depth" type="xs:decimal" />
      <xs:element minOccurs="0" name="girth" type="xs:decimal" />
      <xs:element minOccurs="0" name="combinedDimension" type="xs:decimal" />
      <xs:element minOccurs="0" name="volume" type="xs:decimal" />
      <xs:element minOccurs="0" name="currency" type="xs:string" />
      <xs:element minOccurs="0" name="value" type="xs:decimal" />
      <xs:element minOccurs="0" name="numberOfParts" type="xs:decimal" />
      <xs:element minOccurs="0" name="numberOfItems" type="xs:decimal" />
      <xs:element minOccurs="0" name="hangingGarment" type="xs:boolean" />
      <xs:element minOccurs="0" name="theftRisk" type="xs:boolean" />
      <xs:element minOccurs="0" name="multipleParts" type="xs:boolean" />
      <xs:element minOccurs="0" name="catalogue" type="xs:boolean" />
      <xs:element minOccurs="0" name="description" type="xs:string" />
      <xs:element minOccurs="0" name="originOfParcel" type="xs:string" />
    </xs:sequence>
  </xs:complexType>

When I make the call using SOAPUI the call completes without an error. Below is the complete code, I'm hard coding the values for now to complete my testing, so any recommendation will have to account for the fact that I will be populating from database values.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using HermesWebService;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }
    protected void Button1_Click(object sender, EventArgs e)
    {
        RoutingWebServiceClient objHermesWebService = new RoutingWebServiceClient();
        objHermesWebService.ClientCredentials.UserName.UserName = "ababab";
        objHermesWebService.ClientCredentials.UserName.Password = "abababa";

        deliveryRoutingRequest objRoutingRequest = new deliveryRoutingRequest();
        objRoutingRequest.clientId = "aba";
        objRoutingRequest.clientName = "aba";
        objRoutingRequest.userId = "abababa";
        objRoutingRequest.sourceOfRequest = "ababab";

        delRoutingRequestEntry objReqEntry = new delRoutingRequestEntry();
                objReqEntry.expectedDespatchDate = Convert.ToDateTime("2015-04-10T00:00:00");
    objReqEntry.countryOfOrigin = "US";

        customer objCust = new customer();
        objCust.customerReference1 = "12345";

        address objadr = new address();
        objadr.lastName = "Robinson";
        objadr.streetName = "Eastern Perimeter Road";
        objadr.addressLine1 = "London Heathrow Airport";
        objadr.city = "London";
        objadr.region = "Hounslow";
        objadr.postCode = "TW6 2GE";
        objadr.countryCode = "GB";

        parcel objpcl = new parcel();
        objpcl.weight = 10m;
        objpcl.length = 10m;
        objpcl.width = 10m;
        objpcl.depth = 10m;
        objpcl.girth = 10m;
        objpcl.combinedDimension = 10m;
        objpcl.volume = 10m;
        objpcl.value = 100;

        objCust.address = objadr;
        objReqEntry.customer = objCust;
        objReqEntry.parcel = objpcl;

        objRoutingRequest.deliveryRoutingRequestEntries = new [] {objReqEntry};


        //var request = new delroutingrequestentry
        //{
        //    addressvalidationrequired = false
        //};

        //request.parcel = objpcl;
        //objroutingrequest.deliveryroutingrequestentries[0] = request;

        var x = objHermesWebService.validateDeliveryAddress(objRoutingRequest);

    }
}

After running the Microsoft Service Trace Viewer it appears that the Parcel element is not making it to the API call, here is a copy of part of the trace viewer log:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<ActivityId CorrelationId="58ef72b0-fd4d-475f-9347-5f1ba25f5987" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">7f7337fb-8db5-4b84-8e6c-44d7f43d561a</ActivityId>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<validateDeliveryAddress xmlns="http://v2.web.domain.routing.hermes.co.uk/">
<deliveryRoutingRequest>
<clientId xmlns="">aba</clientId>
<clientName xmlns="">aba</clientName>
<userId xmlns="">ababab</userId>
<sourceOfRequest xmlns="">ababab</sourceOfRequest>
<deliveryRoutingRequestEntries xmlns="">
<deliveryRoutingRequestEntry>
<customer>
<address>
<lastName>Robinson</lastName>
<streetName>Eastern Perimeter Road</streetName>
<addressLine1>London Heathrow Airport</addressLine1>
<city>London</city>
<region>Hounslow</region>
<postCode>TW6 2GE</postCode>
<countryCode>GB</countryCode>
</address>
<customerReference1>12345</customerReference1>
</customer>
<parcel></parcel>
<expectedDespatchDate>2015-04-10</expectedDespatchDate>
<countryOfOrigin>US</countryOfOrigin>
</deliveryRoutingRequestEntry>
</deliveryRoutingRequestEntries>
</deliveryRoutingRequest>
</validateDeliveryAddress>
</s:Body>
</s:Envelope>

I had a feeling the problem had a simple solution that I was overlooking. Each decimal field has a corresponding field which ends in Specified. The Specified field is a boolean which must be set to true in order for the field value to be sent during the serialization. There are additional post ( XmlSerializer, "Specified" suffix and IReflect ) which define better ways of accomplishing this; for now I manually specify:

    var objpcl = new parcel
    {
        weight = 10, weightSpecified = true,
        length = 10, lengthSpecified = true,
        width = 10, widthSpecified = true,
        depth = 10, depthSpecified = true, 
        girth = 10, girthSpecified = true,
        combinedDimension = 10, combinedDimensionSpecified = true,
        volume = 10, volumeSpecified = true,
        value = 100, valueSpecified = true,
        numberOfParts = 1, numberOfPartsSpecified = true,
        numberOfItems = 10, numberOfItemsSpecified = true,            
        description = "Test Package",
        originOfParcel = "US",
    };

If I spent a little more time reviewing the WSDL file I would have noticed the following:

    [XmlElement(Form = XmlSchemaForm.Unqualified, Order = 0)]
    public decimal weight { get; set; }
    [XmlIgnore]
    public bool weightSpecified { get; set; }

/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool weightSpecified
{
    get
    {
        return this.weightFieldSpecified;
    }
    set
    {
        this.weightFieldSpecified = value;
        this.RaisePropertyChanged("weightSpecified");
    }
}

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM