7 modi di fare rendering in ASP.NET MVC3

datedomenica 4 dicembre 2011 alle 15.58  - posted by Manuel Scapolan in ASP.NET

Il pattern MVC ci dice che il controller deve preparare i dati del modello e scegliere la vista da visualizzare e che la vista ha il solo compito di formattare i dati. Nella realtà però le informazioni da visualizzare hanno diversa granularità e contesto e non sempre la linearità del metodo classico risolve tutti i casi. Vediamo allora quali possibilità ci vengono offerte dal framework ASP.NET MVC per quanto riguarda il rendering dei dati sulla vista:

1. Strongly Typed Views

Cominciamo dal modo classico.

public ActionResult Index()
{
   var cart = ShoppingCart.GetCart(this.HttpContext);

   var viewModel = new ShoppingCartViewModel
   {
     CartItems = cart.GetCartItems(),
     CartTotal = cart.GetTotal()
   };

   // Return the view
   return View(viewModel);
}

Il controller prepara il model (3-9) e lo passa direttamente alla vista (12).

mvc strongly typed view

Nella vista definisco il tipo di modello (in razor con @model) e l'IntelliSense fa il resto.

Quando usare viste tipizzate?

Sempre e il più possibile, magari valutando l'abbinamento con il pattern ViewModel.

2. Codice in-line

Posso scrivere codice C# direttamente nelle viste per organizzare il markup in base al modello.

@foreach (var item in Model.CartItems)
{
  <tr id="row-@item.RecordId">
    <td>
      @Html.ActionLink(item.Album.Title, 
                 "Details", "Store", new { id = item.AlbumId }, null)
    </td>
    <td>@item.Album.Price</td>
    <td id="item-count-@item.RecordId">@item.Count</td>
    <td>
      <a href="#" data-id="@item.RecordId">Remove from cart</a>
    </td>
   </tr>
}

Quando usare codice in-line?

Portare la logica nelle viste va contro la separation of concerns tipica di MVC e renderà il codice non testabile. Se il codice da scrivere va oltre un semplice foreach è consigliato metterlo sul controller, oppure gestirlo con un Html Helper o in una RenderAction.

3. Html Helper Methods

Scrivere codice html alle volte può risultare ripetitivo, ecco perché il framework ci mette a disposizione degli Extension Methods che nascondono la scrittura dei più comuni tag html.

<div class="editor-label">
     @Html.Label("Promo Code")
</div>
<div class="editor-field">
     @Html.TextBox("PromoCode")
</div>

L'output è il seguente:

<div class="editor-label">
    <label for="Promo_Code">Promo Code</label>
</div>
<div class="editor-field">
    <input id="PromoCode" name="PromoCode" type="text" value="" />
</div>

Quando usare gli Html Helper Methods?

Devo confessare che a me scrivere codice html piace, non userei quindi gli helper per banalità quali label o textbox perché peggiorano la leggibilità del codice. Trovo molto utili invece quelli che derivano da HtmlHelper<TModel> ovvero gli helper fortemente tipizzati. Ad esempio:

<div class="editor-field">
  @Html.EditorFor(model => model.AlbumArtUrl)
  @Html.ValidationMessageFor(model => model.AlbumArtUrl)
</div>

4. Html.Partial() e Html.RenderPartial()

Vi ricordate gli User Control del paradigma WebForm? Esistono anche in MVC e si chiamano PartialView. Le viste parziali sono praticamente delle viste senza master page, per richiamarle possiamo usare due helper: Html.Partial() e Html.RenderPartial(). La differenza? Partial ritorna una stringa, mentre RenderPartial scrive direttamente nella Response.

Quando usare le Partial View?

Le partial view vengono utilizzate per condividere del codice tra più viste, ad esempio un menu di navigazione, il footer oppure l'header. Possono contenere codice in-line, chiamate ad altri helper, ma non hanno logica di business. Per questi motivi i dati vengono passati attraverso il Model oppure tramite ViewData/ViewBag dell'action chiamante. Se vogliamo utilizzarle per i classici cross-cutting concern dobbiamo inserire la logica in un base controller, in un filtro oppure nel ViewData di ogni chiamante.

5. Html.Action() e Html.RenderAction()

Vogliamo avere una partial view con della logica applicativa? Possiamo richiamare all'interno della vista una action di un controller attraverso l'helper RenderAction. Ogni volta che chiamiamo questo metodo viene generata una richiesta che attraversa tutta la pipeline di MVC e renderizza il codice della vista direttamente nella Response. Utilizzi tipici di questa tecnica sono i widget. Ad esempio:

