Nitin Varpe
Nitin Varpe

Reputation: 10694

Passing XElement to Webservice .The remote server returned an unexpected response: (400) Bad Request WebService

I was working on webservice.I want to pass XmlDocument to method in webservice.But read on one of the article to pass XElement instead. I am calling web service from windows form , but it throws exception

        XmlDocument doc = new XmlDocument();
        doc.Load(FilePath);

        MyClient client = new MyClient();
        XElement element = XElement.Load(new XmlNodeReader(doc));

        client.PassXml(element);//Exception at this line

        client.Close();

My webservice

Interface

 [OperationContract]
 [WebInvoke(Method = "POST",BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Xml)]
        string PassXml(XElement doc);

Class which extends interface

 public class Service: IService
    {
    public string PassXml(XElement doc)
    {
        //My Logic
        return "Done";
    }
}

I tried following way but cant get it worked

 [DataContract]
       public class XmlDoc
        {
           [DataMember]
           public XmlElement doc { get; set; }

        }

then assigning my Xelement to doc

XmlDoc xml = new XmlDoc();
  xml.doc =element;

and passing it to method throws same exception.

 client.PassXml(element);//Exception

Any Solutions

My Xml

<Main>
<Product SKU="101091">
    <Name>Anchor White Tooth Paste 200Gm</Name>
    <Mrp>54.0000</Mrp>
    <Price>53.2800</Price>
    <Cost>46.0463</Cost>
    <Barcode>101091,8904000900457,8904000900501,8904000900624,8904000900631,9910109100017,9910109100727</Barcode>
  </Product>
  <Product SKU="101094">
    <Name>Haldiram's Khari Bundi 40Gm</Name>
    <Mrp>10.0000</Mrp>
    <Price>9.1287</Price>
    <Cost>0.0000</Cost>
    <Barcode>101094,9910109400018,9910109400124,9910109401206</Barcode>
  </Product>
</Main>

app.config

<system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_INopService" closeTimeout="00:10:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
                    allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                    messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                    useDefaultWebProxy="true">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    <security mode="None">
                        <transport clientCredentialType="None" proxyCredentialType="None"
                            realm="" />
                        <message clientCredentialType="UserName" algorithmSuite="Default" />
                    </security>
                </binding>
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:64223/Service.svc"
                binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_INopService"
                contract="ServiceReference1.INopService" name="BasicHttpBinding_INopService" />
        </client>
    </system.serviceModel>

Upvotes: 0

Views: 564

Answers (2)

Tim
Tim

Reputation: 28530

To follow up Darin's comments regarding using a data contract, here's an example:

[DataContract]
public class Product
{

    [DataMember]
    public string SKU { get; set; }

    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public decimal MRP { get; set; }

    [DataMember]
    public decimal Price { get; set; }

    [DataMember]
    public decimal Cost { get; set; }

    [DataMember]
    List<string> Barcodes { get; set; }
}

You could then change your operation signature to:

string PassXml(List<Product> products);

However, it appears that the data you want to pass is already in XML, so another option would be to do this:

string PassXml(string xml);

Then you could do something like this:

XmlDocument doc = new XmlDocument();
doc.Load(FilePath);

try
{
    MyClient client = new MyClient();
    client.PassXml(doc.ToString());
    client.Close();
}
catch (Exception ex)
{
    client.Abort();
    // do something about the error
}

Then in your service implementation you could use XDocument.Parse() to turn the string back into an XDocument and do whatever processing you need.

Note also that if you're sending a lot of data, you might be exceeding the some of the limits of the service (which could also generate a 400 error). Try either of the above suggestions and if you still get a 400 error, post your service's config file.

ADDED

You run a risk with the second approach in exceeding maximum string content length (the default is 8192). I would increase the settings in your binding for maxReceivedMessageSize, maxBufferSize (these two must be equal) as well as maxStringContentLength to a larger value. I would suggest using 2147483647 to start for all three.

Upvotes: 1

shujaat siddiqui
shujaat siddiqui

Reputation: 1577

Try to wrap your element in a tag and pass it

postData = @"<string xmlns='http://schemas.microsoft.com/2003/10/Serialization/'><![CDATA[" + your XMLelement + "]]></string>";

Basically <![CDATA[""]]> stop the serializer to treat it as XML.

Upvotes: 0

Related Questions