Question

OK, so I have a MediaTypeFormatter:

public class iOSDeviceXmlFormatter : BufferedMediaTypeFormatter
{
    public iOSDeviceXmlFormatter() {
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/xml"));
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/xml"));
    }
    public override bool CanReadType(Type type) {
        if (type == typeof(iOSDevice)) {
            return true;
        }
        return false;
    }

    public override object ReadFromStream(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger) {
        iOSDevice device = null;
        using (XmlReader reader = XmlReader.Create(readStream)) {
            if (reader.ReadToFollowing("iOSDevice")) {
                if (!reader.IsEmptyElement) {
                    device = new iOSDevice();
                    ... do processing here ...
                }
            }
        }
        readStream.Close();
        return device;
    }

I have this action to handle PUT:

    public void Put(string id, iOSDevice model)
    {
    }

I have tried this as well:

    public void Put(string id, [FromBody]iOSDevice model)
    {
    }

And I've tried this:

    public void Put(string id, [FromBody]string value)
    {
    }

None of these work when I do this:

string data = "<iOSDevice>xml_goes_here</iOSDevice>";
WebClient client = new WebClient();
client.UploadString(url, "PUT", data);

The action refuses to trigger my iOSDeviceXmlFormatter, and it won't even read it as a [FromBody] string. How do you get this thing to map?

Thanks,

Allison

Était-ce utile?

La solution

How did you register your formatter? You'll want to register this formatter in the first position so that it takes precedence over WebAPI's default formatters. The code would look like this:

config.Formatters.Insert(0, new iOSDeviceXmlFormatter());

That should make sure that any requests that come in with content-type application/xml or text/xml for type iOSDevice use your formatter for deserialization.

Autres conseils

You have specified that your formatter will be triggered for the following request Content-Type headers:

SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/xml"));
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/xml"));

But you haven't set them in the request. That's why your custom formatter is never trigerred. So once you register it in the global configuration:

config.Formatters.Insert(0, new iOSDeviceXmlFormatter());

You should make sure that you are setting the proper request Content-Type header:

string data = "<iOSDevice>xml_goes_here</iOSDevice>";
using (WebClient client = new WebClient())
{
    // That's the important part that you are missing in your request
    client.Headers[HttpRequestHeader.ContentType] = "text/xml";
    var result = client.UploadString(url, "PUT", data);
}

Now the following action will be trigerred:

public void Put(string id, iOSDevice model)
{
}

and of course your custom formatter will be invoked before in order to instantiate your iOSDevice from the request.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top