Model binding asincrono con ASP.NET WebForms 4.6

di Moreno Gentili, in ASP.NET 4.5,

Con il rilascio ufficiale del .NET Framework 4.6 avvenuto lo scorso luglio, Microsoft introduce alcuni miglioramenti che interessano anche le applicazioni ASP.NET WebForms.
Si tratta di un aggiornamento in-place della precedente versione 4.5.2, che può essere scaricato dai canali ufficiali http://aspit.co/a6g ed installato su sistemi operativi Windows Server 2008 SP2 (o superiore) e, per il desktop, da Windows Vista SP2.
Nel caso in cui non abbiate ancora effettuato l'aggiornamento a Visual Studio 2015, potrete comunque beneficiare di queste nuove funzionalità da Visual Studio 2012 o 2013 scaricando l'apposito Targeting Pack http://aspit.co/a6h ed impostando il .NET Framework 4.6 come framework di destinazione del vostro progetto.

Il miglioramento di cui parleremo oggi è il supporto al model binding asincrono.
Il model binding è una funzionalità nata con ASP.NET MVC, reinterpretata successivamente per ASP.NET WebForms che permette ad un databound control come la GridView di scambiare dati con i nostri metodi di business, anziché con sorgenti come il SqlDataSource.
Marco De Sanctis ne ha già fornito un esempio in un suo precedente script:
http://aspit.co/aju

Con il .NET Framework 4.6, il model binding per ASP.NET WebForms diventa ancor più efficiente perché in grado di sfruttare metodi asincroni per l'ottenimento e l'aggiornamento dei dati, a tutto vantaggio delle prestazioni della nostra applicazione web, soprattutto in condizioni di carico elevato.

Iniziamo aggiungendo l'attributo Async="true" alla direttiva @Page, che ci abiliterà all'uso dei metodi asincroni.

<%@ Page Async="true" %>

Nel markup della WebForm, aggiungiamo una GridView che useremo per visualizzare e gestire gli elementi esistenti. Inoltre, aggiungiamo un DetailsView per inserirne di nuovi.

<!-- GridView per visualizzare, modificare ed eliminare prodotti esistenti -->
<h2>Lista prodotti</h2>
<asp:GridView ID="ProductsList" ItemType="Model.Product" DataKeyNames="ProductId" runat="server"
    AutoGenerateColumns="false" AutoGenerateEditButton="true" AutoGenerateDeleteButton="true"
    SelectMethod="ReadProducts"
    UpdateMethod="UpdateProduct"
    DeleteMethod="DeleteProduct">
    <Columns>
        <asp:BoundField HeaderText="Id" DataField="ProductId" ReadOnly="true" />
        <asp:BoundField HeaderText="Descrizione" DataField="Description" />
        <asp:BoundField HeaderText="Prezzo in euro" DataField="PriceInEuro" />
    </Columns>
</asp:GridView>

<!-- DetailsView per creare nuovi prodotti -->
<h2>Nuovo prodotto</h2>
<asp:DetailsView ItemType="Model.Product" DataKeyNames="ProductId" runat="server"
    DefaultMode="Insert" AutoGenerateRows="false" AutoGenerateInsertButton="true"
    InsertMethod="CreateProduct">
    <Fields>
        <asp:BoundField HeaderText="Descrizione" DataField="Description" />
        <asp:BoundField HeaderText="Prezzo" DataField="PriceInEuro" />
    </Fields>
</asp:DetailsView>

Il punto interessante di questo esempio risiede negli attributi SelectMethod, UpdateMethod, DeleteMethod e CreateMethod che abbiamo valorizzato con i nomi di metodi asincroni che andremo a creare nel codefile della pagina.
Apriamo dunque il file .aspx.cs ed aggiungiamo i seguenti metodi, resi asincroni dalla parola chiave async e dal tipo Task restituito.

public async Task<IEnumerable<Product>> ReadProducts()
{
  using (var context = new MyOnlineStoreContext())
  {
    // Estraggo l'elenco dei prodotti in maniera asincrona
    return await context.Products.ToListAsync();
  }
}

public async Task UpdateProduct(Product product)
{
  if (!ModelState.IsValid) return;
  using (var context = new MyOnlineStoreContext())
  {
    context.Entry(product).State = EntityState.Modified;
    // Aggiorno il prodotto in maniera asincrona
    await context.SaveChangesAsync();
  }
}

public async Task DeleteProduct(Product product)
{
  using (var context = new MyOnlineStoreContext())
  {
    context.Entry(product).State = EntityState.Deleted;
    // Elimino il prodotto in maniera asincrona
    await context.SaveChangesAsync();
  }
}

public async Task CreateProduct(Product product)
{
  if (!ModelState.IsValid) return;
  using (var context = new MyOnlineStoreContext()) {
    context.Entry(product).State = EntityState.Added;
    // Aggiungo il prodotto in maniera asincrona
    await context.SaveChangesAsync();
  }
  //Indico alla GridView che deve riottenere l'elenco dei prodotti
  ProductsList.DataBind();
}

In questo modo, possiamo sfruttare appieno le tecnologie che, a loro volta, espongono API asincrone come Entity Framework 6. Nell'esempio mostrato, la parola chiave await, che viene usata con i metodi ToListAsync e SaveChangesAsync, permette ad IIS di riutilizzare in maniera intelligente i thread di elaborazione delle richieste web, così che non restino bloccati e inutilizzati in attesa che la lettura o la scrittura al database si completi.
Il model binding asincrono diventa ancor più consigliato quando consumiamo risorse soggette ad una latenza di rete consistente, come ad esempio web services o altro tipo di servizi che siano ospitati su macchine remote o nel cloud.

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi