Condividi tramite


Il presente articolo è stato tradotto automaticamente.

ASP.NET,

Introduzione alla navigazione per il framework ASP.NET Web Forms

Graham Mendick

Scaricare il codice di esempio

La navigazione per ASP.Quadro NET Web Form, un progetto open source ospitato presso navigation.codeplex.com, ti permette di scrivere codice di Web Form con copertura di test di unità e l'aderenza alle te stesso non ripetere principi (a secco) che avrebbero fatto una pagina ASP.Applicazione MVC NET verde con invidia.

Anche se c'è stato qualche abbandono dei Web Form in favore di MVC, con alcuni sviluppatori crescente stanco di grandi codebehinds non raggiungibile da unit test, questo nuovo quadro — in collaborazione con associazione dati — fa un argomento convincente per prendere uno sguardo fresco al Web Form.

Associazione dati con controlli ObjectDataSource è stato intorno dal Visual Studio 2005, permettendo pulitore codebehinds e codice di recupero dei dati di essere unità testato, ma ci sono stati alcuni problemi di inibizione della sua assunzione — per esempio, generando un'eccezione era l'unico modo di riferire un fallimento di convalida aziendale all'interfaccia utente.

La stragrande maggioranza allo sforzo di sviluppo Web Form per l'imminente rilascio di Visual Studio è stata investita nell'associazione dati, portare attraverso i concetti di associazione modello da MVC per risolvere questi problemi — per esempio, l'introduzione di stato modello risolve il business convalida mancata comunicazione.Tuttavia, due spine rimangono nel lato di associazione dati relativi alla navigazione e dei dati passando — ma essi possono essere indolore estratti utilizzando la navigazione per ASP.Framework NET Web Form (che chiameremo "quadro di navigazione" qui di seguito per brevità).

La spina prima è che non c'è nessuna astrazione per la logica di navigazione, a differenza di in dove esso è incapsulato in tipi restituiti metodo controller MVC.Questo determini il reindirizzamento chiamate all'interno di metodi con associazione a dati, impedendo loro di essere testato unità.La Toruń è che il tipo di un parametro di un oggetto ObjectDataSource determina da dove viene il suo valore — per esempio, un QueryStringParameter ottiene sempre i dati dalla stringa di query.Questo previene la stessa origine dati viene utilizzato in diversi contesti di navigazione — ad esempio postback e non postback — senza logica sostanziale nel codebehind temuta.

Quadro di navigazione rimuove queste spine adottando un approccio olistico alla navigazione e dei dati passando.Indipendentemente dal tipo di navigazione viene eseguito — esso essere collegamento ipertestuale, postback, AJAX storia o unità di test — dati passati si tiene sempre nello stesso modo.In futuri articoli, farò vedere come questo porta alla codebehinds vuota con dati completamente testato da unità di recupero e navigazione logica e anche di Search Engine Optimization (SEO)-amichevole, progressivamente migliorato la sola pagina applicazioni senza duplicazione del codice per gli scenari di JavaScript abilitato e - disabled.Questo articolo presenta il quadro di navigazione e vengono illustrati alcuni dei suoi basic — ma chiave — concetti con la costruzione di un campione di applicazioni Web.

Applicazione di esempio

L'applicazione Web di esempio è un sondaggio online.Questa indagine ha solo due domande e viene visualizzato un messaggio di "thank you" al completamento.Ogni domanda è rappresentata da una pagina ASPX separata, chiamata rispettivamente Question1.aspx e Question2.aspx, e il messaggio "thank you" ha una propria pagina chiamata Thanks.aspx.

È la prima domanda, "quale ASP.NET tecnologia sei attualmente usando?"a che le risposte possibili sono"Web Form"o"MVC." Così a Question1.aspx io aggiungo la domanda e le risposte di pulsante radio hardcoded:

    <h1>Question 1</h1>
    <h2>Which ASP.NET technology are you currently using?</h2>
    <asp:RadioButtonList ID="Answer" runat="server">
      <asp:ListItem Text="Web Forms" Selected="True" />
      <asp:ListItem Text="MVC" />
    </asp:RadioButtonList>

