Domanda

Come posso implementare il Post-Redirect-Get modello con ASP.NET?

Fare clic su un pulsante esegue alcune operazioni di elaborazione:

<asp:Button id="bbLaunch" OnCommand="bbLaunch_Click" />

Utente fa clic sul pulsante, il veicolo spaziale è lanciato, la pagina web si visualizza nuovamente.Se l'utente preme F5, si ottiene il messaggio di avviso:

enter image description here

La soluzione al problema è la Post-Redirect-Get modello.

Che cosa è il metodo con cui PRG può essere implementato in ASP.NET?


La domanda attorno ai centri di problemi di:

  • come è possibile che l' <asp:Button> eseguire un POST per un luogo che non è la sua forma originale?
  • qual è la ViewState quando si registra in un formato che non legge lo stato di visualizzazione.
  • qual è la ViewState quando si reindirizza a "reale" modulo web aspx?
  • è ViewState fondamentalmente incompatibile con ASP.net Post-Redirect-Get?
  • è ASP.net fondamentalmente incompatibile con Post-Redirect--Get?
  • come (cioèqual'e ' il codice) ti reindirizza al "reale" modulo web aspx?
  • come (cioècosa url) ti reindirizza al "reale" modulo web aspx?Una relazione in questione menziona Response.Redirect(Request.RawUrl);
  • quando (cioènel qual caso il gestore) non si reindirizza a "reale" modulo web aspx?
  • le domande relative a sollevare questioni di come è il modulo di inserimento dati.C'è l'implicazione che HTML forme non può essere utilizzato - e tutti i dati del modulo deve essere aggiunto alla stringa di query.È vero questo?Se è così, perché?Se no, perché? Può un browser metti i dati del modulo in una stringa di query?
  • una domanda correlata cita Server.Transfer.Utilizzando Server.Transfer è completamente sbagliato, e in nessun modo si risolve il Post-Redirect-Get problema (perché non c'è Redirect).Corretto?
  • che cosa modifica del codice deve avvenire nel aspx o aspx.cs file di supporto del PRG?Presumibilmente, almeno, il codice deve essere modificato post da qualche parte oltre MyPage.aspx.

In altre parole: Come si fa a fare Post-Redirect-entrare in ASP.net?

Nota:ASP.net (cioènon ASP.net MVC)

Vedi anche

È stato utile?

Soluzione

In genere si dovrebbe fare creando un modulo web aspx, che utilizza la querystring per segnalare il record per carico/processo.

Supponiamo di avere una pagina che ti permette di aggiornare alcuni dati del cliente:

http://www.mysite.com/customer.aspx

Sarebbe necessario caricare il modulo utilizzando un id in querystring:

http://www.mysite.com/customer.aspx?CustomerId=42

Nel codebehind si potrebbe avere qualcosa di simile a questo:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        int customerId = 0;
        if (!string.IsNullOrEmpty(Request.QueryString["CustomerId"]))
        {
            int.TryParse(Request.QueryString["CustomerId"], out customerId );
        }
        if (customerId == 0) 
        {
            //handle case when no valid customer id was passed in the qs here
        }
        else 
        {
            //load customer details, bind controls etc
            //make sure to handle the case when no customer was found using the id in the qs
        }
    }
}

Poi da qualche parte nella pagina, l'utente avrebbe un pulsante che consente di salvare le modifiche.Il pulsante dovrebbe avere un gestore OnClick nel codice sottostante:

protected void SaveClicked(object sender, EventArgs e)
{
    //save changes to database here

    //Redirect if all went well
    Response.Redirect("http://www.mysite.com/customer.aspx?CustomerId=" 
        + idOfSavedCustomer.ToString());
}

Che fondamentalmente dovrebbe essere.Il redirect causare il browser al rilascio di una nuova richiesta GET per l'url di Reindirizzamento(...).Verrà caricata la pagina, il if (!IsPostBack) verrà eseguito e inizializzare la pagina con i nuovi valori che hai appena salvato nel precedente post indietro.

Per tutto questo processo, il traffico tra il browser e il server sarebbe qualcosa di simile a questo:

Browser: GET http://www.mysite.com/customer.aspx?CustomerId=42
Server: 200 (send back some html)

