21

I have a Web Api method which should return an xml data but it returns string:

 public class HealthCheckController : ApiController
    {       
        [HttpGet]
        public string Index()
        {
            var healthCheckReport = new HealthCheckReport();

            return healthCheckReport.ToXml();
        }
    }

It returns:

<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">
<myroot><mynode></mynode></myroot>
</string>

and I have added this mapping:

 config.Routes.MapHttpRoute(
              name: "HealthCheck",
              routeTemplate: "healthcheck",
              defaults: new
              {
                  controller = "HealthCheck",
                  action = "Index"
              });

How to make it return just the xml bits:

<myroot><mynode></mynode></myroot>

If I was using just MVC, I could be using the below but Web API doesn't support "Content":

 [HttpGet]
        public ActionResult Index()
        {
            var healthCheckReport = new HealthCheckReport();

            return Content(healthCheckReport.ToXml(), "text/xml");
        }

I have also added the below codes to the WebApiConfig class:

 config.Formatters.Remove(config.Formatters.JsonFormatter);
 config.Formatters.XmlFormatter.UseXmlSerializer = true;
The Light
  • 26,341
  • 62
  • 176
  • 258
  • 1
    Can you just return the HealthCheckReport instance, and let the XML formatter do the serialization? Right now, you are serializing to XML in your controller and then passing that string to the XML formatter. Then the XML formatter serializes the string to XML. – Mike Wasson Mar 14 '13 at 17:29

1 Answers1

45

The quickest way is this,

 public class HealthCheckController : ApiController
 {       
     [HttpGet]
     public HttpResponseMessage Index()
     {
         var healthCheckReport = new HealthCheckReport();

         return new HttpResponseMessage() {Content = new StringContent( healthCheckReport.ToXml(), Encoding.UTF8, "application/xml" )};
     }
 }

but it is also very easy to build a new XmlContent class that derives from HttpContent to support XmlDocument or XDocument directly. e.g.

public class XmlContent : HttpContent
{
    private readonly MemoryStream _Stream = new MemoryStream();

    public XmlContent(XmlDocument document) {
        document.Save(_Stream);
            _Stream.Position = 0;
        Headers.ContentType = new MediaTypeHeaderValue("application/xml");
    }

    protected override Task SerializeToStreamAsync(Stream stream, System.Net.TransportContext context) {

        _Stream.CopyTo(stream);

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

    protected override bool TryComputeLength(out long length) {
        length = _Stream.Length;
        return true;
    }
}

and you can use it just like you would use StreamContent or StringContent, except that it accepts a XmlDocument,

public class HealthCheckController : ApiController
{       
    [HttpGet]
    public HttpResponseMessage Index()
    {
       var healthCheckReport = new HealthCheckReport();

       return new HttpResponseMessage() {
           RequestMessage = Request,
           Content = new XmlContent(healthCheckReport.ToXmlDocument()) };
    }
}
Josh Gallagher
  • 5,211
  • 2
  • 33
  • 60
Darrel Miller
  • 139,164
  • 32
  • 194
  • 243