Condividi tramite


Migrazione Web

Migrazione di un'applicazione Web da WebMatrix ad ASP.NET MVC 3

Brandon Satrom

Scarica il codice di esempio

Nel gennaio scorso, Microsoft ha presentato un nuovo modello di programmazione per lo sviluppo Web con Microsoft .NET Framework denominato ASP.NET Web Pages. Attualmente supportato per impostazione predefinita in WebMatrix (web.ms/WebMatrix), Web Pages è un modello di programmazione incentrato sulle pagine che si comporta in modo molto simile al linguaggio PHP, in cui ciascun pagina contiene la propria logica aziendale, il proprio accesso ai dati e il contenuto dinamico per eseguire il rendering del codice HTML nel browser.

Esistono diversi motivi per creare un sito Web in WebMatrix. Tuttavia, se prevedessimo di migrare a Visual Studio in un futuro non troppo lontano? Se la nostra intenzione è di migrare a ASP.NET MVC 3, sarà necessario risviluppare il sito prima della migrazione? Fughiamo ogni timore di affrontare WebMatrix e Web Pages, perché non ne esiste il motivo.

Web Pages, in quanto parte del framework principale di ASP.NET, è stato creato pensando alla flessibilità. Inoltre, benché non esistano limitazioni tecniche in Web Pages che impongano una migrazione ASP.NET MVC, potrebbe presentarsi il momento in cui se ne senta la necessità nel proprio team, per il proprio prodotto o azienda.

In questo articolo, illustreremo alcuni dei motivi per cui scegliere di effettuare la migrazione (nonché alcuni dei motivi per non farla). Illustreremo inoltre le strategie per migrare il sito Web Pages esistente a ASP.NET MVC, se lo si desidera. Spiegheremo come trasformare pagine in viste, come gestire la logica aziendale e il codice helper, nonché come introdurre modelli nell'applicazione. Infine, illustreremo come conservare gli URL del sito esistente tramite il routing e il supporto di reindirizzamenti permanente, qualora necessario.

Quando effettuare la migrazione?

Prima di esaminare i motivi per cui effettuare una migrazione da Web Pages a ASP.NET MVC, analizziamo alcuni dei motivi per non farlo. I principianti non dovrebbero migrare da Web Pages a ASP.NET MVC per timore di incompatibilità applicative. Poiché Web Pages è basato su ASP.NET, offre molte delle stesse caratteristiche di prestazioni delle applicazioni scritte per ASP.NET MVC o Web Form. Ovviamente, ciascun tipo di applicazione dispone di un modello di esecuzione leggermente diverso, ma non esiste alcuna caratteristica integrata di ASP.NET MVC che lo renda essenzialmente più o meno scalabile di un'applicazione Web Pages. La scalabilità e le prestazioni dipendono strettamente dalle decisioni di progettazione prese in fase di creazione del sito così come il framework di base prescelto.

Non è inoltre una buona idea migrare il sito esistente da Web Pages a ASP.NET MVC solo perché va di moda e tutti ne parlano bene o semplicemente perché si desidera lavorare con il sito in Visual Studio; è già possibile anche in Web Pages. ASP.NET MVC rappresenta una scelta nell'architettura delle applicazioni Web, non una bacchetta magica che rende il sito istantaneamente migliore. La migrazione da Web Pages ad ASP.NET MVC è una scelta, non una necessità. Inoltre, benché Microsoft abbia fatto un lavoro fantastico per rendere possibile e indolore la migrazione, comporterà comunque un dispendio di tempo, risorse e denaro come qualsiasi altra migrazione. Alla luce di ciò, è fondamentale assicurarsi che si stia effettuando la migrazione ad ASP.NET MVC per motivi validi.

Un motivo valido potrebbe essere l'importante degli unit test. Poiché il modello Web Pages è incentrato sulle pagine, non è possibile utilizzare gli strumenti esistenti per l'esecuzione di unit test con i siti basati su Web Pages. Il test dell'interfaccia utente Web, mediante strumenti come WatiN o Selenium, è comunque possibile, mentre non è possibile l'esecuzione di unit test a livello di codice con strumenti come NUnit o MSTest. Se il sito è aumentato di complessità e l'esecuzione di unit test sono diventati importanti, la migrazione ad ASP.NET MVC inizia ad avere senso.