Browser: POST http://www.mysite.com/customer.aspx?CustomerId=42 (post data sent in request)
Server: 302 (point to http://www.mysite.com/customer.aspx?CustomerId=42)

Browser: GET http://www.mysite.com/customer.aspx?CustomerId=42
Server: 200 (send html)

Nel mezzo passo, il server è fondamentalmente dicendo:

"Che la richiesta post che mi hai mandato, ho avuto a che fare con questo.Ora, si prega avuto questa pagina qui..."

Il fatto che l'url nel fatto riferimento alla stessa pagina non è importante.


Alcune riflessioni in risposta al tuo punto elenco di domande:

  • come si può eseguire un POST di un luogo che non è il suo forma originale?

Si può fare impostando il action attributo di forma, o è possibile impostare il PostBackUrl sul pulsante.

  • qual è il ViewState quando si registra un modulo che non leggere lo stato di visualizzazione.

Dipende.Se è sufficiente inviare il form ad un'altra pagina, è possibile utilizzare il <%@ PreviousPageType .../> direttiva per raccontare la "nuova" pagina in cui il post è venuto da.Questo simplyfy di lavoro con i dati pubblicati sulla nuova pagina.Vedere questo link per i dettagli.

  • qual è il ViewState quando si reindirizza a "reale" aspx modulo web?

Vista è stato inviato nel post di richiesta.Quando il reindirizzamento del browser caricherà una nuova pagina e creare un proprio viestate.

  • è ViewState fondamentalmente incompatibile con ASP.net Post-Redirect-Get?

Dipende da come la si guarda.Dopo il redirect alla nuova pagina non avrà accesso al viewstate della pagina prima.

  • è ASP.net fondamentalmente incompatibile con Post-Redirect--Get?

No.Vedere l'esempio di cui sopra.

  • come (cioèqual'e ' il codice) ti reindirizza al "reale" modulo web aspx?

Risposta.Redirect(url).Questo invierà una risposta al browser, dicendogli di fare una nuova richiesta get.

  • quando (cioènel qual caso il gestore) non si reindirizza a "reale" aspx modulo web?

Quando sono state eseguite tutte le opere necessarie per elaborare la richiesta post.

  • le domande relative a sollevare questioni di come il modulo di inserimento dati.C' è l'implicazione che i form HTML non può essere utilizzato - e tutti i dati del modulo deve essere aggiunto alla stringa di query.È vero questo?Se è così, perché?Se non, perché no?Può un browser metti i dati del modulo in una stringa di query?

Il reindirizzamento di una richiesta post non è ben supportato e probabilmente dovrebbe essere evitato.Esso può essere fatto (con alcuni browser) utilizzando la risposta http 307.Durante l'operazione, il server dice efficacemente il browser "Io non processo di post di richiesta, si prega di inviare a quest'altra pagina invece".

  • una domanda correlata cita Server.Il trasferimento.Utilizzo Di Server.Il trasferimento è completamente sbagliato, e in nessun modo si risolve il Post-Redirect-Get problema (perché non c'è nessun Redirect).Corretto?

Server.Trasferimento(...) è qualcosa che si sta svolgendo sul lato server.Il browser non è a conoscenza di esso.Fondamentalmente una pagina possibile utilizzare il Server.Trasferimento in modo da avere som altra pagina fare qualche elaborazione, e che la pagina sarà responsabile per l'invio di una risposta al browser.Ma il browser si pensa che sia stato l'originale pagina risposto.

  • che cosa modifica del codice deve avvenire in aspx o aspx.cs file di supporto PRG?Presumibilmente, almeno, il codice deve essere modificato il post da qualche parte oltre MyPage.aspx.

No, un normale post indietro può essere utilizzato.Il trucco è quello di avere uno (o alcuni) specifiche gestore di eventi(s) nella pagina che fa una Repsonse.Redirect dopo l'elaborazione dei dati pubblicati.

Altri suggerimenti

Q) come eseguire un POST di un luogo che non è la sua forma originale?

A) Con PRG, non POSTARE a una pagina diversa, è posta alla stessa pagina (vedi figura alla pagina di wikipedia è collegato.) Ma la risposta da quella pagina DEVE ESSERE un 30X risposta (in genere un 302.)

D) qual è il ViewState quando si registra in un formato che non legge lo stato di visualizzazione.

A) Lo stato di visualizzazione c'è quando si POSTA, ma non lo stato di visualizzazione di non essere lì per la nuova pagina che si sta facendo un GET.

D) qual è il ViewState quando si reindirizza a "reale" modulo web aspx?

