Переопределение ActionResult без кэширования данных - PullRequest
0 голосов
/ 27 ноября 2018

Я создал SitemapResult класс, производный от ActionResult.Он позволяет вызывающей стороне добавлять любое количество ресурсов URL, а затем выводит данные карты сайта в формате XML.

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

        }
    }
}

Проблема заключается в том, что класс хранит все URL до тех пор, пока не будет вызван ExecuteResult().Кажется, было бы более эффективно, если бы я мог записать каждый URL-адрес в ответ по мере их добавления, а не хранить их все в памяти, а затем записывать все сразу.

Кто-нибудь знает какие-либо хорошие примерыпереопределить ActionResult для записи данных в ответ, когда он станет доступным?В этом случае я бы подумал, что ExecuteResult() вообще ничего не нужно будет писать.

1 Ответ

0 голосов
/ 28 ноября 2018

То, чего вы пытаетесь достичь, - это построение вашей модели в представлении (пользовательском представлении) ... это не очень хорошая практика ... в MVC контроллеры отвечают за построение модели и передачу ее в представление.Представления отвечают за отображение модели и должны иметь как можно меньше логики.


Похоже, было бы более эффективно, если бы я мог записывать каждый URL-адрес в ответ по мере их добавления, а не хранить их все в памяти, а затем записывать все сразу.

Почему?Вам нужно хранить SitemapItems где-то в памяти, поэтому даже если вы напишите их в ответ, они все еще будут храниться в памяти, пока вы не вернете ответ ... и я думаю, что было бы более эффективно сериализовать весь список в XMLза один раз, в отличие от сериализации каждого SitemapUrl в отдельности.


Существует очень элегантное решение для вашего вопроса по этому универсальному курсу :

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);
    }
}

И вы строите свою модель в контроллере и передаете ее в представление:

return new SitemapResult(SitemapItems);

Если вы хотите напрямую написать в ответ, вы можете сделать это в контроллере:

public MyController : controller
{
    public void GetSiteMapUrls()
    {
        XmlSerializer serializer = new XmlSerializer(SitemapItems.GetType());
        Response.ContentType = "text/xml";
        serializer.Serialize(Response.Output, SitemapItems);
    }
}
...