2

I am posting XmlDocument to ApiController (from windows service, service is working fine, it is posting correct, I used it in wcf web API), but XML is always null, what am I doing wrong?

I can post some class, such in tutorials, or Get any data and everything will be ok, but I can't post XmlDocument.

public class XmlController : ApiController
{
    public void PostXml(XmlDocument xml)
    {
       // code
    }
}

3 Answers 3

2

i follow the solution given by @Rhot but somehow it doesn't work so i edit like below which work for me:

public class XmlMediaTypeFormatter : MediaTypeFormatter
    {
        public XmlMediaTypeFormatter()
        {
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/xml"));
        }

        public override bool CanReadType(Type type)
        {
            return type == typeof(XDocument);
        }

        public override bool CanWriteType(Type type)
        {
            return type == typeof(XDocument);
        }

        public override Task<object> ReadFromStreamAsync(Type type, Stream stream, HttpContent content, IFormatterLogger formatterLogger)
        {
            var reader = new StreamReader(stream);
            string value = reader.ReadToEnd();            

            var tcs = new TaskCompletionSource<object>();
            try
            {
                var xmlDoc = XDocument.Parse(value);
                tcs.SetResult(xmlDoc);
            }
            catch (Exception ex)
            {
                //disable the exception and create custome error
                //tcs.SetException(ex);
                var xml = new XDocument(
                    new XElement("Error",
                        new XElement("Message", "An error has occurred."),
                        new XElement("ExceptionMessage", ex.Message)
                ));

                tcs.SetResult(xml);
            }

            return tcs.Task;
        }

        public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContent content, TransportContext transportContext)
        {
            var writer = new StreamWriter(stream);
            writer.Write(((XDocument)value).ToString());
            writer.Flush();

            var tcs = new TaskCompletionSource<object>();
            tcs.SetResult(null);
            return tcs.Task;
        }              
    }

register to global.asax:

GlobalConfiguration.Configuration.Formatters.Insert(0, new XmlMediaTypeFormatter());

and below my WebAPI Controller:

public HttpResponseMessage Post(XDocument xml)
        {            
            return Request.CreateResponse(HttpStatusCode.OK, xml);
        }
Sign up to request clarification or add additional context in comments.

Comments

1

I've found a solution:

We need to use inheritance to inherit MediaTypeFormatter

public class XmlMediaTypeFormatter : MediaTypeFormatter
{
    public XmlMediaTypeFormatter()
    {
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/xml"));      
    }

    public override System.Threading.Tasks.Task<object> ReadFromStreamAsync(Type type, Stream stream,
         HttpContentHeaders contentHeaders,
         IFormatterLogger formatterLogger)
    {
        var taskCompletionSource = new TaskCompletionSource<object>();
        try
        {
            var memoryStream = new MemoryStream();
            stream.CopyTo(memoryStream);
            var s = System.Text.Encoding.UTF8.GetString(memoryStream.ToArray());

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(s);

            taskCompletionSource.SetResult(xmlDoc);
        }
        catch (Exception e)
        {
            taskCompletionSource.SetException(e);
        }
        return taskCompletionSource.Task;
    }

    public override bool CanReadType(Type type)
    {
        return type == typeof(XmlDocument);
    }

    public override bool CanWriteType(Type type)
    {
        return false;
    }
}

Then register it in Global.asax:

GlobalConfiguration.Configuration.Formatters.Insert(0, new XmlMediaTypeFormatter());

Controller:

public HttpResponseMessage PostXml([FromBody] XmlDocument xml)
    {//code...}

Comments

0

Is PostXml supposed to be an action on a controller? If so you should mark your controller action as accepting an HttpPost. From there I would modify the action to work as follows:

[HttpPost]
public ActionResult PostXml(HttpPostedFileBase xml)
{
    // code
}

If you are still have trouble accepting the posted files, fire up the debugger and inspect the Request files collection: http://msdn.microsoft.com/en-us/library/system.web.httprequest.files.aspx

1 Comment

It's not mvc controller, it's apicontroller, and following this asp.net/web-api/overview/creating-web-apis/… there's no necessity to add [HttpPost] attribute. Moreover xml is null too in your example.

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.