RSS-каналы в ASP.NET MVC

#c# #asp.net #asp.net-mvc-3

#asp.net-mvc #RSS-канал

Вопрос:

Как бы вы порекомендовали обрабатывать RSS-каналы в ASP.NET MVC? Используете стороннюю библиотеку? Используя RSS-материалы в BCL? Просто создаем RSS-представление, которое отображает XML? Или что-то совершенно другое?

Комментарии:

1. Используя RssToolkit, вам просто нужно иметь один файл .ashx в вашем проекте для создания RSS-канала. Затем вы можете переписать его URL на более удобный. Я думаю, что в этом подходе нет ничего против MVC.

2. Вот последующее сообщение, в котором идея RssActionResult развивается немного дальше с помощью обобщенного класса результатов SyndicationAction, а также 304 немодифицированного фильтра условного получения. 58bits.com/blog /…

3. Я написал RssResult, на который вы можете взглянуть, если хотите. Это должно соответствовать вашим требованиям http://www.wduffy.co.uk/blog/rssresult-aspnet-mvc-rss-actionresult /

4. Просто чтобы обновить этот вопрос по состоянию на 18 месяцев после последнего редактирования — казалось разумным задать вопрос «изменилось ли что-то с итерациями для обоих. сеть и mvc, которые изменили бы наш подход к проблеме управления каналами»? Консенсус (через другой поток SO) заключается в том, что «Никаких фундаментальных изменений — это остается вашим лучшим набором альтернатив».

5. плохое предложение для ASP.NET MVC.

Ответ №1:

Платформа .NET Framework предоставляет классы, которые обрабатывают синдицирование: SyndicationFeed и т.д. Итак, вместо того, чтобы выполнять рендеринг самостоятельно или использовать какую-либо другую предлагаемую библиотеку RSS, почему бы не позволить фреймворку позаботиться об этом?

В принципе, вам просто нужен следующий пользовательский ActionResult, и вы готовы к работе:

 public class RssActionResult : ActionResult
{
    public SyndicationFeed Feed { get; set; }

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

        Rss20FeedFormatter rssFormatter = new Rss20FeedFormatter(Feed);
        using (XmlWriter writer = XmlWriter.Create(context.HttpContext.Response.Output))
        {
            rssFormatter.WriteTo(writer);
        }
    }
}
  

Теперь в вашем действии контроллера вы можете просто вернуть следующее:

 return new RssActionResult() { Feed = myFeedInstance };
  

Полный пример есть в моем блоге по адресуhttp://www.developerzen.com/2009/01/11/aspnet-mvc-rss-feed-action-result /

Ответ №2:

Вот что я рекомендую:

  1. Создайте класс с именем RssResult, который наследует абстрактный базовый класс ActionResult.
  2. Переопределите метод ExecuteResult.
  3. У ExecuteResult есть ControllerContext, переданный ему вызывающим, и с его помощью вы можете получить данные и тип контента.
  4. Как только вы измените тип контента на rss, вам захочется сериализовать данные в RSS (используя свой собственный код или другую библиотеку) и записать в ответ.

  5. Создайте действие на контроллере, которому вы хотите возвращать rss, и задайте возвращаемый тип как RssResult. Извлекайте данные из вашей модели на основе того, что вы хотите вернуть.

  6. Тогда любой запрос к этому действию получит RSS любых данных, которые вы выберете.

Это, вероятно, самый быстрый и многократно используемый способ возврата rss имеет ответ на запрос в ASP.NET MVC.

Комментарии:

1. У Хансельмана есть похожее решение (видео: начинается примерно с 41m), где он наследует FileResult. Поступая таким образом, вы можете вызвать конструктор вашего класса base("application/rss xml") и избежать шагов 3 и 4. Он переопределяет ExecuteResult, но это не жизненно важно. Он также сокращает множество типично домотканого кода и использует более 3,5 функций SyndicateItem , SyndicateFeed и Rss20FeedFormatter .

2. @Dale: возможно ли записать в ответ, когда вы хотите вывести в канал частичное представление? Спасибо.

3. Обновлена ссылка на видео Хансельмана из моего предыдущего комментария.

Ответ №3:

Я согласен с хаком. В настоящее время я внедряю свой сайт / блог с использованием MVC Framework, и я выбрал простой подход создания нового представления для RSS:

 <%@ Page ContentType="application/rss xml" Language="C#" AutoEventWireup="true" CodeBehind="PostRSS.aspx.cs" Inherits="rr.web.Views.Blog.PostRSS" %><?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>ricky rosario's blog</title>
