0

I'm having a really hard time getting Web API to work with XML. It seems like it should work for XML, but many of the beginner tutorials only pass ints and string to a very simple model.

I was able to extract the XML from the HttpWebRequest, but I want to try and bind the XML to a model. I'm confused on how I use XML for posting, though.

Every time I post XML (any XML, I'm just experimenting) to my ApiController method, the model object I created for the XML is null. So, I assume that there's something not wired up. I'm not sure if I have to add an entry to the Global.asax.cs file or if I need a helper class or what.

Can someone point me in the right direction? (Please no "Just use JSON" suggestions. I want to do JSON, too, but I also want to know how to get XML working, as well.)

Thanks!!

2
  • Just for fun, I created a model object in my post method, populated it with test values and returned it. An empty string came back to the client. Weird... Commented Nov 28, 2012 at 13:21
  • After adding the content-type to the post, I got XML back. I changed my method to return the model object it receives. When I posted the XML back with new values, the new values came back to me. But, what if my XML is more complicated or what if the XML isn't under my control? I want to be able to setup ANY XML document with a model. How do I set that up? Commented Nov 28, 2012 at 14:30

1 Answer 1

1

The easiest approach is to perform a simple get against your object to get an example of the XML to send back.

Things to remember:

  1. Include the namespace xmlns:i="http://www.w3.org/2001/XMLSchema-instance" this is needed to indicate null values
  2. If using the standard XML serialiser config you need the namespace too e.g. xmlns="http://schemas.datacontract.org/2004/07/MvcApplication10.Controllers"
  3. When doing a get set the accept header to accept: application/xml
  4. When posting to the controller set content type. content-type: application/xml

Using the example object and controller.

public class Foo
{
    public string Bar { get; set; }
}

public class FoosController : ApiController
{
    // GET api/foos
    public Foo Get()
    {
        return new Foo { Bar = "Test" }; 
    }

    // GET api/foos
    public Foo Post(Foo test)
    {
        return test;
    }
}

I do a GET on the /api/foos and get an example object:

User-Agent: Fiddler
Host: localhost
accept: application/xml

Response:

<Foo xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/MvcApplication10.Controllers"><Bar>Testing</Bar></Foo>

To Post it back I simply set the content-type header alter a value in the xml and post it back:

User-Agent: Fiddler
Host: localhost:61280
content-type: application/xml
Content-Length: 167

Request

<Foo xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/MvcApplication10.Controllers"><Bar>Testing Response</Bar></Foo

Response

<Foo xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/MvcApplication10.Controllers"><Bar>Testing Response</Bar></Foo>

Update

For complicated XML models you need to start using DataContract annotations http://msdn.microsoft.com/en-us/library/ms731045.aspx.

Example:

[DataContract(Name = "Person")]
public class Foo
{
    [DataMember(Name = "Address", IsRequired = False)]
    public string Bar { get; set; }
}

This alters the XML required

<Person xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/MvcApplication10.Controllers"><Address>Testing Response</Address></Person>

For collections etc look here http://msdn.microsoft.com/en-us/library/aa347850.aspx

Sign up to request clarification or add additional context in comments.

7 Comments

I added item 4 to my client application and got an XML response for my test object. That's a step in the right direct!
But, let's say the XML I need to post isn't the exact same as the XML generated by Web API. How do I compensate for the differences?
@Darkwater23 there is no reason why you couldn't declare your controller like this and expect a model in one form but return another. public Bar Post(Foo test)... i.e. post it a Foo and get a Bar back.... (obviously you will need to handle the mapping between these types in the code somewhere). In JSON you can look at Dynamic Objects and JTokens for extra flexibility hanselman.com/blog/…
I'm still missing something. If I handed you an XML file you've never seen before, your first step to use it with Web API is to create a model class, right? In your example, the element names and property names line up. What if they didn't? What if I had elements like <someElement> and you wanted your field to be object.SomeElement? Or, if there were nested elements that you need to turn into a IEnumerable property? How does that get handled?
@Darkwater23 the XML formatter in WebApi uses the DataContract serialiser. Apologies my example was deliberately simple. You can read about this stuff here: msdn.microsoft.com/en-us/library/ms733127.aspx But examples would require annotations like // The default is overridden to become "Address". [DataMember(Name = "Address")] public string Ship_to;
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.