Se si preferisce di effettuare unit test del codice, è inoltre possibile che sia necessaria una qualche forma di delimitazione nelle applicazioni. Inoltre, benché sia possibile creare codice pulito, con codice delimitato mediante l'impiego di helper e di file di codice all'interno del modello Web Pages, quest'ultimo non si presta a delimitazioni in modo nativo come ASP.NET MVC. Se la delimitazione dei problemi costituisce un fattore importante e si desidera un'architettura applicativa che promuova tali delimitazioni, la migrazione rappresenta una scelta valida.

Oltre questi ultimi due, altri motivi per effettuare la migrazione potrebbe entrare in gioco a seconda del contesto del sito o dell'organizzazione. Se si dispone di un team in costante crescita e di un sito che sta aumentando di complessa che richiede di funzionalità aziendali più avanzate, la migrazione rappresenta una scelta obbligata. La migrazione può essere inoltre necessaria per sfruttare meglio un ecosistema di sviluppo più avanzato per attività quali il controllo del codice sorgente, il test di carico e così via.

Preparazione per la migrazione

Per questo articolo, utilizzeremo il sito di modelli Raccolta foto incluso con WebMatrix e lo migreremo ad ASP.NET MVC. L'operazione fondamentale del processo di migrazione consiste nel convertire pagine in modelli, controller e viste, ma è necessario effettuare alcune attività di preparazione prima di iniziare.

Poiché stiamo illustrando le fasi di una migrazione manuale in questo breve articolo, non saremo in grado di dedicare lo stesso tempo a ciascuna fase. Il nostro obiettivo consiste nell'illustrare le fasi principali e almeno menzionare menzionare le osservazioni minori. Abbiamo inoltre scelto di omettere gli elementi che non sono correlati alle parti essenziali della conversione stessa, quali le procedure consigliate per l'accesso ai dati, la struttura potenziale degli assembly, l'inserimento delle dipendenze e simili. Questi elementi sono senz'altro importanti, ma molti di essi rientrano nelle preferenze e nel background dello sviluppatore e possono essere considerati durante i refactoring successivi alla migrazione.

È inoltre importante notare che non utilizziamo la funzionalità Open in Visual Studio (Apri in Visual Studio) in WebMatrix per questo articolo, che consente l'apertura del sito esistente come progetto di tipo Sito Web in Visual Studio. Sebbene l'utilizzo di questa opzione sia consentito, anche se si sceglie di non migrare ad ASP.NET MVC, preferiamo utilizzare il tipo di progetto Applicazione Web di Visual Studio per ASP.NET MVC, iniziando con un sito Web vuoto in cui effettuare la migrazione manualmente.

Come tale, inizieremo la migrazione scegliendo File | Nuovo | Progetto, quindi selezionando Applicazione Web ASP.NET MVC 3 con un modello vuoto, utilizzando Razor come motore di visualizzazione predefinito.

Una volta impostata l'applicazione di destinazione, sarà necessario eseguire alcune attività iniziali di migrazione. Di seguito è riportato un resoconto delle fasi iniziali:

  1. Aggiungere tutti i pacchetti utilizzati nel sito Web Pages al sito ASP.NET MVC tramite NuGet (nuget.org).
  2. Aggiungere i riferimenti agli spazi dei nomi System.Web.Helpers, WebMatrix.Data e WebMatrix.WebData. Nel riquadro delle proprietà, impostare ciascuno spazio dei nomi su Copy Local = true.
  3. Spostare il contenuto del file _AppStart.cshtml nel metodo Application_Start del file Global.asax. Benché sia possibile migrare e utilizzare il file _AppStart nello stato in cui si trova, si consiglia di centralizzarne la logica nel file Global.asax con il codice di avvio ASP.NET MVC esistente.
  4. Aggiungere la riga <roleManager enabled=true /> nella sezione <system.web> del file web.config radice. L'applicazione Raccolta foto utilizza il nuovo provider di appartenenze WebSecurity presente in WebMatrix.WebData, quindi sarà necessario aggiungerlo nella configurazione del sito per garantirne il funzionamento.
  5. Spostare tutti i fogli di stile, i file script e le immagini nelle cartelle Content o Scripts nell'applicazione. Aggiornare tutti i collegamenti alle risorse presenti in tali file con i nuovi percorsi.
  6. Modificare il percorso predefinito in Global.asax in modo che punti al controller Gallery e all'azione Default.
  7. Copiare il database SQL Compact presente nella cartella App_Data nella cartella App_Data del sito. Se si utilizza un altro database per il sito, aggiungere la relativa stringa di connessione al file Web.Config dell'applicazione.

Migrazione da pagine a viste

Una volta completata l'impostazione iniziale del sito ASP.NET MVC, si è pronti per migrare la parte principale del sito esistente: le pagine. In Web Pages, una pagina (.[cs/vb]html) contiene markup, logica aziendale e tutti gli accessi ai dati necessari per la pagina. La parte principale del processo di migrazione ad ASP.NET MVC consisterà nello smembrare ciascuna pagina e suddividerne il contenuto in azioni Controller (logica aziendale), classi di accesso ai dati (accesso ai dati) e viste (markup).

In primo luogo, è necessario migrare il layout del sito. In modo simile alle pagine master in Web Form e ASP.NET MVC, le pagine di layout sono file in cui vengono specificate le strutture di layout del sito. Web Pages e ASP.NET MVC 3 (se utilizzati in associazione al motore di visualizzazione Razor) utilizzano entrambi lo stesso sottosistema di layout, pertanto questa parte della migrazione dovrebbe risultare semplice. Nel sito Raccolta foto, il file _SiteLayout.cshtml radice contiene la struttura del sito. È necessario copiarne il contenuto e spostarsi sul sito ASP.NET MVC. Aprire, quindi, il file di layout che si trova nel percorso Views/Shared/_Layout.cshtml e incollare il contenuto del file _SiteLayout.cshtml.

Al termine., sarà necessario apportare alcune modifiche minori al file _Layout.cshtml. Innanzitutto, sarà necessario modificare il collegamento al foglio di stile con la nuova posizione nell'applicazione ASP.NET MVC application (~/Content/Site.css invece di ~/Styles/Site.css). In secondo luogo, sarà necessario modificare @Page.Title in @ViewBag.Title. Entrambi sono oggetti di tipo dinamico che contengono i dati di visualizzazione o altro relativi alle pagine del sito e, come probabilmente avrete dedotto, Page viene utilizzato Web Pages, mentre ViewBag viene utilizzato per ASP.NET MVC.

L'ultimo elemento da modificare nel file _Layout.cshtml è qualcosa da tenere in considerazione per tutte le pagine da migrare ad ASP.NET MVC. Si tenga presente che nel file _Layout.cshtml vengono utilizzate chiamate @Href per inserire URL nella pagina. Per qualsiasi chiamata che faccia riferimento a contenuto statico (script, fogli CSS e così via), possono restare invariati. Sarà, tuttavia, necessario modificare tutte le chiamate @Href che puntano a pagine nel sito. Benché funzioneranno anche nello stato in cui si trovano dopo la migrazione, puntano comunque a URL statici. In ASP.NET MVC, è considerata procedura consigliata utilizzare il routing ASP.NET per creare URL da utilizzare durante il rendering delle viste. Il risultato è più ordinato e i collegamenti sono associati alle definizioni di una tabella di routing, piuttosto che impostati come hardcoded nel sito .

Come tale, sarà necessario modificare tutti i collegamenti nel modo seguente:

<div id="banner">
  <p class="site-title">
    <a href="@Href("~/")">Photo Gallery</a>
  </p>
...
</div>

Al contrario, utilizzeremo @Url.RouteUrl o @Url.Action:

<div id="banner">
  <p class="site-title">
    <a href="@Url.Action("Default", "Gallery")">Photo Gallery</a>
  </p>
...
</div>

Una volta completata la migrazione del layout del sito, è possibile iniziare la migrazione delle pagine in viste. Se nell'applicazione Web Pages sono presenti eventuali pagine con estensione .cshtml eseguite da chiamate RenderPage, spostarle nella cartella Views/Shared per le pagine che interessano l'intero sito o nella sottocartella Views appropriata per le pagine condivise da un controller, quale Account. Ciascuna pagina che chiama una di queste pagine parziali, dovrà essere aggiornata per riflettere la nuova posizione.