<link>http://<%= Request.Url.Host %></link>
<description>Blog RSS feed for rickyrosario.com</description>
<lastBuildDate><%= ViewData.Model.First().DatePublished.Value.ToUniversalTime().ToString("r") %></lastBuildDate>
<language>en-us</language>
<% foreach (Post p in ViewData.Model) { %>
    <item>
    <title><%= Html.Encode(p.Title) %></title>
    <link>http://<%= Request.Url.Host   Url.Action("ViewPostByName", new RouteValueDictionary(new { name = p.Name })) %></link>
    <guid>http://<%= Request.Url.Host   Url.Action("ViewPostByName", new RouteValueDictionary(new { name = p.Name })) %></guid>
    <pubDate><%= p.DatePublished.Value.ToUniversalTime().ToString("r") %></pubDate>
    <description><%= Html.Encode(p.Content) %></description>
    </item>
<% } %>
</channel>
</rss>
  

Для получения дополнительной информации ознакомьтесь с (shameless plug)http://rickyrosario.com/blog/creating-an-rss-feed-in-asp-net-mvc

Комментарии:

1. для использования Razor: @model PageModel @{Ответ. ContentType = «application/rss xml»; }<?версия xml=»1.0″ кодировка= «UTF-8» ?>

2. Какие накладные расходы? вы имеете в виду тот факт, что вы пишете меньше кода, чтобы выполнить то же самое более читаемым способом?

Ответ №4:

Другой безумный подход, но имеющий свое преимущество, заключается в использовании обычного представления .aspx для отображения RSS. В вашем методе action просто установите соответствующий тип контента. Одним из преимуществ этого подхода является то, что легко понять, что визуализируется и как добавлять пользовательские элементы, такие как геолокация.

Опять же, другие перечисленные подходы могли бы быть лучше, я просто их не использовал. 😉

Комментарии:

1. @Haacked: Мир полон недопустимого RSS XML, сгенерированного системой шаблонов. Пожалуйста, не добавляйте беспорядка! Рики, кодировка HTML != кодировка XML.

2. Ниже приведена документация по кодированию Html из MSDN: > Из-за текущих деталей реализации эта функция может использоваться как функция xmlEncode. В настоящее время все именованные объекты, используемые этой функцией, также являются предопределенными xml именованными объектами. Они < > » amp; кодируются как < > » и amp;amp;. Другие объе кты имеют десятичную кодировку, например amp;# 160;. http://msdn.microsoft.com/en-us/library/73z22y6h.aspx

3. Как вы можете убедиться, что XML действителен, делая это таким образом? Было бы неплохо, если бы рендеринг представления был отделен от входящего веб-запроса, чтобы сделать возможными XML-представления или шаблоны электронной почты, подобные выполненным ruby on rails.

4. Вместо того, чтобы использовать механизм просмотра, вы могли бы создать RssResult, который является производным от ActionResult . Мы делаем это с помощью JsonResult, который сериализует объект в JSON. В вашем случае вы бы нашли какой-нибудь сериализатор (я думаю, у WCF есть такой), который сериализует в RSS.

Ответ №5:

Я получил это от Эрана Кампфа и видео Скотта Хансельмана (забыл ссылку), так что оно лишь немного отличается от некоторых других постов здесь, но, надеюсь, полезно и готово для копирования и вставки в качестве примера rss-канала.

Из моего блога

Eran Kampf

 using System;
using System.Collections.Generic;
using System.ServiceModel.Syndication;
using System.Web;
using System.Web.Mvc;
using System.Xml;

namespace MVC3JavaScript_3_2012.Rss
{
    public class RssFeed : FileResult
    {
        private Uri _currentUrl;
        private readonly string _title;
        private readonly string _description;
        private readonly List<SyndicationItem> _items;

        public RssFeed(string contentType, string title, string description, List<SyndicationItem> items)
            : base(contentType)
        {
            _title = title;
            _description = description;
            _items = items;
        }

        protected override void WriteFile(HttpResponseBase response)
        {
            var feed = new SyndicationFeed(title: this._title, description: _description, feedAlternateLink: _currentUrl,
                                           items: this._items);
            var formatter = new Rss20FeedFormatter(feed);
            using (var writer = XmlWriter.Create(response.Output))
            {
                formatter.WriteTo(writer);
            }
        }

        public override void ExecuteResult(ControllerContext context)
        {
            _currentUrl = context.RequestContext.HttpContext.Request.Url;
            base.ExecuteResult(context);
        }
    }
}
  

И код контроллера….

     [HttpGet]
public ActionResult RssFeed()
{
    var items = new List<SyndicationItem>();
    for (int i = 0; i < 20; i  )
    {
        var item = new SyndicationItem()
        {
            Id = Guid.NewGuid().ToString(),
            Title = SyndicationContent.CreatePlaintextContent(String.Format("My Title {0}", Guid.NewGuid())),
            Content = SyndicationContent.CreateHtmlContent("Content The stuff."),
            PublishDate = DateTime.Now
        };
        item.Links.Add(SyndicationLink.CreateAlternateLink(new Uri("http://www.google.com")));//Nothing alternate about it. It is the MAIN link for the item.
        items.Add(item);
    }

    return new RssFeed(title: "Greatness",
                       items: items,
                       contentType: "application/rss xml",
                       description: String.Format("Sooper Dooper {0}", Guid.NewGuid()));

}