Alla seconda domanda, "stai usando la navigazione per ASP.NET Web Form framework?"ha le risposte del"Sì"o"No"ed è contrassegnato in modo simile.

Introduzione

Il modo più semplice per impostare l'indagine progetto Web per utilizzare il framework di navigazione è installarlo utilizzando il gestore di pacchetti NuGet. L'esecuzione del comando "Pacchetto di installazione di navigazione" dall'interno della Console di gestione pacchetti aggiungerà il riferimento richiesto e la configurazione. Se non si utilizza Visual Studio 2010, istruzioni di installazione manuale possono essere trovate alla navigation.codeplex.com/documentation.

Configurazione di navigazione

Quadro di navigazione può essere pensato come una macchina a Stati, dove ogni diverso stato rappresenta una pagina e si muovono da uno stato a altro — o navigare tra le pagine — viene definita una transizione. Questo insieme predefinito di Stati e transizioni è configurato nel file StateInfo.config creato con l'installazione di NuGet. Senza questa configurazione di base, che esegue l'applicazione di indagine verrà generata un'eccezione.

Perché gli Stati sono essenzialmente solo pagine, l'applicazione di indagine richiede tre Stati, uno per ciascuno dei suoi tre pagine:

    <state key="Question1" page="~/Question1.aspx">
    </state>
    <state key="Question2" page="~/Question2.aspx">
    </state>
    <state key="Thanks" page="~/Thanks.aspx">
    </state>

Da ora in poi sarò riferirsi a diversi Stati con i loro nomi chiave, Question1, Question2 e grazie, piuttosto che dalle pagine che essi rappresentano.

Poiché le transizioni di descrivere i possibili navigazioni fra gli Stati, l'applicazione di indagine richiede due transizioni. Uno è per la navigazione da Question1 a Question2 e un altro è per la navigazione da Question2 grazie. Una transizione appare come un bambino dello stato sta uscito e punti, tramite il suo "a" attributo, allo stato immesso:

    <state key="Question1" page="~/Question1.aspx">
      <transition key="Next" to="Question2"/>
    </state>
    <state key="Question2" page="~/Question2.aspx">
      <transition key="Next" to="Thanks"/>
    </state>
    <state key="Thanks" page="~/Thanks.aspx">
    </state>

Finestre di dialogo sono l'elemento finale della configurazione e rappresentano un raggruppamento logico degli Stati. L'applicazione di indagine richiede solo una finestra di dialogo perché Question1, Question2 e grazie sono effettivamente un percorso di navigazione unico. Attributo "iniziale" della finestra di dialogo deve puntare allo stato iniziale — cioè, Question1:

    <dialog key="Survey" initial="Question1" path="~/Question1.aspx">
      <state key="Question1" page="~/Question1.aspx">
        <transition key="Next" to="Question2"/>
      </state>
      <state key="Question2" page="~/Question2.aspx">
        <transition key="Next" to="Thanks"/>
      </state>
      <state key="Thanks" page="~/Thanks.aspx">
      </state>
    </dialog>

Si noterà che ogni finestra di dialogo, stato e transizione ha un attributo key. Ho scelto di nome i tasti dello stato dopo i nomi di pagina, ma questo non è necessario. Si noti, però, che tutte le chiavi devono essere univoci all'interno del loro genitore; ad esempio, si possono avere stati pari livello con la stessa chiave.

Con Question1.aspx come pagina iniziale, l'applicazione di indagine ora inizia con successo nello stato Question1. Tuttavia, l'indagine rimane bloccato in questo stato perché non c'è alcun modo per progresso a Question2.

Esplorazione

