Reputation: 67195
I've create a SitemapResult
class that derives from ActionResult
. It allows the caller to add any number of URL resources, and it then outputs sitemap data in XML format.
public class SitemapResult : ActionResult
{
private List<SitemapUrl> SitemapItems;
public SitemapResult()
{
SitemapItems = new List<SitemapUrl>();
}
public void AddUrl(string url, DateTime? lastModified = null, SitemapFrequency? frequency = null, double? priority = null)
{
AddUrl(new SitemapUrl(url, lastModified, frequency, priority));
}
public override void ExecuteResult(ControllerContext context)
{
context.HttpContext.Response.ContentType = "text/xml; charset=utf-8";
using (XmlWriter writer = XmlWriter.Create(context.HttpContext.Response.Output))
{
// TODO: Write sitemap data to output
}
}
}
The problem is that the class stores all the URLs until ExecuteResult()
is called. It seems like it would be more efficient if I could write each URL to the response as they are added rather than hold them all in memory and then write every thing at once.
Does anyone know of any good examples of overriding ActionResult
to write data to the response as it becomes available? In this case, I would think ExecuteResult()
won't need to write anything at all.
Upvotes: 3
Views: 80
Reputation: 15559
What you are trying to achieve, is building your model inside the view (custom view)... that's not a good practice... in MVC, controllers are responsible for building the model and passing it to the view... views are responsible for displaying the model and should have as little logic as possible.
It seems like it would be more efficient if I could write each URL to the response as they are added rather than hold them all in memory and then write every thing at once.
Why? You need to keep SitemapItems
somewhere in the memory, so even if you write them to response, they are still kept in memory until you return the response... and I think it would be more efficient to serialize the whole list to XML at one go, as opposed to serializing each SitemapUrl
individually.
There is a very elegant solution to your question on this pluralsight course:
public class SitemapResult : ActionResult
{
private object _data;
public SitemapResult(object data)
{
_data = data;
}
public override void ExecuteResult(ControllerContext context)
{
// you can use reflection to determine object type
XmlSerializer serializer = new XmlSerializer(_data.GetType());
var response = context.HttpContext.Response;
response.ContentType = "text/xml";
serializer.Serialize(response.Output, _data);
}
}
And you build your model in the controller, and pass it to the view:
return new SitemapResult(SitemapItems);
If you want to directly write to the Response you can do it in the controller:
public MyController : controller
{
public void GetSiteMapUrls()
{
XmlSerializer serializer = new XmlSerializer(SitemapItems.GetType());
Response.ContentType = "text/xml";
serializer.Serialize(Response.Output, SitemapItems);
}
}
Upvotes: 1