tags:

views:

63

answers:

3

This seemed easier in Web Forms; I'd have a user control, with the logic in the code-behind, and I could just drop it on a page.

But apparently code-behinds are a no-no in MVC, and the logic is in controllers. I'm a little confused about how logic for a user control is "wired up".

I want to display an RSS Feed user control. So I have a page:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Home Page
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <p>
        <% Html.RenderPartial("RssFeed"); %>
    </p>
</asp:Content>

I have my user control:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewPage<SyndicationFeed>" %>
<%@ Import Namespace="System.ServiceModel.Syndication" %>

<p>
    <%: ViewData.Model.Title.Text %>
</p>

<div>
    <% foreach (var item in ViewData.Model.Items)
    {
       string url = item.Links[0].Uri.OriginalString;
    %>
    <p><a href='<%= url %>'><b><%= item.Title.Text %></b></a></p>

    <% } %>
</div>

And I have this code that I need to run to get the rss data:

using (XmlReader reader = XmlReader.Create(ConfigurationManager.AppSettings["RssFeed"]))
{
    SyndicationFeed rssData = SyndicationFeed.Load(reader);

    return View(rssData);
}

But where does it go? In the controller for the page that contains the control?

+1  A: 

Based on my understanding.... Yes, it can go in the controller in the page that contains the control. The partial can use the parent's ViewModel

See here (the bit on Partial Views)

http://msdn.microsoft.com/en-us/library/dd410123.aspx

EDIT To include your RSS feed If my controller were named RssController and it had a ViewResult method named RssFeed, I'd include the following on the .Master. <% Html.RenderAction("RssFeed","Rss"); %>

This causes the RssController to get invoked and return the view for your partial (assuming that's what View(rssData) sent back.

Jim Leonardo
What if I want the control in the Master Page? There's not really a controller for the master page, where would it go then?
Steven
Ah... I thought your samples looked a little weird. Lemme poke around a bit.
Jim Leonardo
That's right, I too generally create a specific controller for it like RssController or a controller that contains all the actions that don't go anywhere else like ServiceController. I generally avoid usign RenderPartial with controls that require some data - i.e. I normally don't use the second override of RenderPartial() which accepts a model and rather use RenderAction() to prepare the data for the control and then return PartialView(model).
mare
+1  A: 

In ASP.NET MVC 2+, you can use Html.RenderAction to render an action's result inline.

Giving the action a [ChildActionOnly] attribute will prevent users from navigating to the action normally, making it usable only in this kind of "child" context.

Chris W.
This is the way to go in use cases that you described.
mare
+1  A: 

To sum it up, this is how you can do it

[HttpGet, ChildActionOnly]
// put this in RssController
public ActionResult RssFeed()
{
    // prepare the model
    SyndicationFeed rssData;
    using (XmlReader reader = XmlReader.Create(ConfigurationManager.AppSettings["RssFeed"])) 
    {
        rssData = SyndicationFeed.Load(reader);
    }

    return PartialView(rssData);
}

Usage:

<% Html.RenderAction("RssFeed", "Rss"); %>

And put a check into your ASCX if the Model you are sending in is null and if so, skip everything so it won't render anything. If you leave it like you have it now, it will end in an exception if the Model sent in is null.

mare
So I'm getting a compilation error: Cannot convert type 'ASP.views_shared_rssfeed_ascx' to 'System.Web.Mvc.ViewUserControl'. What's the story here?
Steven
Nevermind, found the answer here: http://stackoverflow.com/questions/1028047/asp-net-mvc-custom-type-list-in-partial-view
Steven