Zachary
Zachary

Reputation: 6532

Problem passing object between WCF and ASMX using DataContracts

I'm trying to use ASMX/WCF to pass objects between sites (public / private). I can get the serialized object from my private ASMX service to my public WCF service, but I can't deserialize the object. Code below followed by error.

WCF service that calls a private ASMX service.

[WebGet(UriTemplate = "{part}")]
public Distributor GetDistributorInventory(string part)
{
    const string url = "http://www.site.com/service/lookup.asmx/StockCheck?part=" + part;
    //This is a wrapper for a HttpWebRequest that returns a string
    string results = WebHelper.HttpRequest("GET", "text/xml", null, url, new CookieContainer());  
    byte[] byteArray = Encoding.ASCII.GetBytes(results);
    MemoryStream stream = new MemoryStream(byteArray);
    DataContractSerializer deserialize = new DataContractSerializer(typeof(Distributor));
    return (Distributor)deserialize.ReadObject(stream);
}

Contract used in both Public/Private Services

[DataContract(Namespace = "http://www.site.com/Services/", Name = "Inventory")]
public class Inventory
{
    [DataMember(Order = 1)]
    public string MPN{ get; set; }
    [DataMember(Order = 2)]
    public string DataSheetURL { get; set; }
    [DataMember(Order = 3)]
    public List<Distributor> Stock { get; set; }
}

[DataContract(Namespace = "http://www.site.com/Services/", Name = "Distributor")]
public class Distributor
{
    [DataMember(Order = 1)]
    public string Name { get; set; }
    [DataMember(Order = 2)]
    public string Part { get; set; }
    [DataMember(Order = 3)]
    public int Quantity { get; set; }
    [DataMember(Order = 4)]
    public string URL { get; set; }
}

Error Message:

Error in line 1 position 166. Expecting element 'Distributor' from namespace 'http://www.site.com/Services/'.. Encountered 'Element' with name 'Inventory', namespace 'http://www.site.com/Services/'.

I might be going about this the entirely wrong way, so suggestions on a better approach (with sample) would greatly appreciate. My end goal is to pass objects between WCF & WCF or ASMX services using custom objects and DataContracts.

Upvotes: 0

Views: 1560

Answers (3)

Zachary
Zachary

Reputation: 6532

Here is the final solution I found for making this work, with the least amount of work possible.

  1. I switched from passing my object as XML to JSON (was my final goal, tho I started with XML)

  2. After getting my JSON object received, I noticed it had a wrapper "d:" and had a property "__type:" that was being added. Knowing these needed to be removed, I decided to find a generic way to remove the elements.

  3. My generic solution was to use this code/article on Codeplex that had extension methods that did the clean-up using Reg Ex. Very simple.

Here is my resulting code:

[WebGet(UriTemplate = "{part}")]
public Distributor GetDistributorInventory(string part)
{
  const string url = "http://www.site.com/service/lookup.asmx/StockCheck";
  string results = WebHelper.HttpRequest("POST", "application/json; charset=utf-8", "{part: " + part + "}", url, new CookieContainer());

  Inventory inventory = new JavaScriptSerializer().CleanAndDeserialize<Inventory>(results);

  return inventory;
}

Another perk to this solution, is the ability to convert the object regardless of namespace. This results in being able to use the object "sender.Inventory" in my source ASMX service and the object "receiver.Inventory" in my WCF service where I'm going to consume the object.

Upvotes: 0

CyberDude
CyberDude

Reputation: 8949

Looks like it's trying to deserialize as Distributor but the response from the StockCheck call is returning a Inventory.

Upvotes: 2

Preet Sangha
Preet Sangha

Reputation: 65466

The asmx service is probably not using the DataContractSerialiser. Here is short video on on how to do custom serialisation in a the ASMX service.

Or you could deserialise in the WCF service using the same serialiser that the asmx service is using (XmlSerialiser?)

Another option is to use the Json serialiser instead. There is an example here.

Upvotes: 0

Related Questions