A) Al di sopra, non c'è più lo stato di visualizzazione vengono reindirizzati alla pagina.

Q) ViewState è fondamentalmente incompatibile con ASP.net?

A) ViewState non è incompatibile con ASP.NET.È (quasi) inutile per la P/R/G per il rendering della pagina che vengono reindirizzate.

D) è ASP.net fondamentalmente incompatibile con Post-Redirect--Get?

A) No - ma non troppo si basano sull'utilizzo di una pagina e tenere tutto il tuo stato nel viewstate, come indicato sopra.Detto questo, ASP.MVC è di mappe molto meglio P/R/G

Q) come (cioèqual'e ' il codice) ti reindirizza al "reale" modulo web aspx?

A) Risposta.Redirect("new_page_you_are_redirecting_to.aspx") in bbLaunch_Click metodo di old_page_you_are_posting_from.aspx

Q) come (cioècosa url) ti reindirizza al "reale" modulo web aspx?Una relazione in questione menziona Risposta.Redirect(Richiesta.RawUrl);

A) Vedi sopra

D) quando (cioènel qual caso il gestore) non si reindirizza a "reale" modulo web aspx?

A) Dopo aver elaborato il tasto premere il tasto, vengono salvati i dati al DB (o di sessione, ecc), e prima di aver scritto nulla per il flusso di Risposta.

Q) le domande relative a sollevare questioni di come il modulo di inserimento dati.C'è l'implicazione che i form HTML non può essere utilizzato - e tutti i dati del modulo deve essere aggiunto alla stringa di query.È vero questo?

A) Senza la pressione del pulsante in ASP.NET WebForms verrà rinviata alla pagina.

Q) Se sì, perché?Se no, perché?

A) È più semplice di questo, è perché non.Imaging due pagine:first_page.asp e second_page.aspx.First_page.aspx ha il pulsante su di esso, insieme con altri ASP.NET controlli web, come caselle di testo, ecc che l'utente ha compilato.) Quando si preme il pulsante, un POST alla first_page.aspx.Dopo l'elaborazione dei dati, è probabile che all'interno di viewstate, anche se questo è svincolato), è possibile reindirizzare l'utente a second_page.aspx utilizzo di Risposta.redirect.Second_page.aspx in grado di visualizzare ciò che si desidera.Se avete voglia (o bisogno) per visualizzare l'interfaccia utente è simile a quello che era sul first_page.aspx, compresi i controlli e quali sono inseriti, si desidera memorizzare che nella sessione, cookie, URL, come querystring params, per impostare i controlli sul second_page.aspx.(Ma potrebbe non essere necessario per visualizzare nulla sul second_page.aspx che è simile a first_page.aspx - quindi non c'è alcuna regola generale qui.)

Q) un browser metti i dati del modulo in una stringa di query?

A) Sì, se si imposta il metodo per OTTENERE invece di POSTARE.Non è possibile sostituire WebForms per fare questo, e questo non è richiesto per il PRG

D) una domanda correlata cita Server.Il trasferimento.Utilizzo Di Server.Il trasferimento è completamente sbagliato, e in nessun modo si risolve il Post-Redirect-Get problema (perché non c'è nessun Redirect).Corretto?

A) Essenzialmente

Q) che la modifica del codice deve avvenire in aspx o aspx.cs file di supporto del PRG?Presumibilmente, almeno, il codice deve essere modificato il post da qualche parte oltre MyPage.aspx.

A) Il codice deve ancora post indietro (come sopra.) Ma poi Mypage.aspx dovrebbe re-indirizzare ad una pagina nuova nel gestore pulsante.

Il modello post-re-redita-get può essere utilizzato in forme web. Ho mostrato come questo può essere fatto convertendo l'applicazione MVC Nerddinner in moduli Web, http://navigationnerddinner.codeplex.com/ . Ho mantenuto i dettagli di navigazione esattamente gli stessi, quindi ci sono molti esempi del modello PRG.

Tuttavia, esiste un altro modo per evitare il problema F5/Aggiorna. Se avvolgi la tua pagina in un updatepanel (parte di ASP.NET AJAX), tutti i back di post verranno convertiti in richieste di pagine parziali. Ciò significa che quando viene premuto F5, aggiornerà solo la richiesta Get originale (dal momento che non ci sono stati post successivi) e quindi non otterrai l'avvertimento. (Nota, se JavaScript è disabilitato, verrà comunque visualizzato l'avvertimento).

