Fuentes RSS en ASP.NET MVC

113

¿Cómo recomendaría manejar las fuentes RSS en ASP.NET MVC? ¿Utilizas una biblioteca de terceros? ¿Estás usando el material RSS en la BCL? ¿Solo está creando una vista RSS que muestre el XML? ¿O algo completamente diferente?

Lance Fisher
fuente
Con RssToolkit, solo necesita tener un solo archivo .ashx en su proyecto para generar un feed RSS. Luego, puede volver a escribir su URL en una amigable. Creo que no hay nada en contra de MVC en este enfoque.
Mahdi Taghizadeh
Aquí hay una publicación de seguimiento que lleva la idea de RssActionResult un poco más allá con una clase de resultado SyndicationAction generalizada, así como un filtro de obtención condicional 304 NotModified. 58bits.com/blog/…
Blue Waters
Escribí un RssResult que puede ver si lo desea. Debe cumplir con sus requisitos http://www.wduffy.co.uk/blog/rssresult-aspnet-mvc-rss-actionresult/
WDuffy
1
Solo para actualizar esta pregunta a los 18 meses después de la última edición: parecía razonable preguntar '¿han cambiado las cosas con iteraciones tanto en .net como en mvc que cambiarían la forma en que abordamos el problema de la gestión de alimentos? El consenso (a través de un hilo SO diferente) es que, 'Sin cambios fundamentales, este sigue siendo su mejor conjunto de alternativas'.
justSteve
mala sugerencia para ASP.NET MVC.
tugberk

Respuestas:

64

Esto es lo que recomiendo:

  1. Cree una clase llamada RssResult que herede de la clase base abstracta ActionResult.
  2. Anule el método ExecuteResult.
  3. ExecuteResult tiene el ControllerContext pasado por la persona que llama y con esto puede obtener los datos y el tipo de contenido.
  4. Una vez que cambie el tipo de contenido a rss, querrá serializar los datos a RSS (usando su propio código u otra biblioteca) y escribir en la respuesta.

  5. Cree una acción en un controlador que desee devolver rss y establezca el tipo de retorno como RssResult. Toma los datos de tu modelo en función de lo que quieras devolver.

  6. Entonces, cualquier solicitud a esta acción recibirá rss de los datos que elija.

Esa es probablemente la forma más rápida y reutilizable de devolver rss tiene una respuesta a una solicitud en ASP.NET MVC.

Dale Ragan
fuente
10
Hanselman tiene una solución similar (video: comienza alrededor de 41 m) donde hereda de FileResult. Al hacerlo, puede hacer que el constructor de su clase llame base("application/rss+xml")y evitar los pasos 3 y 4. Él anula ExecuteResult, pero no es vital. También atajos de una gran cantidad de código típicamente de andar por casa y utiliza las características de 3.5 + SyndicateItem, SyndicateFeedy Rss20FeedFormatter.
patridge
@Dale: ¿es posible escribir en la respuesta cuando desea enviar una salida a una vista parcial? Gracias.
Christian
1
Enlace actualizado del video de Hanselman de mi comentario anterior.
patridge
150

El marco .NET expone clases que manejan la sincronización: SyndicationFeed, etc. Entonces, en lugar de hacer el renderizado usted mismo o usar alguna otra biblioteca RSS sugerida, ¿por qué no dejar que el marco se encargue de ello?

Básicamente, solo necesita el siguiente ActionResult personalizado y está listo para comenzar:

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

Ahora, en la acción de su controlador, puede devolver lo siguiente:

return new RssActionResult() { Feed = myFeedInstance };

Hay una muestra completa en mi blog en http://www.developerzen.com/2009/01/11/aspnet-mvc-rss-feed-action-result/

Eran Kampf
fuente
34

Estoy de acuerdo con Haacked. Actualmente estoy implementando mi sitio / blog utilizando el marco MVC y seguí el enfoque simple de crear una nueva Vista para 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>

Para obtener más información, consulte (enchufe descarado) http://rickyrosario.com/blog/creating-an-rss-feed-in-asp-net-mvc

Ricky
fuente
4
para uso de Razor: @model PageModel @ {Response.ContentType = "application / rss + xml"; } <? xml version = "1.0" encoding = "UTF-8"?>
Anthony Johnston
2
¿Qué sobrecarga? ¿Te refieres al hecho de que estás escribiendo menos código para lograr lo mismo de una manera más legible?
Paul
12

Otro enfoque loco, pero tiene su ventaja, es usar una vista .aspx normal para renderizar el RSS. En su método de acción, simplemente configure el tipo de contenido apropiado. El único beneficio de este enfoque es que es fácil comprender qué se está renderizando y cómo agregar elementos personalizados, como la geolocalización.

Por otra parte, los otros enfoques enumerados podrían ser mejores, simplemente no los he usado. ;)

Pirateado
fuente
3
@Haacked: El mundo está lleno de XML RSS no válido generado por un sistema de plantillas. ¡Por favor no agregue al lío! Ricky, codificación HTML = codificación XML.
Brad Wilson
A continuación se muestra la documentación de Html Encode de MSDN:> Debido a los detalles de implementación actuales, esta función se puede utilizar como una función xmlEncode. Actualmente, todas las entidades con nombre utilizadas por esta función también son entidades con nombre predefinidas xml. Están <> "& codificadas como & lt; & gt; & quot; y & amp ;. Otras entidades están codificadas en decimal como & # 160 ;. http://msdn.microsoft.com/en-us/library/73z22y6h.aspx
Ricky
¿Cómo puede asegurarse de que el XML sea válido de esta manera? Sería bueno si la representación de la vista se desacoplara de una solicitud web entrante, para hacer posibles las vistas XML o las plantillas de correo electrónico como done ruby ​​on rails.
Paco
En lugar de utilizar un motor de visualización, puede crear un RssResult que se derive de ActionResult. Hacemos esto con JsonResult que serializa el objeto en JSON. En su caso, encontrará algún serializador (creo que WCF tiene uno) que serializa a RSS.
Pirateado el
8

Obtuve esto de Eran Kampf y un video de Scott Hanselman (olvidé el enlace), por lo que es solo un poco diferente de algunas otras publicaciones aquí, pero con suerte es útil y está listo para copiar y pegar como un ejemplo de feed rss.

De mi blog

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

Y el código del controlador ...

    [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()));

}
TheDev6
fuente