Tutte le pagine rimanenti devono essere spostate nella cartella Views, organizzate in cartelle dal controller. Poiché nel sito Web Pages non esiste alcun concetto di controller, sarà necessario introdurre i controller durante una migrazione. La buona notizia è rappresentata dal fatto che una sorta di struttura di controller è evidente nell'applicazione Raccolta foto che rappresenta una buona norma da seguire nei propri siti.

Ad esempio, nel sito dei modelli Raccolta foto vengono utilizzate le seguenti cartelle per il raggruppamento delle pagine: Account, Gallery, Photo, Tag e User. Ciascun cartella contiene pagine che consentono alcune funzionalità correlate al raggruppamento. Ad esempio, la cartella Account contiene pagine per accedere a e uscire dal sito e per la registrazione degli utenti. La cartella Gallery contiene una pagina di elenco della raccolta, una pagina per l'aggiunta di una nuova raccolta e una pagina per la visualizzazione delle foro in una raccolta. Le restanti cartelle sono organizzate in modo simile. Benché tale strutture non sia necessaria nei siti Web Pages, consente una migrazione più semplice ad ASP.NET MVC. In questo caso, ciascuna cartella si associa perfettamente a un controller e ciascun file .cshtml a un'azione a una vista.

Iniziamo a spostare la cartella Account e le relative tre pagine, Login, Logout e Register nell'applicazione ASP.NET MVC sotto la directory Views. Nel gergo di ASP.NET MVC, le pagine diventano istantaneamente viste in base alla natura della propria posizione nell'applicazione. Non abbiamo ancora finito, tuttavia, poiché l'applicazione necessita di un controller e di un'azione per poter mostrare tali viste all'utente quando richiesto.

Introduzione ai controller

Per convenzione di MVC, il fatto che si disponga di una cartella Account sotto la directory Views significa che si dovrebbe disporre di un controller denominato AccountController; pertanto, il nostro prossimo passo consiste nel creare tale controller sotto la cartella Controllers. È sufficiente fare clic con il pulsante destro del mouse e scegliere Aggiungi | controller. Da questo controller vuoto, possiamo creare metodi azione che conterranno la logica che si trova adesso nella parte superiore di ciascuna pagina .cshtml spostata nell'applicazione.

Prenderemo in considerazione prima il file Login.cshtml, che contiene il codice illustrato nella Figura 1.

Figura 1 Logica aziendale contenuta nella pagina Login.cshtml

Page.Title = "Login";
if (IsPost) {
  var email = Request["email"];
  if (email.IsEmpty()) {
    ModelState.AddError(
      "email", "You must specify an email address.");
  }
  var password = Request["password"];
  if (password.IsEmpty()) {
    ModelState.AddError(
      "password", "You must specify a password.");
  }

  if (ModelState.IsValid) {
    var rememberMe = Request["rememberMe"].AsBool();
    if (WebSecurity.Login(email, password, rememberMe)) { 
      string returnUrl = Request["returnUrl"];        
      if (!returnUrl.IsEmpty()) {
        Context.RedirectLocal(returnUrl);
      } else{
        Response.Redirect("~/");
      }
    } else {
      ModelState.AddFormError(
        "The email or password provided is incorrect.");
    }
  }
}

Tenere presente che vengono gestiti due scenari in questo contesto. Il primo contempla la situazione in cui l'utente carica la pagina di accesso per la prima volta. In questo scenario, la pagina imposta il proprio titolo e le transizioni direttamente nei markup. Il secondo scenario è contenuto nell'istruzione condizionale IsPost e rappresenta la logica eseguita quando l'utente completa il modulo di accesso e fa clic sul pulsante di accesso.

In ASP.NET MVC, viene gestito un processo di distribuzione di un modulo vuoto e di accettazione dell'invio di un modulo mediante la creazione di due metodi azione nel controller, uno per il modulo vuoto e uno per gestire l'invio. La prima azione imposterà il titolo della pagina e restituirà la vista di accesso, mentre la second conterrà la logica all'interno dell'istruzione condizionale IsPost. Tali azioni sono illustrate nella Figura 2. Dopo aver aggiunto queste due azioni, eliminare il codice di intestazione dal file Login.cshtml.

Figura 2 Azioni del controller di accesso

public ActionResult Login() {
  ViewBag.Title = "Login";
  return View();
}