È utile dividere i diversi tipi di navigazione Web Form in due campi. Il campo non postback si dove controllo da una pagina ASPX viene passato a un altro e prende la forma di collegamenti ipertestuali, reindirizza o trasferimenti. Il campo di postback è dove il controllo rimane sulla stessa pagina e prende la forma di postback, richieste di pagina parziale o storia di AJAX. Questo secondo tipo sarà esaminato in un prossimo articolo discute il modello di interfaccia a pagina singola. In questo articolo, concentrerò sul primo tipo di navigazione.

Per spostarsi tra le pagine, deve essere costruito un URL. Prima di Visual Studio 2008, l'unica opzione era di costruire manualmente gli URL da nomi di pagina ASPX hardcoded, causando l'accoppiamento stretto tra le pagine che hanno fatto le applicazioni fragili e difficile da mantenere. L'introduzione di routing alleviata questo problema, con nomi di percorso configurabile utilizzati al posto dei nomi di pagina. Tuttavia, il fatto che di routing genera un'eccezione se utilizzato di fuori di un ambiente Web —­combinato con resistenza di instradamento a beffardo — lo rende un nemico di unit test.

Quadro di navigazione conserva l'accoppiamento lasco fornito da di routing ed è un amico di unit test. Simile all'uso di nomi di percorso, anziché hardcoding nomi di pagina ASPX, esso è la finestra di dialogo e di transizione tasti configurati nella sezione precedente che si fa riferimento nel codice; lo stato di spostarsi è determinato dai rispettivo "iniziale" e "a" attributi.

Tornando all'indagine, la chiave di transizione successiva consente di passare da Question1 a Question2. Aggiungere un pulsante avanti per Question1.aspx e il codice seguente nel suo associato fare clic su gestore:

protected void Next_Click(object sender, EventArgs e)
{
  StateController.Navigate("Next");
}

La chiave passata al metodo Navigate viene confrontata con le transizioni configurato bambino dello stato Question1 e quindi viene visualizzato lo stato identificato dall'attributo "a" — cioè, Question2. Aggiungerò lo stesso pulsante e gestore di Question2.aspx. Se si esegue il survey, troverete che è possibile navigare attraverso i tre stati cliccando sui pulsanti Next.

Potreste aver notato la seconda questione è Web Form specifico e, come tale, è irrilevante quando "MVC" è stato selezionato come prima risposta. Il codice deve cambiare per gestire questo scenario, navigare direttamente da Question1 grazie e bypassare Question2 interamente.

La configurazione corrente non consentire la navigazione da Question1 a grazie perché la transizione sola elencata è quello di Question2. Così cambierò la configurazione con l'aggiunta di una seconda transizione di sotto dello stato Question1:

    <state key="Question1" page="~/Question1.aspx">
      <transition key="Next" to="Question2"/>
      <transition key="Next_MVC" to="Thanks"/>
    </state>

Con questa nuova transizione in atto è semplice regolare la prossimo gestore click del pulsante per passare una chiave di transizione diverse a seconda del risposta scelta:

if (Answer.SelectedValue != "MVC")
{
  StateController.Navigate("Next");
}
else
{
  StateController.Navigate("Next_MVC");
}

Un'indagine non sarebbe molto buona se non permette all'utente di modificare le risposte. Attualmente non non c'è alcun modo per tornare a una domanda precedente (oltre al pulsante indietro del browser). Per spostarsi indietro si potrebbe pensare che è necessario aggiungere due transizioni sotto grazie, che punta a Question1 e Question2 e l'altro di sotto di Question2, che punta a Question1. Anche se questo dovrebbe funzionare, è inutile perché la navigazione posteriore viene gratis con quadro di navigazione.

