I have a partial view (ascx) for displaying the top x articles of a person’s RSS feed:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Models.Article>>" %>
<% foreach (var item in Model) { %>
<a href="<%: item.Url %>"><%: item.Title %></a><br />
<%: String.Format("{0:g}", item.Date) %><br />
<%: item.Body %>
<br />
<% } %>
In addition, I have a method that takes an RSS URL and returns an IEnumerable of type Article:
public static class ArticleFeedHelper
{
public static IEnumerable<Models.Article> GetArticles(string feedUrl)
{
// Uncaught exception can happen here (e.g. 404, malformed RSS, etc.)
}
}
On one of my views, I call the partial view like this:
<div id="articleList" class="section">
<div class="sectionTitle">My Recent Articles</div>
<hr />
<div class="sectionBody">
<% Html.RenderPartial("ArticleList", ArticleFeedHelper.GetArticles(Model.RSSFeed)); %>
</div>
</div>
The problem is that I would like to surface an error message to the main view. Just because the RSS feed cannot be retrieved should not be so disruptive that it jettisons the user to a full error page.
RESOLUTION:
The partial view, and ArticleFeedHelper stayed the same.
Using Dave’s suggestions, the main view was changed to:
<div id="articleList" class="section">
<div class="sectionTitle">My Recent Articles</div>
<hr />
<div class="sectionBody">
<% Html.RenderAction("ArticleList", "ArticleList", new { feedUrl = Model.RSSFeed }); %>
</div>
</div>
A partial controller was added:
public class ArticleListController : Controller
{
public ActionResult Index()
{
return View();
}
[ChildActionOnly]
public ActionResult ArticleList(string feedUrl)
{
try
{
IEnumerable<Models.Article> articles = Helpers.ArticleFeedHelper.GetArticles(feedUrl);
return PartialView(articles);
}
catch (Exception ex)
{
// Handle the error and return an error partial view
}
}
}
And a route was added:
routes.MapRoute(
"ArticleList", // Route name
"{controller}/{action}/{feedUrl}", // URL with parameters
new { controller = "ArticleList", action = "ArticleList", feedUrl = "" } // Parameter defaults
);
The cleaner way would be to use
RenderActionthat calls an action, which loads the feed data and can then catch errors.RssWidget action on ServicesController (could actually reside in every controller, doesn’t matter, but I think, that’s a clean solution):
This action loads the articles from the feed. Note that the code is only demo and you have to replace
RssService.GetArticles()by your implementation of loading the articles. If all goes right, a PartialView (named RssWidget.ascx) is returned, that shows a list of articles.RssWidget.ascx: This is the (partial) view which is used to render the list of articles. Don’t forget to replace
Articlewith your actual Type for the articles:The View where the RssWidget is displayed. You can render this “widget” in any view, you want to.
RenderAction("RssWidget", "Services")tells the framework to execute the RssWidget action on the ServicesController and to insert the result in the actual view.