@{Html.RenderAction("CartSummary", "ShoppingCart");}
[ChildActionOnly]
public ActionResult CartSummary()
{
    var cart = ShoppingCart.GetCart(this.HttpContext);
    ViewData["CartCount"] = cart.GetCount();

    return PartialView("CartSummary");
}

Quando utilizzare Html.RenderAction()?

La scelta tra mettere tutto in una action e fare un'altra richiesta dipende dalla volontà di mantenere separata la logica tra le chiamate. Se parliamo in termini di riutilizzo del codice o di cross-cutting concern è opportuno intraprendere prima altre strade come un base controller oppure un global filter.

6. Custom Html Helper Methods

Oltre agli helper contenuti nel framework possiamo definirne di personalizzati semplicemente sfruttando la tecnica degli Extension Methods, un esempio:

public static class HtmlHelpers
{
   public static string Truncate(this HtmlHelper helper, 
                                 string input, 
                                 int length)
   {
      if (input.Length <= length)
      {
         return input;
      }
      else
      {
         return input.Substring(0, length) + "...";
      }
   }
}
<td>@Html.Truncate(item.Title, 25) </td>

Quando utilizzare un helper personalizzato?

Potenzialmente qualsiasi metodo che ritorna una stringa può essere trasformato in un helper. E' buona regola comunque pensare ad un helper come ad un pattern ovvero alla soluzione di un problema ricorrente.

7. Razor Template

Cito testualmente dal post di Scott Guthrie: "One other useful (and extremely powerful) feature we are enabling with Razor is the ability to pass “inline template” parameters to helper methods. These “inline templates” can contain both HTML and code, and can be invoked on-demand by helper methods". Ecco un esempio e qui sotto un altro:

@using System.Text;
@functions {
  public static IHtmlString Repeat(int n, Func<int, object> template) {
        StringBuilder builder = new StringBuilder();
        for(int i = 0; i < n; i++) {
            builder.Append(template(i));
        }
        return new HtmlString(builder.ToString());
  }
}
<!DOCTYPE html>
<html>
    <head>
        <title>Repeat Helper Demo</title>
    </head>
    <body>
        <p>Repeat Helper</p>
        <ul>
            @Repeat(10, @<li>List Item #@item</li>);
        </ul>
    </body>
</html>

Quando e perché utilizzare un razor template?

Non l'ho ancora capito...


Resources:
- MvcMusicStore di Jon Galloway
- Inside Razor - Part 3 - Templates (Andrew Nurse)

tagsTags: ,

Commenti chiusi

About me

manuel scapolanSono un consulente informatico. Nel 2004 terminati gli studi in Ingegneria Informatica (1° livello), ho iniziato come freelance collaborando con una ditta di consulenza informatica ed una agenzia di marketing e comunicazione nello sviluppo di applicazioni web. Attualmente divido il lavoro di sviluppatore e progettista web con attività di formazione nel settore della programmazione.
View Manuel Scapolan's profile on LinkedIn

Follow me on Follow manuelscapolan on Twitter
Member of:
innova

Calendario


<<  febbraio 2012  >>
lumamegivesado
303112345
6789101112
13141516171819
20212223242526
2728291234
567891011

Disclaimer

Eccetto dove diversamente specificato, i contenuti di questo sito sono rilasciati mediante:
creative commons
Attribuzione: Non commerciale
Condividi allo stesso modo. R.2.5

Books (a bit more about my library)

Domain Driven Design - Eric Evans Applying Domain-Driven Design and Patterns - Jimmy Nilsson Refactoring to Patterns - Joshua Kerievsky Design Patterns -  Erich Gamma, Richard Helm, Ralph Johnson, John M. Vlissides Code Complete Second Edition - Steve McConnell Patterns of Enterprise Application Architecture - Martin Fowler Agile Principles, Patterns, and Practices in C# - Robert C. Martin xUnit Test Patterns - Gerard Meszaros Refactoring - Martin Fowler CLR via C# Second Edition - Jeffrey Richter Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries - Krzysztof Cwalina, Brad Abrams Don't make me think! - Steve Krug Bulletproof Ajax - Jeremy Keith

Manuel Scapolan Copyright © 2007 - 2010 - Tutti i diritti riservati - Powered by BlogEngine.NET 1.5.0.7 - silk icons by famfamfam - Time CET