Percorso di spostamento è un insieme di collegamenti che fornisce accesso a ogni pagina precedente, l'utente ha visitato nel raggiungimento di quella attuale. Web Form ha percorso di spostamento integrato nel suo funzionalità Mappa del sito. Tuttavia, poiché le mappe del sito sono rappresentate da una struttura di navigazione fissa, per una determinata pagina questi pangrattato è sempre gli stessi indipendentemente dall'itinerario seguito. Essi non possono gestire situazioni come quella trovata nell'indagine dove la rotta a grazie a volte esclude Question2. Quadro di navigazione, di tenere traccia di stati visitati come navigazioni effettuate, accumula un breadcrumb trail della rotta effettiva presa.

Per dimostrare,'ll aggiungere che un collegamento ipertestuale a Question2.aspx e nel codebehind impostata a livello di codice la proprietà NavigateUrl usando navigazione indietro. Deve essere passato un parametro di distanza che indica quanti afferma di tornare a, un valore di 1 significato immediato predecessore:

protected void Page_Load(object sender, EventArgs e)
{
  Question1.NavigateUrl = StateController.GetNavigationBackLink(1);
}

Se si esegue l'applicazione e risposta "Web Form" a mettere in discussione quello che si vedrà il collegamento ipertestuale su Question2.aspx ti porta indietro alla prima domanda.

Farò lo stesso per Thanks.aspx, anche se è un po' più ingannevole perché due collegamenti ipertestuali sono necessario (uno per ogni domanda), e l'utente non può aver visto entrambe le questioni — cioè, se egli rispose "MVC" al primo. Il numero di stati precedenti può essere controllato prima di decidere come impostare i collegamenti ipertestuali (vedere Figura 1).

Figura 1 navigazione dinamica Back

protected void Page_Load(object sender, EventArgs e)
{
  if (StateController.CanNavigateBack(2))
  {
    Question1.NavigateUrl = StateController.GetNavigationBackLink(2);
    Question2.NavigateUrl = StateController.GetNavigationBackLink(1);
  }
  else
  {
    Question1.NavigateUrl = StateController.GetNavigationBackLink(1);
    Question2.Visible = false;
  }
}

L'indagine è ora funzionale, consentendo di compilare domande e modificare le risposte precedenti. Ma c'è il piccolo punto un sondaggio se queste risposte non sono oggetto di uso. Vi mostrerò come essi possono essere passati da Question1 e Question2 a grazie, dove verrà visualizzati in forma sintetica.

Passaggio di dati

Ci sono tanti modi diversi di passaggio di dati in Web Form come ci sono modi per navigare. Con la navigazione non postback, dove il controllo passa da una pagina a altra (tramite collegamento ipertestuale, redirect o trasferimento), stringa di query o percorso dati possono essere utilizzati. Con navigazione postback, dove il controllo rimane sulla stessa pagina (tramite postback, richiesta di pagina parziale o storia di AJAX), i valori del controllo, vista dello stato o un evento argomenti è i probabili candidati.

Prima di Visual Studio 2005, sono stati gravati codebehinds con la gestione di tali dati passati, così essi si gonfiò con logica di valore-estrazione e conversione dei tipi. Loro carico è stato notevolmente alleggerito con l'introduzione di controlli origine dati e parametri di selezionati ("valore provider" nella prossima versione di Visual Studio). Tuttavia, questi parametri selezionare sono legati a un'origine dati specifica ed essi non possono passare dinamicamente fonti a seconda del contesto di navigazione. Ad esempio, non è possibile recuperare i valori in alternativa da un controllo o dalla stringa di query a seconda che essa sia un postback o no. Codice a fuoriuscire in code-behind, ritornare alla piazza uno dei codebehinds gonfio e untestable fa sì che lavorare intorno a queste limitazioni.

Quadro di navigazione evita questi problemi fornendo un unico data source indipendentemente la navigazione coinvolta, dati relativi allo stato chiamato. La prima volta che viene caricata una pagina, i dati di stato viene popolati con tutti i dati passati durante la navigazione, in modo simile per interrogare i dati stringa o rotta. Una marcata differenza, tuttavia, è quello stato dati non di sola lettura, così come successive navigazioni postback si verificano, può essere aggiornato per riflettere la pagina corrente della incarnazione. Si rivelerà utile quando rivisitare spostamento indietro verso la fine di questa sezione.