I passaggi esattamente del reindirizzamento post ottengono sono questo:

Hai il modulo che completi i dati e dopo l'invio valido (post) li inserisci nel tuo database e fornisci loro un ID di conferma, quindi reindirizza l'utente alla pagina con questo ID di conferma come parametro URL utilizzato Come (get) dopo il reindirizzamento ogni F5-Refresh viene letto solo i dati e non inserirli di nuovo.

Il codice per l'inserto è diverso dal codice che mostra la conferma, puoi persino renderle diverse pagine: puoi creare la stessa pagina con caselle di testo solo lettura.

Il reindirizzamento è semplice Responce.Redirect funzione di ASP.NET

Dopo il post e la realizzazione del reindirizzamento L'unico Think che ti collega all'azione precedente è il codice di conferma (non ViewState)

Il meno di questo metodo è che in realtà non è riconoscere l'aggiornamento, è solo un passo in più che rende l'aggiornamento non inserendo di nuovo gli stessi dati, ma necessita di codice extra per i dati GET.

L'alternativa è riconoscere l'aggiornamento e non rendere il reindirizzamento. Riconoscere l'aggiornamento su Post Back è possibile evitare di inserire gli stessi dati con un singolo messaggio all'utente. Ci sono alcuni esempi su Internet per questo e ne ho implementati uno con successo.

Un esempio: http://www.codeproject.com/tips/319955/how-to-prevent-re-post-action-caused-by -pressing-b

Puoi invocare il Risposta.redirect metodo per andare in un'altra posizione.

Ci sono un paio di cose che vanno in questo.

  1. Impostare il azione attributo del modulo nella pagina principale (chiamiamolo LaunchForm.aspx) uguale all'URL della pagina "proxy" (Proxylaunchform.aspx).

    u003Cform id="form1" runat="server" action="ProxyLaunchForm.aspx" method="POST">

  2. (opzionale) Aggiungi un input nascosto con il nome redeRecTurl alla forma e valorizza l'URL che dice Proxylaunchform.aspx dove reindirizzare una volta terminato l'esecuzione del lancio (la parte R di PRG).

  3. Ora su Proxylaunchform.aspx, l'implementazione dovrebbe avvenire all'interno del Page_load Handler di eventi, perché ha accesso ai dati post -forma. Esegui il lancio qui.

  4. Successivamente (anche in Page_load), eseguire il reindirizzamento (utilizzando il redeRecTurl da #2 o semplicemente usando l'URL della pagina di riferimento):

    Risposta.redirect (request.params ["rediRecturl"] ?? request.urlreferrer.absoluteuri);

    C'è ancora la questione dello stato di vista. Penso che il modo più semplice per affrontare questo sia cambiare il modo in cui lo stato di vista viene persistito. Normalmente, viene salvato in un elemento di input nascosto sulla pagina e recuperato su Postback (che ovviamente significa che sarebbe perso dopo il reindirizzamento a causa della natura apolida di HTTP). Tuttavia, è possibile sovrascrivere i metodi utilizzati da ASP.NET e fargli utilizzare il Sessione Invece (in questo modo sarà ancora presente anche dopo l'azione proxy PRG). Quindi, finalmente ...

  5. In LaunchForm.aspx.cs, usa come sottoclasse di classe A Base Pagina che prevale il SavePagestaTopersisTenceMium e LoadPagestateFrompersisTenceMium Metodi per archiviarli/recuperarli dalla sessione, piuttosto che da un campo di modulo nascosto. Vedi sotto (e Ecco maggiori informazioni su come funziona.).

*

public class PersistViewStateToSession : Page
{
    protected override void SavePageStateToPersistenceMedium(object viewState)
    {
        // serialize the view state into a base-64 encoded string
        LosFormatter los = new LosFormatter();
        StringWriter writer = new StringWriter();
        los.Serialize(writer, viewState);
        // save the string to session
        Session["LaunchViewState"] = writer.ToString();
    }

    protected override object LoadPageStateFromPersistenceMedium()
    {
       if (!Session["LaunchViewState"] == null)
           return null;
       else
       {
          string sessionString = (string)Session["LaunchViewState"];
          // deserialize the string
          LosFormatter los = new LosFormatter();
          return los.Deserialize(viewStateString);
       }
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top