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: ,

Utilizzare Memcached con ASP.NET

datevenerdì 2 dicembre 2011 alle 14.43  - posted by Manuel Scapolan in ASP.NET | NoSQL

Vediamo come in 5 minuti possiamo configurare Memcached per la nostra applicazione ASP.NET.

Passo 1 - Installazione di Membase Server

Invece di installare Memcached come prodotto "stand-alone" ho deciso di utilizzare Membase Server un "key-value database management system" che tra l'altro permette di gestire Memcached attraverso una comoda console web. Per installare Membase Server dobbiamo scaricare il pacchetto di installazione specifico per il nostro sistema operativo, nel mio caso Windows.

membase

Passo 2 - Configurazione del server

Una volta completata l'installazione ci viene proposto un wizard per la configurazione del server.

membase web console

Nel primo step definiamo la destinazione su disco dello storage e quanta RAM dedicare alla cache.

membase configuration wizard

OK, ma Memcached non era un database in memoria, perché allora ci chiede spazio su disco?
Sì memcached salva i dati in memoria, ma il server di Membase permette anche di scegliere come database una versione nativa che aggiunge a memcached caratteristiche di persistenza e replica.

Il secondo step consiste appunto nella scelta del tipo di storage (in Membase viene definito Bucket) e noi scegliamo Memcached.

membase configuration wizard

Gli ultimi due step consentono di configurare le notifiche sugli aggiornamenti del software e le credenziali di accesso alla console.

Passo 3 - Se siamo in DHCP

Se siamo in DHCP e vogliamo utilizzare Membase in locale dobbiamo andare nella cartella Server/bin sotto l'installazione di Membase e lanciare da prompt (come amministratore) i seguenti comandi:

> service_stop.bat
> service_unregister.bat
> service_register.bat ns_1@127.0.0.1
> service_start.bat

A questo punto dovremmo avere Membase configurato in locale.

Passo 4 - Scaricare le librerie client

Per poter utilizzare Memcached dalla nostra applicazione dobbiamo ora installare le librerie client Enyim Memcached versione 2.11 e Membase versione 2.14, invece di scaricarle da internet possiamo utilizzare il Package Manager di NuGet.


librerie client da nuget

Passo 5 - Configurare l'applicazione web

Nel web.config dobbiamo aggiungere la seguente configurazione:

<configuration>
  <configSections>
    <section name="membase" 
           type="Membase.Configuration.MembaseClientSection, Membase"/>
  </configSections>
  
  <membase>
    <servers bucket="default" bucketPassword="">
      <add uri="http://127.0.0.1:8091/pools/default"/>
    </servers>
  </membase>

  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup> 

Passo 6 - Hello Memcached

A questo punto non ci resta che instanziare il client e salvare il nostro primo valore in Memcached.