Cambierò il sondaggio quindi la risposta alla prima domanda è passata allo stato grazie dove si rivisualizzato per l'utente. I dati vengono passati durante la navigazione attraverso un insieme di coppie chiave / valore, chiamato NavigationData. Cambierò gestore click successivo di Question1.aspx quindi la risposta alla prima domanda è passata allo stato successivo:

NavigationData data = new NavigationData();
data["technology"] = Answer.SelectedValue;
if (Answer.SelectedValue != "MVC")
{
  StateController.Navigate("Next", data);
}
else
{
  StateController.Navigate("Next_MVC", data);
}

Questo NavigationData passato durante la navigazione viene utilizzato per inizializzare i dati di stato che viene reso disponibili per lo stato successivo tramite la proprietà Data dell'oggetto StateContext. Io ' ll aggiungere un'etichetta al Thanks.aspx e impostare la proprietà Text per visualizzare la risposta passata in:

Summary.Text = (string) StateContext.Data["technology"];

Se si esegue l'indagine, si noterà che informazioni di riepilogo viene visualizzati solo quando la risposta alla prima domanda è "MVC"; una risposta di "Web Form" non è mai mostrata. Questo è perché NavigationData è disponibile solo per lo stato successivo, ma non per tutti gli Stati raggiunto a causa di spostamento successivo. Quindi una risposta di "Web Form" è presente nei dati di stato Question2, ma non è disponibile per il momento è raggiungibile grazie. Questo è uno dei modi per risolvere per modificare Question2.aspx in modo che esso trasmette la risposta alla prima domanda — cioè, prende la risposta fuori dei relativi dati di stato e passa al grazie quando esso si sposta:

NavigationData data = new NavigationData();
data["technology"] = StateContext.Data["technology"];
StateController.Navigate("Next", data);

Questo approccio non è ideale perché esso coppie Question1 e Question2 insieme, costringendo lo stato quest'ultimo di essere a conoscenza dei dati passati da ex. Ad esempio, non è possibile inserire una nuova domanda tra il primo e il secondo senza un corrispondente cambiamento Question2.aspx. Un'implementazione a prova di futuro prevede la creazione di un nuovo NavigationData contenente tutti i dati di stato Question2; Questo risultato è ottenuto passando true al costruttore NavigationData:

NavigationData data = new NavigationData(true);
StateController.Navigate("Next", data);

Un'altra differenza fondamentale tra i dati sullo stato e dati di query string o rotta è che con i dati dello stato non stai limitata alla passando stringhe. Piuttosto che passare la risposta come una stringa, come è stato fatto per Question1, per Question2 I'll passare un bool a grazie, con un valore di vera corrispondente a "Sì":

NavigationData data = new NavigationData(true);
data["navigation"] = Answer.SelectedValue == "Yes" ?
true : false;
StateController.Navigate("Next", data);

Si può vedere che il tipo di dati viene mantenuto quando esso viene recuperato dai dati dello stato grazie:

Summary.Text = (string) StateContext.Data["technology"];
if (StateContext.Data["navigation"] != null)
{
  Summary.Text += ", " + (bool) StateContext.Data["navigation"];
}

L'indagine è completa, tranne che per un problema: Risposte a domande non sono mantenute quando utilizzando i collegamenti ipertestuali di navigazione indietro. Ad esempio, quando ritorno a Question1 da grazie al contesto viene perso, così il pulsante di opzione predefinita "Web Form" è sempre selezionato indipendentemente la risposta data.