[HttpPost]
public ActionResult Login(string email, string password, 
  bool? rememberMe, string returnUrl) {
  if (email.IsEmpty())
    ModelState.AddModelError("email", 
      "You must specify an email address.");
  if (password.IsEmpty())
    ModelState.AddModelError("password", 
      "You must specify a password.");
  if (!ModelState.IsValid)
    return View();
  if (WebSecurity.Login(email, password, 
    rememberMe.HasValue ? rememberMe.Value : false)) {
    if (!string.IsNullOrEmpty(returnUrl))
      return Redirect(returnUrl);
    return RedirectToAction("Default", "Gallery");
  }

  ModelState.AddModelError("_FORM", 
    "The email or password provided is incorrect");
  return View();
}

Esistono diverse differenze principali da considerare tra la pagina originale e i metodi azione risultanti. I principianti noteranno che l'istruzione condizionale IsPost non è necessaria. In ASP.NET MVC, creiamo un'azione Post per la pagina di accesso mediante la creazione di un secondo metodo azione Login e l'aggiunta dell'attributo [HttpPost]. Il nostro primo metodo Login adesso si limita a impostare la proprietà ViewBag.Title e a restituire l'elemento ViewResult, che provvederà alla ricerca di una pagina di visualizzazione nella cartella Views/Account denominata Login.cshtml.

Il secondo aspetto da osservare è che l'azione Post contiene diversi parametri e che tutte le chiamate all'oggetto Request utilizzate dalla pagina originale sono sparite. Inserendo parametri nel metodo che corrispondono ai nomi di campi nel modulo Login (email, password e rememberMe) possiamo utilizzare il raccoglitore dei modelli predefiniti di ASP.NET MVC per fare in modo che tali elementi vengano passati come parametri all'azione, il che ci risparmia di chiamare l'oggetto Request e rende la logica dell'azione più sintetica.

Infine, esistono alcune differenze minori nel modo in cui viene gestita la convalida e vengono effettuati i reindirizzamenti nelle applicazioni Web Pages e ASP.NET MVC. Nel sito Web Pages, ModelState.AddError e .AddFormError sono le chiamate utilizzare per segnalare alla pagina che sono stati riscontrati dati non validi nel modulo. Nelle applicazioni ASP.NET MVC, utilizziamo ModelState.AddModelError, che differisce leggermente ma che è richiesto per tutte le pagine. Per i reindirizzamenti, il sito Web Pages chiama il metodo Response.Redirect durante il reindirizzamento dell'utente. In ASP.NET MVC, poiché le azioni del controller devono restituire un ActionResult, chiamiamo return RedirectToRoute("Default"), che restituisce lo stesso risultato.

Una volta completata la migrazione della pagina di accesso, possiamo rapidamente occuparci della pagina Logout.cshtml. In Web Pages, è possibile che alcune pagine contengano la logica ma alcun markup se sono finalizzate all'esecuzione di un'azione e al reindirizzamento dell'utente, come accade per Logout.cshtml:

@{
  WebSecurity.Logout();
  Response.Redirect("~/");
}

In ASP.NET MVC, aggiungeremo un'azione Logout che esegue l'operazione automaticamente:

public ActionResult Logout() {
  WebSecurity.Logout();
  return RedirectToAction("Default", "Gallery");
}

Poiché le viste rappresentano solo gli elementi visivi di una pagina e non contengono funzionalità e abbiamo creato un'azione che gestisce la disconnessione e il reindirizzamento dell'utente, possiamo eliminare la vista Logout.cshtml dall'applicazione.

Fino a questo punto, abbiamo convertito le pagine della cartella Account in viste copiandole nella cartella Views/Account, abbiamo creato un AccountController per gestire le richieste inviate alle pagine Account e abbiamo implementato metodi azione per gestire le situazioni di accesso e disconnessione. A questo punto, è possibile creare ed eseguire il sito e aggiungere Account/Login alla barra degli indirizzi del browser (si noti che la Home page punta a Gallery/Default, che non abbiamo implementato e che pertanto non viene visualizzata).

L'altra parte della funzionalità del sito da prendere in considerazione a questo punto è il codice e gli helper contenuti nella directory App_Code del sito Web Pages. All'inizio della migrazione, è possibile spostare l'intera directory nell'applicazione ASP.NET MVC e includerla nel progetto. Se la directory contiene eventuali file di codice (.cs o .vb), è possibile lasciarli nella directory App_Code o spostarli in un'altra posizione. In entrambi i casi, sarà necessario cambiare il valore della proprietà Build Action di ciascun file su Compile piuttosto che Content. Se la directory contiene file .cshtml con dichiarazioni del metodo @helper, è possibile lasciarli e utilizzarli nello stato in cui si trovano nell'applicazione ASP.NET MVC.