using Enyim.Caching.Memcached;
using Membase;
...
public ActionResult Index()
{
   using (var client = new MembaseClient())
   {
      client.Store(StoreMode.Set, "hello", "

Hello Memcached

"); var msg = client.Get<string>("hello"); ViewBag.Message = msg; } return View(); }

Attenzione! La creazione del client è molto dispendiosa, è opportuno quindi instanziarlo una volta sola magari alla partenza dell'applicazione.

Dalla console di Membase possiamo monitorare l'attività del server e scegliere se necessario di aggiungere a caldo altri server al cluster.


librerie client da nuget

A questo punto siamo liberi di utilizzare Memcached per velocizzare la nostra applicazione ASP.NET ed alleggerire il carico sul nostro caro e vecchio database relazionale!


Fonte: Getting Started with Membase and C#

NoSQL & ASP.NET just married!

datedomenica 27 novembre 2011 alle 10.39  - posted by Manuel Scapolan in ASP.NET | NoSQL

Il vecchio schema a tre livelli non esiste più. Il database relazionale non riesce più a soddisfare le richieste di applicazioni sempre più esigenti in termini di performance e ricchezza del dato.
Ad oggi le applicazioni enterprise utilizzano tre classi di database, al database relazionale per l'OLTP si è aggiunto il data warehouse per operazioni di analisi del dato e reportistica.
A mettere in discussione la supremazia del database relazionale nel campo dei dati "appena sfornati" ci ha pensato il movimento NoSQL, che propone un modo diverso di memorizzare e consumare i dati applicativi.


nosql
fonte: http://geekandpoke.typepad.com/geekandpoke/2011/01/nosql.html

Perché NoSQL: un caso pratico

Le interrogazioni che prevedono dati presi da più tabelle sono le operazioni nelle quali il relazionale viene messo a dura prova, indici, viste e denormalizzazioni varie sono rimedi poco efficaci se la nostra applicazione effettua un numero elevato di richieste. In questo caso viene spontaneo pensare ad un sistema di cache e in questo campo il migliore è memcached.

Nel prossimo post vedremo come configurare memcached per velocizzare sensibilmente le nostre applicazioni ASP.NET.

continua...

tagsTags: ,

Utilizzare dotless con Visual Studio 2010

datevenerdì 28 ottobre 2011 alle 19.12  - posted by Manuel Scapolan in Tips and Tricks

Dotless è il porting di Less un linguaggio dinamico che estende le funzionalità dei css aggiungendo variabili, spazi dei nomi, funzioni, etc. Possiamo creare stili annidati, riutilizzare caratteristiche comuni, definire i colori del nostro sito in un solo punto. Sarà un "compilatore" a generare per noi il css da inviare al browser.

dotless

La generazione dei css può avvenire sia lato client (tramite una libreria javascript), sia lato server tramite un compilatore oppure da C# tramite un'API, ma vediamo come utilizzare dotless con Visual Studio.

Passo 1 - Installare dotless

Per installare dotless dovete lanciare dalla Package Manager Console di Visual Studio 2010 il comando Install-Package dotless. Al termine dell'operazione avrete nella cartella packages della solution tutto quello che serve per cominciare.

Passo 2 - Creare un file .less

Aggiungete al progetto un nuovo file di tipo testo e rinominatelo con estensione .less, per agevolarvi nella compilazione della sintassi potete installare l'add-in LessExtension che potete trovare tramite NuGet. Scrivete qualche riga di codice in "linguaggio" less, magari copiandola dal sito.

Passo 3 - Scrivere un file batch che compili i file .less

Il listato sottostante permette di chiamare il compilatore dotless passando come argomenti la cartella dove trovare i file .less e la destinazione dei file css compilati. Se i file css risultassero vuoti saranno cancellati dall'ultima istruzione (utile se definite un file .less contenente solo variabili).

for /f %%F in ('dir /b %2\*.less') do (
 call %1dotless.compiler.exe -m "%~2%%F" "%~3%%~nF.css"
)

cd %~3
for /F "delims=" %%I in ('dir /B *.css') do (
  if not exist "%%I\" if %%~zI EQU 0 del "%%I"
)

Passo 4 - Lanciare il batch in PreBuild

Per fare in modo che i file css siano generati prima dell'esecuzione del sito è necessario chiamare il file batch nell'evento Pre-Build del progetto. Andate quindi nella sezione "Build Events" delle proprietà del progetto e copiate il listato seguente nel campo Pre-build event command line.

call "$(ProjectDir)less2css.bat" 
            "$(SolutionDir)packages\dotless.1.2.1.0\tool\" 
            "$(ProjectDir)content\css\less\" 
            "$(ProjectDir)content\css\"

Gli argomenti passati sono il percorso dove trovare il compilatore, la cartella dei file .less e la cartella di destinazione dei file css.

Conclusioni

Ci sono altri modi di utilizzare less, se utilizzate less.js come compilatore potete addirittura definire le proprietà degli stili richiamando funzioni javascript. Al momento ho preferito sfruttare less solo lato server per mantenere il client più leggero ed avere maggior controllo sui css generati.

 

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