Nella sezione precedente si è visto il beneficio di navigazione indietro nel pangrattato mappa sito statico. Un'altra limitazione di pangrattato generato dalla mappa del sito è che non portano tutti i dati. Questo significa seguendole può perdere informazioni contestuali. Ad esempio, essi non possono passare la risposta "MVC" precedentemente selezionata quando tornano a Question1 da grazie. Quadro di navigazione, di tenere traccia dei dati di stato connessi con gli stati visitati come navigazioni effettuate, accumula un sensibile al contesto breadcrumb trail. Durante una navigazione indietro questo stato dati vengono ripristinati, permettendo la pagina per essere ricreato esattamente come prima.

Armati con sensibile al contesto di navigazione indietro, posso cambiare l'indagine affinché le risposte vengono mantenute quando rivisitare gli Stati. La prima fase consiste nell'impostare le risposte in dati relativi allo stato nei gestori clic successivi, prima di navigare lontano:

StateContext.Data["answer"] = Answer.SelectedValue;

Ora, quando vengono rivisitati Question1 o Question2, i dati di stato conterrà la risposta selezionata in precedenza. È, quindi, una semplice questione di recuperare questa risposta nel metodo Page_Load e preselezionare il pulsante di opzione pertinenti:

protected void Page_Load(object sender, EventArgs e)
{
  if (!Page.IsPostBack)
  {
    if (StateContext.Data["answer"] != null)
    {
      Answer.SelectedValue = 
        (string)StateContext.Data["answer"];
    }
  }
}

L'indagine, ormai completo, non è suscettibile di errori comunemente riscontrati nelle applicazioni Web quando un utente preme il pulsante indietro del browser (o hanno più finestre del browser aperte). Tali problemi sorgono in genere quando dati specifici della pagina viene mantenuti in una sessione sul lato server. Anche se c'è un solo oggetto session, ci possono essere più versioni di "corrente" di una singola pagina. Ad esempio, utilizzando il pulsante indietro per recuperare una versione "obsolete" di una pagina dalla cache del browser potrebbe causare il client e il server per essere sincronizzati. Quadro di navigazione non facce tali problemi perché non ha tutte le cache sul lato server. Invece, il sentiero dei dati e navigazione stato, statale tutti si tengono nell'URL. Ciò significa, tuttavia, che un utente può cambiare questi valori modificando l'URL.

Rendendo MVC geloso

All'inizio ho dichiarato che il quadro di navigazione consente di creare codice di Web Form per rendere MVC geloso. Dopo tale affermazione audace potrebbe sentirsi un po' breve cambiato dall'applicazione indagine campione, perché ha probabilmente MVC tenendo il suo naso per evitare il soffio sgradevole di code-behind su di esso. Ma per favore non disperare; Questo era soltanto un'introduzione ai concetti fondamentali. Futuri articoli si concentrano sulla integrità architettonica, con particolare attenzione ai principi di prova e secca di unità.

Nella seconda rata creerò un campione con associazione a dati con codebehinds vuota e unità completa test di code coverage. Questa copertura prevede anche il codice alla navigazione, notoriamente difficile da provare in un'applicazione MVC.

Nella terza rata creerò una domanda sola pagina SEO-friendly. Utilizzerà il miglioramento progressivo, che impiegano ASP.NET AJAX quando JavaScript è abilitato e degradanti, con garbo, quando è disabilitato, con gli stessi metodi con associazione a dati utilizzati in entrambi gli scenari. Ancora una volta, questo è difficile da realizzare in un'applicazione MVC.

Se questo mette appetito e non vedo l'ora di provare alcune delle funzionalità più avanzate, accertarsi di scaricare il codice di esempio e documentazione completo di funzionalità da navigation.codeplex.com.

Graham Mendick è il più grande fan di Web Forms' e vuole mostrarlo possono essere solo come architettonicamente suoni come ASP.NET MVC. E ' autore di navigazione per ASP.Quadro NET Web Form, che egli ritiene — quando viene utilizzato con associazione dati — può infondere nuova vita nel Web Form.

Grazie all'esperto tecnica seguente per la revisione di questo articolo: Damian Edwards