Per la parte restante del sito Web Pages, si seguirà un ciclo simile in cui viene creato un controller per ciascuna cartella Views, vengono create azioni per ciascuna pagina e viene spostato il codice di intestazione da ciascuna pagina in una o più azioni. In brevissimo tempo, si otterranno tutte le pagine ordinatamente delimitate in azioni controller e viste. Tuttavia, esiste ancora un aspetto di MVC di cui non abbiamo ancora parlato in questo articolo: il modello.

Migrazione dell'accesso ai dati in classi Repository

Il processo di trasferimento della logica aziendale da ciascuna pagina in una o più azioni controller è un'operazione piuttosto semplice, con una eccezione: l'accesso ai dati Benché è possibile che alcune delle pagine siano simili alle pagine di accesso e di disconnessione e contengano una logica ma nessuna funzionalità di accesso ai dati, la maggior parte del sito Web Pages probabilmente utilizza un database.

La pagina Account/Register.cshtml ne è un esempio. Quando l'utente completa il modulo di registrazione e fa clic sul relativo pulsante, vengono effettuate due chiamate al database, illustrate nella Figura 3.

Figura 3 Logica del database della pagina Register.cshtml

var db = Database.Open("PhotoGallery");
      
var user = db.QuerySingle("SELECT Email FROM 
UserProfiles WHERE LOWER(Email) = LOWER(@0)", email);
       
if (user == null) {      
  db.Execute(
    "INSERT INTO UserProfiles (Email, DisplayName, Bio) 
    VALUES (@0, @1, @2)", email, email, "");

  try {
    WebSecurity.CreateAccount(email, password);
    WebSecurity.Login(email, password);
    Response.Redirect("~/");
  } catch (System.Web.Security.MembershipCreateUserException e) {
    ModelState.AddFormError(e.ToString());
  }
} else {
  ModelState.AddFormError("Email address is already in use.");
}

In primo luogo, la pagina di registrazione apre il database PhotoGallery e restituisce un oggetto WebMatrix.Data.Database che rappresenta il database. Successivamente, la pagina utilizza l'oggetto per cercare un indirizzo di posta elettronica esistente con il valore fornito dall'utente. Se l'indirizzo non esiste, viene creato un nuovo record UserProfile e viene creato un account per l'utente mediante il provider di appartenenze WebSecurity.

Fintantoché abbiamo aggiunto un riferimento a WebMatrix.Data e impostato la proprietà Copy Local su true, possiamo utilizzare questa logica di database senza modifiche e il sito funzionerà normalmente. Nell'ambito di una migrazione in corso, questo potrebbe essere l'approccio più adatto per garantire la continuità di funzionamento del sito.

In questo articolo, tuttavia, andremo oltre e creeremo altri oggetti che contengono le funzionalità di accesso ai dati, esattamente come faremmo per un'applicazione ASP.NET MVC creata da zero. Esistono diversi modelli a disposizione per separare la logica del controller da quella di accesso ai dati. Utilizzeremo il modello Repository della Raccolta foto e, mediante l'astrazione delle funzionalità di accesso ai dati in classi Repository, possiamo incapsulare questa logica e ridurre al minimo le conseguenze, qualora scegliessimo in corso d'opera di aggiungere oggetti Model formali o un sistema ORM (Object-Relational Mapping), ad esempio Entity Framework.

Inizieremo con la creazione di una cartella Repositories nell'applicazione insieme a una piccola classe denominata AccountRepository.cs. Quindi, possiamo passare a ciascuna chiamata al database nell'azione Register e spostare la relativa logica nel nostro oggetto Repository, come mostrato nella Figura 4.

Figura 4 AccountRepository

public class AccountRepository {
  readonly Database _database;
  public AccountRepository() {
    database = Database.Open("PhotoGallery");
  }

  public dynamic GetAccountEmail(string email) { 
    return _database.QuerySingle(
      "SELECT Email FROM UserProfiles 
      WHERE LOWER(Email) = LOWER(@0)", email);
  }
 
  public void CreateAccount(string email) {
    _database.Execute(
      "INSERT INTO UserProfiles 
      (Email, DisplayName, Bio) VALUES (@0, @1, @2)", 
      email, email, "");
  }
}

Abbiamo aggiunto la chiamata a Database.Open al costruttore del nostro repository e abbiamo creato due metodi, uno per la ricerca di un account di posta elettronica e un altro per la creazione dell'account.

Si osservi che il tipo restituito per GetAccountEmail è dinamico. In WebMatrix.Data, molti dei metodi di query restituiscono risultati dinamici o di tipo IEnumerable<dynamic> e non vi è alcun motivo per non continuare a utilizzare questa procedura nei propri repository per tutto il tempo necessario. 

Il nuovo metodo Register, che utilizza AccountRespository, è illustrato nella Figura 5.

Figura 5 Azione Register che utilizza AccountRepository

[HttpPost]
public ActionResult Register(string email, string password, 
  string confirmPassword) {

  // Check Parameters (omitted)

  if (!ModelState.IsValid)
    return View();
 
  var db = new AccountRepository();
  var user = db.GetAccountEmail(email);
 
  if (user == null) {
    db.CreateAccount(email);
 
    try {
      WebSecurity.CreateAccount(email, password);
      WebSecurity.Login(email, password);
      return RedirectToAction("Default", "Gallery");
    }
    catch (System.Web.Security.MembershipCreateUserException e) {
      ModelState.AddModelError("_FORM", e.ToString());
    }
  }
  else {
    ModelState.AddModelError("_FORM", 
      "Email address is already in use.");
  }
 
  return View();
}

L'utilizzo di tipi restituiti dinamici è assolutamente accettabile e potrebbe essere anche consigliabile durante una migrazione poiché si otterrebbe un sito completamente funzionante come applicazione ASP.NET MVC completa. Non è necessario utilizzare modelli fortemente tipizzati in un'applicazione ASP.NET MVC; pertanto, è possibile utilizzare questa strategia fintantoché non si presenti l'esigenza di una definizione basata sul codice del modello dati. La logica del controller e le viste dell'applicazione ASP.NET MVC basata su modelli dinamici funzionerà normalmente, con un'eccezione.

È possibile che abbiate notato che nell'applicazione Web Pages i campi dei moduli sono esplicitamente definiti mediante markup standard:

<input type="text" />
<input type="submit" />
...

In ASP.NET MVC, il modo migliore di utilizzare i controlli dei moduli consiste nell'utilizzare i metodi helper Html quali Html.TextBox o Html.TextBoxFor perché questi ultimi utilizzano il modello passato nella vista per l'impostazione dei valori correnti e la gestione della convalida dei moduli. Per utilizzare queste metodi helper durante la fase di post-migrazione delle viste, sarà necessario introdurre oggetti Model fortemente tipizzati ed evitare l'utilizzo di tipi dinamici nei repository, poiché i metodi helper non funzionano con i modelli dinamici.

Conservazione degli URL del sito

Gli URL del sito sono importanti. A prescindere dallo stato del sito, molte risorse esterne dipendono dagli URL esistenti, tra cui motori di ricerca, documentazione, comunicazioni, script di test e simili. A causa di tali dipendenze, non si devono arbitrariamente modificare gli URL, anche in caso di migrazione.

Si consiglia di prendere in considerazione il routing ASP.NET per assicurarsi che vengano conservati gli URL esistenti. Il routing ASP.NET facilita una richiesta e la associa alla risorsa corretta, nel nostro caso un controller e un'azione. Web Pages utilizza un sistema di routing diverso rispetto ad ASP.NET MVC, pertanto sarà necessario dedicare del tempo per assicurarsi che gli URL esistenti vengano conservati.

Le applicazioni Web Pages possono gestire URL con e senza estensioni. Ad esempio, entrambi questi URL fanno riferimento alla stessa pagina:

http://miosito/Gallery/Default.cshtml

http://miosito/Gallery/Default

Un'applicazione ASP.NET MVC, tuttavia, non gestirà il primo URL mediante l'estensione .cshtml. L'utilizzo di URL senza estensioni nell'intero sito garantirà che i motori di ricerca e altri siti dipendenti si comportino allo stesso modo, il che ridurrà al minimo le conseguenze della migrazione sul sito. Se, tuttavia, è necessario gestire URL esistenti con estensioni, è possibile creare percorsi nell'applicazione ASP.NET MVC per assicurarsi che non siano interrotti.

Ad esempio, consideriamo il seguente percorso per la nostra applicazione Raccolta foto:

routes.MapRoute(
  "Default", 
  "{controller}/{action}/{id}", 
  new { controller = "Home", 
    action = "Index", id = "" } 
);

Per garantire il supporto degli legacy nel nostro sistema, sarà necessario aggiungere percorsi alla nostra tabella di routing sopra questa definizione del file Global.asax. Di seguito un esempio di questa definizione:

routes.MapRoute(
  "LegacyUrl",
  "{controller}/{action}.cshtml/{id}",
  new { controller = "Gallery", 
    action = "Default", id = "" }
);

In questa route, gli URL che contengono l'estensione .cshtml vengono gestiti e inviati al controller e all'azione appropriati, presupponendo che la struttura del sito Web Pages esegua il mapping in modo corretto alla struttura controller/azione

Durante la pianificazione di una migrazione, tenere presente che potrebbe essere necessario modificare la route predefinita o anche altre route dell'applicazione per garantire il supporto degli URL esistenti. Se, tuttavia, si decide di disassemblare un URL esistente, assicurarsi di includere la cartella Actions per la gestione dei reindirizzamenti permanenti per gli utenti.

Conclusioni

Per mettere in evidenza le conseguenze di una migrazione da Web Pages a ASP.NET MVC, esaminiamo alla struttura iniziale e finale del sito Raccolta foto. Nella Figura 6, viene visualizzata la struttura del sito Web Pages in WebMatrix sulla sinistra. Sulla destra viene visualizzato il sito dopo il completamento di una migrazione ad ASP.NET MVC. Si osservi che, benché siano presenti differenze strutturali, gran parte del risultato finale ci apparirà familiare.

Application Layout Before and After

Figura 6 Layout dell'applicazione iniziale e finale

Attualmente gli sviluppatori ASP.NET dispongono di tre opzioni framework tra cui scegliere: Web Form, Web Pages e ASP.NET MVC. Benché ciascuno di essi disponga dei propri punti di forza, la scelta di uno non impedisce di sfruttarne un altro o di migrare il proprio sito completamente a un altro framework in futuro. Inoltre, poiché tutti e tre sono basati su ASP.NET, la migrazione da uno a un altro non dovrebbe mai rappresentare un problema dal punto di vista tecnico. Se si sceglie di migrare, le somiglianze tra Web Pages e ASP.NET MVC consentono di continuare a utilizzare tecnologie quali NuGet, Razor, Web Deploy, IIS Express ed SQL Compact senza modifiche.

Se si crea un'applicazione con Web Pages e si decide di effettuare una migrazione, il passaggio da Web Pages ad ASP.NET MVC rappresenta il percorso più semplice, specialmente se si prendono in anticipo delle decisioni di progettazione relative al sito Web Pages in modo tale da raggruppare le pagine in cartelle in base alla relativa funzionalità, da utilizzare gli URL associati a tutte le risorse e da posizionare tutta la logica aziendale all'inizio di ciascuna pagina. Quando giunge il momento di iniziare la migrazione, ci si renderà conto che il passaggio da Web Pages ad ASP.NET MVC è semplice e indolore come previsto.

I collegamenti a diverse delle tecniche e tecnologie utilizzate in questo articolo e molto altro sono disponibili all'indirizzo bit.ly/WebMatrixToMVC.

Brandon Satrom è un Senior Developer Evangelist per Microsoft nei dintorni di Austin, Texas. Possiede un blog all'indirizzo userInexperience.com, crea podcast all'indirizzo DeveloperSmackdown.com ed è raggiungibile su Twitter all'indirizzo twitter.com/BrandonSatrom.

Clark Sell è un Senior Developer Evangelist per Microsoft nei dintorni di Chicago. Possiede un blog su csell.net, crea podcast all'indirizzo DeveloperSmackdown.com ed è raggiungibile su Twitter all'indirizzo twitter.com/csell5.

Un ringraziamento ai seguenti esperti tecnici per la revisione dell'articolo: Phil Haack ed Erik Porter