Thomas Bandt

Über mich | Kontakt | Archiv

ASP.NET MVC - Separation of Concerns with Html.RenderAction();

Think about the following two (common) scenarios within an ASP.NET MVC application:

  1. You have an user control which displays - for example - an ad. To define which ad will be displayed some logic is necessary. You want to use this control on different places within your site, one time placed in your MasterPage, one time in a View.
  2. You have a portal page where each of your users can select some "portal objects" (calendar, news or whatever else). These "portal objects" will only be rendered when selected by the user. Each of this object has its only logic.

Both scenarios vary from the common way how ASP.NET MVC works. Because each of this controls will need its own model and own logic behind, you can't filfill that with handling it in the current action method of your actual controller. Each of this controls needs its own "place for business logic".

With ASP.NET WebForms the solution would propably be to put that logic in the code behind. This is also possible with ASP.NET MVC (remember, the ASP.NET life cycle is still valid), but it would break the rules.

So what should we do?

The solution is very simple but not delivered by Microsoft within the official bits. There exists a project called "ASP.NET MVC Futures" which offers a HTML helper called Html.RenderAction(). This extension offers you the complete flexibility and plays the MVC game at the same time.

How does it work?

As well as your "normal" controllers and views! Just create a method in a controller of type ActionResult and call it via Html.RenderAction(). That's it.

Sample

Controller:

   1:  [Authorize]
   2:  public class PortalController : Controller
   3:  {
   4:      public ActionResult Portlet_3_ProfileVisitors()
   5:      {
   6:          return View("~/Views/Portal/Portlets/3_ProfileVisitors.ascx", 
   7:          UserService.GetLatestProfileVisitors(CurrentUser.ID, 4));
   8:      }
   9:  }

Control:

   1:  <%@ Control Language="C#" AutoEventWireup="true" 
   2:  Inherits="System.Web.Mvc.ViewUserControl<List<Guid>>" %>
   3:  <% if (Model != null && Model.Count > 0) { %>
   4:  <table border="0" cellpadding="0" cellspacing="0">    
   5:  <% Html.Repeater(Model, "", "", (visitorID, item) => { %>
   6:      <tr>
   7:          <td>Besucher-ID: <%= visitorID%></td>
   8:      </tr>
   9:  <% }); %>
  10:  </table>
  11:  <% } else { %>
  12:  Dein Profil wurde noch nicht aufgerufen
  13:  <% } %>

Call:

   1:  <% Html.RenderAction("Portlet_3_ProfileVisitors", "Portal"); %>

Summary

This feature is so useful - I don't know why it hasn't made its way into the System.Web.Mvc assembly. But I'm sure, it will. So, go and use it :-).

Kommentare

  1. Dean schrieb am Donnerstag, 5. Februar 2009 09:57:00 Uhr:

    Hi there,

    I am starting with ASP.NET MVC and I am having some trouble seeing the difference between this approach and by using Html.RenderPartial. Wouldn't partials achieve the same result?
  2. Thomas schrieb am Donnerstag, 5. Februar 2009 10:12:00 Uhr:

    Hi,

    no, they wouldn't. Because Controls rendered with Html.RenderPartial() are rendered in the context of the current action.

    Example:

    If your view awaites a model of type Car and your control does this, too, for example for displaying a search mask, then you can take Html.RenderPartial().

    But if your Control awaits a model of type Train, you can't handle that within one action.

    Ok? :)
  3. Dean schrieb am Donnerstag, 5. Februar 2009 10:21:00 Uhr:

    Now I got it. Thanks a lot.
  4. Wookie schrieb am Donnerstag, 5. Februar 2009 19:14:00 Uhr:

    Doesn't this thing break the SoC in MVC? To have your view actively calling your controller instead of the other way around?
  5. Thomas schrieb am Donnerstag, 5. Februar 2009 21:48:00 Uhr:

    Hm ... maybe. On the other side: actually it doesn't matter from where the request to the controller comes as long as the path is then controller -> view.

    But it's also a question of pragmatism - you will come to the point where you need and independent control which is usable wherever you need it on the page and which is independent from the view in which it is rendered. I don't see a better solution for that case at the moment.
  6. Minhajuddin schrieb am Freitag, 6. Februar 2009 20:00:00 Uhr:

    Nice blog post.


« Zurück  |  Weiter »