Stéphane
Stéphane

Reputation: 11864

What is your prefered way to return XML from an ActionMethod in Asp.net MVC?

I am displaying charts that load the data asynchronously because the searches are the work to fetch the data is quite heavy. The data has to be return as XML to make the chart library happy.
My ActionMethods return a ContentResult with the type set as text/xml. I build my Xml using Linq to XML and call ToString. This works fine but it's not ideal to test.
I have another idea to achieve this which would be to return a view that builds my XML using the XSLT View engine.

I am curious and I always try to do the things "the right way". So how are you guys handling such scenarios?

Do you implement a different ViewEngine (like xslt) to build your XML or do you Build your XML inside your controller (Or the service that serves your controller)?

EDIT :

Since I need this to pass the data to a Charting Library, I have to follow their xml structure. Their notation is not the way i want to build my model classes at all. That's why I build the XML myself using Linq to XML and wonder if a template would be better.
Simple serialization is not what I look for

Upvotes: 2

Views: 1019

Answers (3)

Drew Noakes
Drew Noakes

Reputation: 311007

Given that you're using Linq to XML to compose the response XML, you might like to use the same approach I do.

I create a XDocument in the action method.

public ActionResult MyXmlAction()
{
    // Create your own XDocument according to your requirements
    var xml = new XDocument(
        new XElement("root",
            new XAttribute("version", "2.0"),
            new XElement("child", "Hello World!")));

    return new XmlActionResult(xml);
}

This reusable, custom ActionResult serialises the XDocument as XML text to the response stream for you.

public sealed class XmlActionResult : ActionResult
{
    private readonly XDocument _document;

    public Formatting Formatting { get; set; }
    public string MimeType { get; set; }

    public XmlActionResult(XDocument document)
    {
        if (document == null)
            throw new ArgumentNullException("document");

        _document = document;

        // Default values
        MimeType = "text/xml";
        Formatting = Formatting.None;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.Clear();
        context.HttpContext.Response.ContentType = MimeType;

        using (var writer = new XmlTextWriter(context.HttpContext.Response.OutputStream, Encoding.UTF8) { Formatting = Formatting })
            _document.WriteTo(writer);
    }
}

You can specify a MIME type (such as application/rss+xml) and whether the output should be indented if you need to. Both properties have sensible defaults.

If you need an encoding other than UTF8, then it's simple to add a property for that too.

Upvotes: 0

dove
dove

Reputation: 20674

I use my own custom ActionResult, which you could modify to your needs.

public class XmlDataResult : ActionResult
    {
        private readonly object _stringToConvertToXml;

        public XmlDataResult(string stringToConvertToXml)
        {
            _stringToConvertToXml = stringToConvertToXml;
        }

        public object StringToConvertToXml
        {
            get { return _stringToConvertToXml; }
        }

        public override void ExecuteResult(ControllerContext context)
        {
            if (_stringToConvertToXml != null)
            {
                context.HttpContext.Response.Clear();
                context.HttpContext.Response.ContentType = "text/xml";
                context.HttpContext.Response.Write(_stringToConvertToXml);
            }
        }
    }

Upvotes: 1

Darin Dimitrov
Darin Dimitrov

Reputation: 1038930

Write a custom action result:

public class XmlActionResult : ActionResult
{
    public XmlActionResult(object data)
    {
        Data = data;
    }

    public object Data { get; private set; }

    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.ContentType = "text/xml";

        // TODO: Use your preferred xml serializer 
        // to serialize the model to the response stream :
        // context.HttpContext.Response.OutputStream
    }
}

And in your controller action:

public ActionResult Index() 
{
    var model = _repository.GetModel();
    return new XmlActionResult(model);
}

Upvotes: 5

Related Questions