Inleiding tot ASP.NET webpagina's - Databasegegevens bijwerken

door Tom FitzMacken

Deze zelfstudie laat zien hoe u een bestaande databasevermelding bijwerkt (wijzigt) wanneer u ASP.NET Webpagina's (Razor) gebruikt. Hierbij wordt ervan uitgegaan dat u de reeks hebt voltooid via Het invoeren van gegevens met behulp van formulieren met behulp van ASP.NET webpagina's.

Wat u leert:

  • Hoe selecteer je een individuele record in de WebGrid helper?
  • Een enkele record lezen uit een database.
  • Een formulier vooraf laden met waarden uit de databaserecord.
  • Een bestaande record bijwerken in een database.
  • Informatie opslaan op de pagina zonder deze weer te geven.
  • Een verborgen veld gebruiken om informatie op te slaan.

Functies/technologieën besproken:

  • De WebGrid helper.
  • De SQL-opdracht Update .
  • De Database.Execute methode.
  • Verborgen velden (<input type="hidden">).

Wat je gaat bouwen

In de vorige zelfstudie hebt u geleerd hoe u een record toevoegt aan een database. Hier leert u hoe u een record kunt weergeven voor bewerking. Op de pagina Films werkt u de WebGrid helper bij zodat er een koppeling Bewerken naast elke film wordt weergegeven:

WebGrid-weergave met een koppeling 'Bewerken' voor elke film

Wanneer u op de koppeling Bewerken klikt, gaat u naar een andere pagina, waar de filmgegevens zich al in een formulier bevinden:

Filmpagina bewerken met film die moet worden bewerkt

U kunt een van de waarden wijzigen. Wanneer u de wijzigingen indient, werkt de code op de pagina de database bij en gaat u terug naar de filmvermelding.

Dit deel van het proces werkt bijna precies zoals de pagina AddMovie.cshtml die u in de vorige zelfstudie hebt gemaakt, zodat veel van deze zelfstudie bekend is.

Er zijn verschillende manieren waarop u een manier kunt implementeren om een afzonderlijke film te bewerken. De getoonde benadering is gekozen omdat het eenvoudig te implementeren en gemakkelijk te begrijpen is.

Om te beginnen werkt u de pagina Films bij zodat elke filmvermelding ook een koppeling Bewerken bevat.

Open het bestand Movies.cshtml .

Wijzig de WebGrid opmaak in de hoofdtekst van de pagina door een kolom toe te voegen. Dit is de gewijzigde opmaak:

@grid.GetHtml(
    tableStyle: "grid",
    headerStyle: "head",
    alternatingRowStyle: "alt",
    columns: grid.Columns(
        grid.Column(format: @<a href="~/EditMovie?id=@item.ID">Edit</a>),
        grid.Column("Title"),
        grid.Column("Genre"),
        grid.Column("Year")
    )
)

De nieuwe kolom is deze:

grid.Column(format: @<a href="~/EditMovie?id=@item.ID)">Edit</a>)

Het punt van deze kolom is om een koppeling (<a> element) weer te geven waarvan de tekst 'Bewerken' staat. We willen een link maken die er als volgt uitziet wanneer de pagina wordt uitgevoerd, met een andere id waarde voor elke film:

http://localhost:43097/EditMovie?id=7

Met deze koppeling wordt een pagina met de naam EditMovie aangeroepen en wordt de querytekenreeks ?id=7 aan die pagina doorgegeven.

De syntaxis voor de nieuwe kolom kan er iets complex uitzien, maar dat komt alleen doordat deze verschillende elementen samenvoegt. Elk afzonderlijk element is eenvoudig. Als u zich alleen op het <a> element richt, ziet u deze markeringen:

<a href="~/EditMovie?id=@item.ID)">Edit</a>

Achtergrondinformatie over de werking van het raster: in het raster worden rijen weergegeven, één voor elke databaserecord en worden kolommen weergegeven voor elk veld in de databaserecord. Terwijl elke rasterrij wordt samengesteld, bevat het item object de databaserecord (item) voor die rij. Deze rangschikking biedt u een manier in code om de gegevens voor die rij op te halen. Dit is wat u hier ziet: de expressie item.ID krijgt de id-waarde van het huidige database-item. U kunt een van de databasewaarden (titel, genre of jaar) op dezelfde manier verkrijgen met behulp item.Titlevan , item.Genreof item.Year.

De expressie "~/EditMovie?id=@item.ID combineert het in code vastgelegde deel van de doel-URL (~/EditMovie?id=) met deze dynamisch afgeleide id. (U hebt de ~ operator in de vorige zelfstudie gezien; het is een ASP.NET operator die de huidige website-root vertegenwoordigt.)

Het resultaat is dat dit deel van de markeringen in de kolom gewoon iets produceert als de volgende markeringen tijdens runtime:

href="/EditMovie?id=2"

Natuurlijk is de werkelijke waarde id voor elke rij anders.

Een aangepaste weergave maken voor een rasterkolom

Ga nu terug naar de rasterkolom. De drie kolommen die u oorspronkelijk in het raster had, bevatten alleen gegevenswaarden (titel, genre en jaar). U hebt deze weergave opgegeven door de naam van de databasekolom door te geven, grid.Column("Title")bijvoorbeeld.

Deze nieuwe Bewerk koppeling kolom is anders. In plaats van een kolomnaam op te geven, geeft u een format parameter door. Met deze parameter kunt u markeringen definiëren die de WebGrid helper samen met de item waarde weergeeft om de kolomgegevens vet of groen weer te geven of in elke gewenste indeling. Als u bijvoorbeeld wilt dat de titel vet wordt weergegeven, kunt u een kolom maken zoals in dit voorbeeld:

grid.Column(format:@<strong>@item.Title</strong>)

(De verschillende @ tekens die u in de format eigenschap ziet, markeren de overgang tussen markeringen en een codewaarde.)

Zodra u weet wat de format eigenschap is, is het gemakkelijker om te begrijpen hoe de nieuwe kolom Koppeling bewerken is samengesteld:

grid.Column(format: @<a href="~/EditMovie?id=@item.ID">Edit</a>),

De kolom bestaat alleen uit de markeringen waarmee de koppeling wordt weergegeven, plus enkele informatie (de id) die is geëxtraheerd uit de databaserecord voor de rij.

Aanbeveling

Benoemde parameters en positionele parameters voor een methode

Vaak wanneer u een methode hebt aangeroepen en parameters eraan hebt doorgegeven, hebt u gewoon de parameterwaarden vermeld, gescheiden door komma's. Hier volgen enkele voorbeelden:

db.Execute(insertCommand, title, genre, year)

Validation.RequireField("title", "You must enter a title")

We hebben het probleem niet vermeld toen u deze code voor het eerst zag, maar in elk geval geeft u parameters door aan de methoden in een specifieke volgorde, namelijk de volgorde waarin de parameters in die methode worden gedefinieerd. Voor db.Execute en Validation.RequireFields, als u de volgorde van de waarden die u doorgeeft verwart, krijgt u een foutbericht wanneer de pagina wordt uitgevoerd, of op zijn minst enkele vreemde resultaten. Het is duidelijk dat u de volgorde moet kennen om de parameters door te geven. (In WebMatrix kan IntelliSense u helpen bij het bepalen van de naam, het type en de volgorde van de parameters.)

Als alternatief voor het doorgeven van waarden op volgorde, kunt u benoemde parameters gebruiken. (Het doorgeven van parameters in volgorde wordt ook wel positionele parameters genoemd.) Voor benoemde parameters neemt u expliciet de naam van de parameter op bij het doorgeven van de waarde. In deze tutorials heeft u al een aantal keren benoemde parameters gebruikt. Voorbeeld:

var grid = new WebGrid(source: selectedData, defaultSort: "Genre", rowsPerPage:3)

en

@grid.GetHtml(
    tableStyle: "grid",
    headerStyle: "head",
    alternatingRowStyle: "alt",
    columns: grid.Columns(
       grid.Column("Title"),
       grid.Column("Genre"),
       grid.Column("Year")
    )
)

Benoemde parameters zijn handig voor een aantal situaties, met name wanneer een methode veel parameters gebruikt. Een is wanneer u slechts één of twee parameters wilt doorgeven, maar de waarden die u wilt doorgeven, behoren niet tot de eerste posities in de parameterlijst. Een andere situatie is wanneer u uw code beter leesbaar wilt maken door de parameters door te geven in de volgorde die het meest zinvol voor u is.

Als u benoemde parameters wilt gebruiken, moet u de namen van de parameters weten. WebMatrix IntelliSense kan u de namen laten zien , maar deze kunnen momenteel niet voor u worden ingevuld.

Het maken van de bewerkpagina

U kunt nu de EditMovie-pagina maken. Wanneer gebruikers op de koppeling Bewerken klikken, komen ze terecht op deze pagina.

Maak een pagina met de naam EditMovie.cshtml en vervang wat er in het bestand staat door de volgende markeringen:

<!DOCTYPE html>
<html>
  <head>
   <meta charset="utf-8" />
   <title>Edit a Movie</title>
    <style>
      .validation-summary-errors{
        border:2px dashed red;
        color:red;
        font-weight:bold;
        margin:12px;
      }
    </style>
  </head>
  <body>
    <h1>Edit a Movie</h1>
    @Html.ValidationSummary()
    <form method="post">
      <fieldset>
        <legend>Movie Information</legend>

        <p><label for="title">Title:</label>
           <input type="text" name="title" value="@title" /></p>

        <p><label for="genre">Genre:</label>
           <input type="text" name="genre" value="@genre" /></p>

        <p><label for="year">Year:</label>
           <input type="text" name="year" value="@year" /></p>

        <input type="hidden" name="movieid" value="@movieId" />

        <p><input type="submit" name="buttonSubmit" value="Submit Changes" /></p>
      </fieldset>
    </form>
  </body>
</html>

Deze markering en code zijn vergelijkbaar met wat u op de pagina AddMovie hebt. Er is een klein verschil in de tekst voor de knop Verzenden. Net als op de pagina AddMovie wordt een Html.ValidationSummary aanroep weergegeven die validatiefouten weergeeft als er een is. Deze keer laten we aanroepen naar Validation.Message weg, omdat fouten worden weergegeven in de validatie-samenvatting. Zoals vermeld in de vorige zelfstudie, kunt u de validatiesamenvatting en de afzonderlijke foutberichten in verschillende combinaties gebruiken.

U ziet nogmaals dat het method kenmerk van het <form> element is ingesteld op post. Net als bij de pagina AddMovie.cshtml brengt deze pagina wijzigingen aan in de database. Daarom moet dit formulier een POST bewerking uitvoeren. (Zie de zijbalk GET in de zelfstudie over HTML-formulieren voor meer informatie over het verschil tussen POST en bewerkingen.)

Zoals u in een eerdere zelfstudie hebt gezien, worden de value kenmerken van de tekstvakken ingesteld met Razor-code om ze vooraf te laden. Deze keer gebruikt u echter variabelen zoals title en genre voor die taak in plaats van Request.Form["title"]:

<input type="text" name="title" value="@title" />

Net als voorheen worden met deze markering de waarden van het tekstvak vooraf geladen met de filmwaarden. U ziet op een moment waarom het handig is om deze keer variabelen te gebruiken in plaats van het Request object te gebruiken.

Er is ook een <input type="hidden"> element op deze pagina. Met dit element wordt de film-id opgeslagen zonder deze zichtbaar te maken op de pagina. De id wordt in eerste instantie doorgegeven aan de pagina met behulp van een querytekenreekswaarde (?id=7 of vergelijkbaar in de URL). Door de id-waarde in een verborgen veld te plaatsen, kunt u ervoor zorgen dat deze beschikbaar is wanneer het formulier wordt verzonden, zelfs als u geen toegang meer hebt tot de oorspronkelijke URL waarmee de pagina is aangeroepen.

In tegenstelling tot de AddMovie-pagina heeft de code voor de EditMovie-pagina twee verschillende functies. De eerste functie is dat wanneer de pagina voor het eerst wordt weergegeven (en alleen dan), de code de film-id ophaalt uit de querytekenreeks. De code gebruikt vervolgens de id om de bijbehorende film uit de database te lezen en deze weer te geven (vooraf laden) in de tekstvakken.

De tweede functie is dat wanneer de gebruiker op de knop Wijzigingen verzenden klikt, de code de waarden van de tekstvakken moet lezen en valideren. De code moet ook het database-item bijwerken met de nieuwe waarden. Deze techniek is vergelijkbaar met het toevoegen van een record, zoals u in AddMovie hebt gezien.

Code toevoegen om één film te lezen

Als u de eerste functie wilt uitvoeren, voegt u deze code toe aan het begin van de pagina:

@{
    var title = "";
    var genre = "";
    var year = "";
    var movieId = "";

    if(!IsPost){
        if(!Request.QueryString["ID"].IsEmpty()){
            movieId = Request.QueryString["ID"];
            var db = Database.Open("WebPagesMovies");
            var dbCommand = "SELECT * FROM Movies WHERE ID = @0";
            var row = db.QuerySingle(dbCommand, movieId);
            title = row.Title;
            genre = row.Genre;
            year = row.Year;
        }
        else{
            Validation.AddFormError("No movie was selected.");
        }
    }
}

De meeste van deze code bevindt zich in een blok dat wordt gestart if(!IsPost). De ! operator betekent 'niet', dus de expressie betekent dat deze aanvraag geen post-inzending is. Dit is een indirecte manier om te zeggen of deze aanvraag de eerste keer is dat deze pagina wordt uitgevoerd. Zoals eerder vermeld, moet deze code alleen de eerste keer worden uitgevoerd dat de pagina wordt uitgevoerd. Als u de code niet tussen if(!IsPost) plaatst, wordt deze elke keer uitgevoerd wanneer de pagina wordt aangeroepen, of het nu de eerste keer is of als reactie op het klikken op een knop.

U ziet dat de code deze keer een else blok bevat. Zoals we hebben gezegd bij het introduceren if van blokken, wilt u soms alternatieve code uitvoeren als de voorwaarde die u test niet waar is. Dat is hier het geval. Als aan de voorwaarde is voldaan (dat wil zeggen, als de ID die aan de pagina is doorgegeven ok is), leest u een rij uit de database. Als de voorwaarde echter niet wordt gehaald, wordt het else blok uitgevoerd en stelt de code een foutbericht in.

Een waarde valideren die is doorgegeven aan de pagina

De code gebruikt Request.QueryString["id"] om de id op te halen die wordt doorgegeven aan de pagina. De code zorgt ervoor dat een waarde daadwerkelijk is doorgegeven voor de id. Als er geen waarde is doorgegeven, wordt met de code een validatiefout ingesteld.

Deze code toont een andere manier om informatie te valideren. In de vorige zelfstudie hebt u met de Validation helper gewerkt. U hebt velden geregistreerd om te valideren en ASP.NET automatisch de validatie uitgevoerd en fouten weergegeven met behulp van Html.ValidationMessage en Html.ValidationSummary. In dit geval valideert u echter niet echt gebruikersinvoer. In plaats daarvan valideert u een waarde die vanaf een andere locatie aan de pagina is doorgegeven. De Validation helper doet dat niet voor u.

Daarom controleert u zelf de waarde door deze te testen met if(!Request.QueryString["ID"].IsEmpty()). Als er een probleem is, kunt u de fout weergeven met behulp van Html.ValidationSummary, net als bij de Validation helper. Om dat te doen, roep Validation.AddFormError aan en geef deze een bericht om weer te geven. Validation.AddFormError is een ingebouwde methode waarmee u aangepaste berichten kunt definiëren die zijn gekoppeld aan het validatiesysteem waarmee u al bekend bent. (Verderop in deze zelfstudie bespreken we hoe u dit validatieproces wat robuuster maakt.)

Nadat u ervoor hebt gezorgd dat er een id voor de film is, leest de code de database, op zoek naar slechts één database-item. (Waarschijnlijk hebt u het algemene patroon voor databasebewerkingen opgemerkt: open de database, definieer een SQL-instructie en voer de instructie uit.) Deze keer bevat Selectde SQL-instructie WHERE ID = @0 . Omdat de id uniek is, kan slechts één record worden geretourneerd.

De query wordt uitgevoerd met behulp van db.QuerySingle (niet db.Query, zoals u hebt gebruikt voor de filmvermelding) en de code plaatst het resultaat in de row variabele. De naam row is willekeurig. U kunt de variabelen een willekeurige naam opgeven. De variabelen die bovenaan zijn geïnitialiseerd, worden vervolgens gevuld met de details van de film, zodat deze waarden in de tekstvakken kunnen worden weergegeven.

De bewerkingspagina testen (tot nu toe)

Als u de pagina wilt testen, voert u de pagina Films nu uit en klikt u op een koppeling Bewerken naast een film. U ziet de pagina EditMovie met de details die zijn ingevuld voor de film die u hebt geselecteerd:

Schermopname van de pagina Film bewerken met de film die moet worden bewerkt.

U ziet dat de URL van de pagina iets als ?id=10 (of een ander nummer) bevat. Tot nu toe hebt u getest dat koppelingen bewerken in de filmpagina werken, dat de pagina de id leest uit de querytekenreeks en dat de databasequery werkt om één filmrecord op te halen.

U kunt de filmgegevens wijzigen, maar er gebeurt niets wanneer u op Wijzigingen verzenden klikt.

Code toevoegen om de film bij te werken met de wijzigingen van de gebruiker

Voeg in het bestand EditMovie.cshtml de volgende code toe net binnen de sluitende accolade van het @ blok om de tweede functie te implementeren (wijzigingen opslaan). (Als u niet precies weet waar de code moet worden geplaatst, kunt u de volledige code bekijken voor de pagina Film bewerken die aan het einde van deze zelfstudie wordt weergegeven.)

if(IsPost){
    Validation.RequireField("title", "You must enter a title");
    Validation.RequireField("genre", "Genre is required");
    Validation.RequireField("year", "You haven't entered a year");
    Validation.RequireField("movieid", "No movie ID was submitted!");

    title = Request.Form["title"];
    genre = Request.Form["genre"];
    year = Request.Form["year"];
    movieId = Request.Form["movieId"];

    if(Validation.IsValid()){
        var db = Database.Open("WebPagesMovies");
        var updateCommand = "UPDATE Movies SET Title=@0, Genre=@1, Year=@2 WHERE Id=@3";
        db.Execute(updateCommand, title, genre, year, movieId);
        Response.Redirect("~/Movies");
   }
}

Deze markering en code zijn weer vergelijkbaar met de code in AddMovie. De code bevindt zich in een if(IsPost) blok, omdat deze code alleen wordt uitgevoerd wanneer de gebruiker op de knop Wijzigingen verzenden klikt, dat wil gezegd, wanneer (en alleen wanneer) het formulier is gepost. In dit geval gebruikt u geen test zoals if(IsPost && Validation.IsValid())— dat wil zeggen, u combineert beide tests niet met behulp van AND. Op deze pagina bepaalt u eerst of er een formulierinzending is (if(IsPost)) en registreert u alleen de velden voor validatie. Vervolgens kunt u de validatieresultaten (if(Validation.IsValid()) testen. De stroom is iets anders dan op de pagina AddMovie.cshtml , maar het effect is hetzelfde.

U krijgt de waarden van de tekstvakken met behulp van Request.Form["title"] en vergelijkbare code voor de andere <input> elementen. U ziet dat de code deze keer de film-id uit het verborgen veld (<input type="hidden">) haalt. Toen de pagina de eerste keer werd uitgevoerd, heeft de code de ID uit de query opgehaald. U krijgt de waarde uit het verborgen veld om ervoor te zorgen dat u de id krijgt van de film die oorspronkelijk werd weergegeven, voor het geval de queryreeks sindsdien is gewijzigd.

Het echt belangrijke verschil tussen de AddMovie-code en deze code is dat u in deze code de SQL-instructie Update gebruikt in plaats van de Insert Into instructie. In het volgende voorbeeld ziet u de syntaxis van de SQL-instructie Update :

UPDATE table SET col1="value", col2="value", col3="value" ... WHERE ID = value

U kunt kolommen in elke volgorde opgeven en u hoeft niet per se elke kolom bij te werken tijdens een Update bewerking. (U kunt de id zelf niet bijwerken, omdat de record hierdoor wordt opgeslagen als een nieuwe record en dat is niet toegestaan voor een Update bewerking.)

Opmerking

Belangrijk De Where component met de id is erg belangrijk, omdat de database weet welke databaserecord u wilt bijwerken. Als u de Where component hebt uitgeschakeld, wordt elke record in de database bijgewerkt. In de meeste gevallen zou dat een ramp zijn.

In de code worden de waarden die moeten worden bijgewerkt doorgegeven aan de SQL-instructie met behulp van tijdelijke aanduidingen. Om te herhalen wat we eerder hebben gezegd: gebruik om veiligheidsredenen alleen tijdelijke aanduidingen om waarden door te geven aan een SQL-instructie.

Nadat de code db.Execute heeft gebruikt om de instructie Update uit te voeren, wordt de gebruiker teruggeleid naar de vermeldingspagina, waar u de wijzigingen kunt zien.

Aanbeveling

Verschillende SQL-instructies, verschillende methoden

Mogelijk hebt u gemerkt dat u iets andere methoden gebruikt om verschillende SQL-instructies uit te voeren. Als u een Select query wilt uitvoeren die mogelijk meerdere records retourneert, gebruikt u de Query methode. Als u een Select query wilt uitvoeren die slechts één database-item retourneert, gebruikt u de QuerySingle methode. Als u opdrachten wilt uitvoeren die wijzigingen aanbrengen, maar die geen database-items retourneren, gebruikt u de Execute methode.

U moet verschillende methoden hebben omdat elk van deze verschillende resultaten retourneert, zoals u al hebt gezien in het verschil tussen Query en QuerySingle. (De Execute methode retourneert eigenlijk ook een waarde, namelijk het aantal databaserijen dat door de opdracht is beïnvloed, maar dat hebt u tot nu toe genegeerd.)

De methode kan natuurlijk Query slechts één databaserij retourneren. ASP.NET behandelt echter altijd de resultaten van de Query methode als een verzameling. Zelfs als de methode slechts één rij retourneert, moet u die ene rij uit de verzameling extraheren. In situaties waarin u weet dat u slechts één rij terugkrijgt, is het handiger om QuerySingle te gebruiken.

Er zijn enkele andere methoden waarmee specifieke typen databasebewerkingen worden uitgevoerd. U vindt een lijst met databasemethoden in de snelzoekgids voor de ASP.NET Webpagina's-API.

Validatie voor de id robuuster maken

De eerste keer dat de pagina wordt uitgevoerd, haalt u de film-id op uit de querytekenreeks, zodat u die film uit de database kunt ophalen. U hebt ervoor gezorgd dat er eigenlijk een waarde was om naar te zoeken, wat u hebt gedaan met behulp van deze code:

if(!IsPost){
    if(!Request.QueryString["ID"].IsEmpty()){
        // Etc.
    }
}

U hebt deze code gebruikt om ervoor te zorgen dat als een gebruiker naar de EditMovies-pagina komt zonder eerst een film op de pagina Films te selecteren, de pagina een gebruiksvriendelijk foutbericht zou weergeven. (Anders zien gebruikers een fout die ze waarschijnlijk alleen maar verwarren.)

Deze validatie is echter niet erg robuust. De pagina kan ook worden aangeroepen met deze fouten:

  • De id is geen getal. De pagina kan bijvoorbeeld worden aangeroepen met een URL zoals http://localhost:nnnnn/EditMovie?id=abc.
  • De id is een getal, maar verwijst naar een film die niet bestaat (bijvoorbeeld http://localhost:nnnnn/EditMovie?id=100934).

Als u wilt weten welke fouten het gevolg zijn van deze URL's, voert u de pagina Films uit. Selecteer een film die u wilt bewerken en wijzig vervolgens de URL van de EditMovie-pagina in een URL die een alfabetische id of de id van een niet-bestaande film bevat.

Wat moet je doen? De eerste oplossing is ervoor te zorgen dat niet alleen een ID aan de pagina wordt doorgegeven, maar dat het ID een geheel getal is. Wijzig de code voor de !IsPost test zodat deze er zo uitziet als dit voorbeeld:

if(!IsPost){
    if(!Request.QueryString["ID"].IsEmpty() && Request.QueryString["ID"].IsInt()) {
       // Etc.

U hebt een tweede voorwaarde toegevoegd aan de IsEmpty test, gekoppeld aan && (logische AND):

Request.QueryString["ID"].IsInt()

Misschien herinnert u zich nog uit de zelfstudie Inleiding tot ASP.NET Programmeren van webpagina's die methoden zoals AsBool een AsInt tekenreeks converteren naar een ander gegevenstype. De IsInt methode (en andere, zoals IsBool en IsDateTime) zijn vergelijkbaar. Ze testen echter alleen of u de tekenreeks kunt converteren zonder de conversie daadwerkelijk uit te voeren. Hier zegt u in feite of de waarde van de querytekenreeks kan worden geconverteerd naar een geheel getal ....

Het andere potentiële probleem is op zoek naar een film die niet bestaat. De code voor het ophalen van een film ziet er als volgt uit:

var row = db.QuerySingle(dbCommand, movieId);

Als u een movieId waarde doorgeeft aan de QuerySingle methode die niet overeenkomt met een werkelijke film, wordt er niets geretourneerd en worden de instructies die volgen (bijvoorbeeld title=row.Title) resulteren in fouten.

Nogmaals, er is een eenvoudige oplossing. Als de db.QuerySingle methode geen resultaten retourneert, is de row variabele null. U kunt dus controleren of de row variabele null is voordat u er waarden uit probeert op te halen. Met de volgende code wordt een if blok rond de instructies toegevoegd waarmee de waarden uit het row object worden opgehaald:

if(row != null) {
    title = row.Title;
    genre = row.Genre;
    year = row.Year;
}
else{
    Validation.AddFormError("No movie was found for that ID.");
}

Met deze twee extra validatietests wordt de pagina sterker beveiligd. De volledige code voor de !IsPost vertakking ziet er nu als volgt uit:

if(!IsPost){
    if(!Request.QueryString["ID"].IsEmpty() && Request.QueryString["ID"].IsInt()) {
        movieId = Request.QueryString["ID"];
        var db = Database.Open("WebPagesMovies");
        var dbCommand = "SELECT * FROM Movies WHERE ID = @0";
        var row = db.QuerySingle(dbCommand, movieId);

        if(row != null) {
            title = row.Title;
            genre = row.Genre;
            year = row.Year;
        }
        else {
            Validation.AddFormError("No movie was found for that ID.");
        }
    }
    else {
        Validation.AddFormError("No movie was selected.");
    }
}

We wijzen erop dat deze taak een goed gebruik is van een else blok. Als de tests niet worden doorstaan, worden foutberichten in de else blokken ingesteld.

Een laatste en nuttige informatie is het toevoegen van een koppeling naar de pagina Films . In de normale gang van zaken beginnen gebruikers op de pagina Films en klikken ze op de koppeling Bewerken. Dat brengt ze naar de EditMovie-pagina , waar ze de film kunnen bewerken en op de knop kunnen klikken. Nadat de code de wijziging heeft verwerkt, wordt deze teruggeleid naar de pagina Films .

Aan de andere kant:

  • De gebruiker kan besluiten niets te wijzigen.
  • De gebruiker heeft deze pagina mogelijk bereikt zonder eerst op een koppeling Bewerken op de pagina Films te klikken.

Hoe dan ook, u wilt het voor hen gemakkelijk maken om terug te keren naar de hoofdlijst. Het is een eenvoudige oplossing: voeg de volgende markeringen toe vlak na de afsluitende </form> tag in de markering:

<p><a href="~/Movies">Return to movie listing</a></p>

Deze markering gebruikt dezelfde syntaxis voor een <a> element dat u elders hebt gezien. De URL bevat ~, wat 'root van de website' betekent.

Het filmupdateproces testen

Nu kunt u testen. Voer de pagina Films uit en klik op Bewerken naast een film. Wanneer de pagina EditMovie wordt weergegeven, breng dan wijzigingen aan in de film en klik op Wijzigingen verzenden. Wanneer de filmvermelding wordt weergegeven, controleert u of uw wijzigingen worden weergegeven.

Als u wilt controleren of de validatie werkt, klikt u op Bewerken voor een andere film. Wanneer u op de EditMovie pagina bent, maak dan het Genre veld leeg (of het Year veld, of beide) en dien vervolgens uw wijzigingen in. U ziet een fout, zoals u zou verwachten:

Filmpagina bewerken met validatiefouten

Klik op de koppeling Terug naar filmvermelding om uw wijzigingen af te staan en terug te keren naar de pagina Films .

Volgende stap

In de volgende zelfstudie ziet u hoe u een filmrecord verwijdert.

@{
    var db = Database.Open("WebPagesMovies") ;
    var selectCommand = "SELECT * FROM Movies";
    var searchTerm = "";

    if(!Request.QueryString["searchGenre"].IsEmpty() ) {
        selectCommand = "SELECT * FROM Movies WHERE Genre = @0";
        searchTerm = Request.QueryString["searchGenre"];
    }

    if(!Request.QueryString["searchTitle"].IsEmpty() ) {
        selectCommand = "SELECT * FROM Movies WHERE Title LIKE @0";
        searchTerm = "%" + Request.QueryString["searchTitle"] + "%";
    }

    var selectedData = db.Query(selectCommand, searchTerm);
    var grid = new WebGrid(source: selectedData, defaultSort: "Genre", rowsPerPage:3);
}

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>Movies</title>
        <style type="text/css">
          .grid { margin: 4px; border-collapse: collapse; width: 600px; }
          .grid th, .grid td { border: 1px solid #C0C0C0; padding: 5px; }
          .head { background-color: #E8E8E8; font-weight: bold; color: #FFF; }
          .alt { background-color: #E8E8E8; color: #000; }
        </style>
    </head>
    <body>
        <h1>Movies</h1>
          <form method="get">
              <div>
                <label for="searchGenre">Genre to look for:</label>
                <input type="text" name="searchGenre" value="@Request.QueryString["searchGenre"]" />
                <input type="Submit" value="Search Genre" /><br/>
                (Leave blank to list all movies.)<br/>
                </div>

              <div>
                  <label for="SearchTitle">Movie title contains the following:</label>
                  <input type="text" name="searchTitle" value="@Request.QueryString["searchTitle"]" />
                  <input type="Submit" value="Search Title" /><br/>
                </div>
            </form>

        <div>
             @grid.GetHtml(
                tableStyle: "grid",
                headerStyle: "head",
                alternatingRowStyle: "alt",
                columns: grid.Columns(
                    grid.Column(format: @<a href="~/EditMovie?id=@item.ID">Edit</a>),
                    grid.Column("Title"),
                    grid.Column("Genre"),
                    grid.Column("Year")
                )
            )
        </div>
    <p>
        <a href="~/AddMovie">Add a movie</a>
    </p>
    </body>
</html>

Volledige paginalijst voor filmpagina bewerken

@{
    var title = "";
    var genre = "";
    var year = "";
    var movieId = "";

    if(!IsPost){
        if(!Request.QueryString["ID"].IsEmpty() && Request.QueryString["ID"].IsInt()) {
            movieId = Request.QueryString["ID"];
            var db = Database.Open("WebPagesMovies");
            var dbCommand = "SELECT * FROM Movies WHERE ID = @0";
            var row = db.QuerySingle(dbCommand, movieId);

            if(row != null) {
                title = row.Title;
                genre = row.Genre;
                year = row.Year;
            }
            else{
                Validation.AddFormError("No movie was selected.");
            }
        }
        else{
            Validation.AddFormError("No movie was selected.");
        }
    }

    if(IsPost){
        Validation.RequireField("title", "You must enter a title");
        Validation.RequireField("genre", "Genre is required");
        Validation.RequireField("year", "You haven't entered a year");
        Validation.RequireField("movieid", "No movie ID was submitted!");

        title = Request.Form["title"];
        genre = Request.Form["genre"];
        year = Request.Form["year"];
        movieId = Request.Form["movieId"];

        if(Validation.IsValid()){
            var db = Database.Open("WebPagesMovies");
            var updateCommand = "UPDATE Movies SET Title=@0, Genre=@1, Year=@2 WHERE Id=@3";
            db.Execute(updateCommand, title, genre, year, movieId);
            Response.Redirect("~/Movies");
        }
    }
}

<!DOCTYPE html>
<html>
  <head>
   <meta charset="utf-8" />
   <title>Edit a Movie</title>
    <style>
      .validation-summary-errors{
        border:2px dashed red;
        color:red;
        font-weight:bold;
        margin:12px;
      }
    </style>
  </head>
  <body>
    <h1>Edit a Movie</h1>
      @Html.ValidationSummary()
      <form method="post">
      <fieldset>
        <legend>Movie Information</legend>

        <p><label for="title">Title:</label>
           <input type="text" name="title" value="@title" /></p>

        <p><label for="genre">Genre:</label>
           <input type="text" name="genre" value="@genre" /></p>

        <p><label for="year">Year:</label>
           <input type="text" name="year" value="@year" /></p>

        <input type="hidden" name="movieid" value="@movieId" />

        <p><input type="submit" name="buttonSubmit" value="Submit Changes" /></p>
      </fieldset>
    </form>
    <p><a href="~/Movies">Return to movie listing</a></p>
  </body>
</html>

Aanvullende bronnen