Delen via


Deel 6, controllermethoden en weergaven in ASP.NET Core

Opmerking

Dit is niet de nieuwste versie van dit artikel. Zie de .NET 10-versie van dit artikel voor de huidige release.

Waarschuwing

Deze versie van ASP.NET Core wordt niet meer ondersteund. Zie het .NET- en .NET Core-ondersteuningsbeleid voor meer informatie. Zie de .NET 9-versie van dit artikel voor de huidige release.

Door Rick Anderson

We hebben een goed begin met de film-app, maar de presentatie is niet ideaal, bijvoorbeeld ReleaseDate moet twee woorden zijn.

Indexweergave: Releasedatum is één woord (geen spatie) en elke releasedatum van de film toont een tijd van 12:00 uur

Open het Models/Movie.cs bestand en voeg de gemarkeerde regels toe die hieronder worden weergegeven:

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MvcMovie.Models;

public class Movie
{
    public int Id { get; set; }
    public string? Title { get; set; }
    
    [Display(Name = "Release Date")]
    [DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }
    public string? Genre { get; set; }
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }
}

DataAnnotations worden uitgelegd in de volgende handleiding. Het kenmerk Weergave geeft aan wat moet worden weergegeven voor de naam van een veld (in dit geval 'Releasedatum' in plaats van 'ReleaseDatum'). Het kenmerk DataType geeft het type van de gegevens (Datum) op, zodat de tijdgegevens die zijn opgeslagen in het veld niet worden weergegeven.

Voer de toepassing uit en vernieuw de /Movies pagina met behulp van de bovenstaande gegevensaantekeningen. Omdat de weergavemarkering gebruikmaakt van de @Html.DisplayNameFor en @Html.DisplayFor methoden om de naam en waarde van de eigenschap weer te geven, worden in de bijgewerkte Index weergave alle velden weergegeven die correct zijn opgemaakt. Releasedatum is nu bijvoorbeeld twee woorden en de tijdgegevens worden niet meer weergegeven.

Indexweergave: Releasedatum is twee woorden en elke releasedatum van de film wordt weergegeven zonder de tijd

De [Column(TypeName = "decimal(18, 2)")] gegevensaantekening is vereist, zodat Entity Framework Core Price correct kan toewijzen aan valuta's in de database. Zie gegevenstypenvoor meer informatie.

Blader naar de Movies controller en houd de muisaanwijzer boven een koppeling Bewerken om de doel-URL weer te geven.

Een browservenster wordt weergegeven waarin de muis boven de koppeling Bewerken zweeft en een koppelings-URL https://localhost:5001/Movies/Edit/5 wordt getoond

De koppelingen Bewerken, Details en Verwijderen worden gegenereerd door de Core MVC Anchor Tag Helper in het Views/Movies/Index.cshtml bestand.

        <a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
        <a asp-action="Details" asp-route-id="@item.Id">Details</a> |
        <a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
    </td>
</tr>

Tag Helpers zorgen ervoor dat code aan de serverzijde kan deelnemen aan het maken en weergeven van HTML-elementen in Razor bestanden. In de bovenstaande code genereert de AnchorTagHelper html-kenmerkwaarde href dynamisch van de actiemethode controller en route-id. U gebruikt Bron weergeven vanuit uw favoriete browser of gebruik de ontwikkelhulpprogramma's om de gegenereerde markeringen te onderzoeken. Hieronder ziet u een deel van de gegenereerde HTML:

 <td>
    <a href="/Movies/Edit/4"> Edit </a> |
    <a href="/Movies/Details/4"> Details </a> |
    <a href="/Movies/Delete/4"> Delete </a>
</td>

Onthoud het formaat voor routering dat is ingesteld in het Program.cs bestand:

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

ASP.NET Core vertaalt https://localhost:5001/Movies/Edit/4 naar een verzoek aan de Edit actiemethode van de Movies controller met de parameter Id van 4. (Controllermethoden worden ook wel actiemethoden genoemd.)

Tag Helpers zijn een van de populairste nieuwe functies in ASP.NET Core. Zie Aanvullende bronnen voor meer informatie.

Open de Movies controller en bekijk de twee Edit actiemethoden. De volgende code toont de HTTP GET Edit methode, waarmee de film wordt opgehaald en het bewerkingsformulier wordt ingevuld dat door het Edit.cshtmlRazor bestand is gegenereerd.

// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie.FindAsync(id);
    if (movie == null)
    {
        return NotFound();
    }
    return View(movie);
}

De volgende code toont de methode HTTP POST Edit, die de geposte filmwaarden verwerkt.

// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
    if (id != movie.Id)
    {
        return NotFound();
    }

    if (ModelState.IsValid)
    {
        try
        {
            _context.Update(movie);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!MovieExists(movie.Id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToAction(nameof(Index));
    }
    return View(movie);
}

Het [Bind] kenmerk is één manier om te beschermen tegen over-posting. U moet alleen eigenschappen opnemen in het [Bind] kenmerk dat u wilt wijzigen. Zie Uw controller beschermen tegen overboeking voor meer informatie. ViewModels bieden een alternatieve methode om overboeking te voorkomen.

U ziet dat de tweede Edit actiemethode wordt voorafgegaan door het [HttpPost] kenmerk.

// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
    if (id != movie.Id)
    {
        return NotFound();
    }

    if (ModelState.IsValid)
    {
        try
        {
            _context.Update(movie);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!MovieExists(movie.Id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToAction(nameof(Index));
    }
    return View(movie);
}

Het HttpPost kenmerk geeft aan dat deze Edit methode alleenPOST voor aanvragen kan worden aangeroepen. U kunt het [HttpGet] kenmerk toepassen op de eerste bewerkingsmethode, maar dat is niet nodig omdat [HttpGet] dit de standaardinstelling is.

Het ValidateAntiForgeryToken kenmerk wordt gebruikt om vervalsing van een aanvraag te voorkomen en wordt gekoppeld aan een antiforgery-token dat is gegenereerd in het bewerkingsweergavebestand (Views/Movies/Edit.cshtml). Het bewerkingsweergavebestand genereert het antiforgery-token met de Helper voor formuliertags.

<form asp-action="Edit">

De Form Tag Helper genereert een verborgen antiforgery-token dat moet overeenkomen met het [ValidateAntiForgeryToken] gegenereerde antiforgery-token in de Edit methode van de Films-controller. Zie Cross-Site Request Forgery -aanvallen (XSRF/CSRF) voorkomen in ASP.NET Corevoor meer informatie.

De HttpGet Edit methode gebruikt de filmparameter ID , zoekt de film op met behulp van de Entity Framework-methode FindAsync en retourneert de geselecteerde film naar de bewerkingsweergave. Als een film niet kan worden gevonden, wordt NotFound (HTTP 404) geretourneerd.

// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie.FindAsync(id);
    if (movie == null)
    {
        return NotFound();
    }
    return View(movie);
}

Toen het scaffoldingsysteem de bewerkingsweergave maakte, onderzocht het de Movie-klasse en creëerde het code om <label> en <input>-elementen weer te geven voor elke eigenschap van de klasse. In het volgende voorbeeld ziet u de bewerkingsweergave die is gegenereerd door het Visual Studio-scaffolding-systeem:

@model MvcMovie.Models.Movie

@{
    ViewData["Title"] = "Edit";
}

<h1>Edit</h1>

<h4>Movie</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Edit">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <input type="hidden" asp-for="Id" />
            <div class="form-group">
                <label asp-for="Title" class="control-label"></label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="ReleaseDate" class="control-label"></label>
                <input asp-for="ReleaseDate" class="form-control" />
                <span asp-validation-for="ReleaseDate" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Genre" class="control-label"></label>
                <input asp-for="Genre" class="form-control" />
                <span asp-validation-for="Genre" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Price" class="control-label"></label>
                <input asp-for="Price" class="form-control" />
                <span asp-validation-for="Price" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Save" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

U ziet hoe de weergavesjabloon boven aan het bestand een @model MvcMovie.Models.Movie instructie bevat. @model MvcMovie.Models.Movie geeft aan dat de weergave verwacht dat het model voor de weergavesjabloon van het type Movieis.

De geveerde code maakt gebruik van verschillende Tag Helper-methoden om de HTML-opmaak te stroomlijnen. De Label Tag Helper geeft de naam van het veld ('Title', 'ReleaseDate', 'Genre' of 'Price') weer. De Helper voor invoertags geeft een HTML-element <input> weer. In de Helper voor validatietags worden validatieberichten weergegeven die aan die eigenschap zijn gekoppeld.

Voer de toepassing uit en navigeer naar de /Movies URL. Klik op een koppeling Bewerken . Bekijk de bron voor de pagina in de browser. De gegenereerde HTML voor het <form> element wordt hieronder weergegeven.

<form action="/Movies/Edit/7" method="post">
    <div class="form-horizontal">
        <h4>Movie</h4>
        <hr />
        <div class="text-danger" />
        <input type="hidden" data-val="true" data-val-required="The ID field is required." id="ID" name="ID" value="7" />
        <div class="form-group">
            <label class="control-label col-md-2" for="Genre" />
            <div class="col-md-10">
                <input class="form-control" type="text" id="Genre" name="Genre" value="Western" />
                <span class="text-danger field-validation-valid" data-valmsg-for="Genre" data-valmsg-replace="true"></span>
            </div>
        </div>
        <div class="form-group">
            <label class="control-label col-md-2" for="Price" />
            <div class="col-md-10">
                <input class="form-control" type="text" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="Price" name="Price" value="3.99" />
                <span class="text-danger field-validation-valid" data-valmsg-for="Price" data-valmsg-replace="true"></span>
            </div>
        </div>
        <!-- Markup removed for brevity -->
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
    <input name="__RequestVerificationToken" type="hidden" value="CfDJ8Inyxgp63fRFqUePGvuI5jGZsloJu1L7X9le1gy7NCIlSduCRx9jDQClrV9pOTTmqUyXnJBXhmrjcUVDJyDUMm7-MF_9rK8aAZdRdlOri7FmKVkRe_2v5LIHGKFcTjPrWPYnc9AdSbomkiOSaTEg7RU" />
</form>

De <input> elementen bevinden zich in een HTML <form> element waarvan action het kenmerk is ingesteld op posten op de /Movies/Edit/id URL. De formuliergegevens worden op de server geplaatst wanneer op de Save knop wordt geklikt. Op de laatste regel voor het afsluitende </form> element ziet u het verborgen XSRF-token dat is gegenereerd door de Helper voor formuliertags.

De POST-aanvraag verwerken

In de volgende lijst ziet u de [HttpPost] versie van de Edit actiemethode.

// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
    if (id != movie.Id)
    {
        return NotFound();
    }

    if (ModelState.IsValid)
    {
        try
        {
            _context.Update(movie);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!MovieExists(movie.Id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToAction(nameof(Index));
    }
    return View(movie);
}

Het [ValidateAntiForgeryToken] kenmerk valideert het verborgen XSRF-token dat is gegenereerd door de antiforgery-tokengenerator in de Helper voor formuliertags

Het modelbindingssysteem gebruikt de geplaatste formulierwaarden en maakt een Movie object dat wordt doorgegeven als de movie parameter. De ModelState.IsValid eigenschap controleert of de gegevens die in het formulier zijn ingediend, kunnen worden gebruikt om een Movie object te wijzigen (bewerken of bij te werken). Als de gegevens geldig zijn, worden deze opgeslagen. De bijgewerkte (bewerkte) filmgegevens worden opgeslagen in de database door de SaveChangesAsync methode van databasecontext aan te roepen. Nadat de gegevens zijn opgeslagen, wordt de gebruiker door de code omgeleid naar de Index actiemethode van de MoviesController klasse, waarin de filmverzameling wordt weergegeven, inclusief de zojuist aangebrachte wijzigingen.

Voordat het formulier op de server wordt geplaatst, controleert de clientvalidatie alle validatieregels op de velden. Als er validatiefouten zijn, wordt er een foutbericht weergegeven en wordt het formulier niet geplaatst. Als JavaScript is uitgeschakeld, hebt u geen validatie aan de clientzijde, maar detecteert de server de geplaatste waarden die niet geldig zijn en worden de formulierwaarden opnieuw weergegeven met foutberichten. Verderop in de zelfstudie bekijken we Modelvalidatie in meer detail. De Helper voor validatietags in de Views/Movies/Edit.cshtml weergavesjabloon zorgt ervoor dat de juiste foutberichten worden weergegeven.

Bewerkingsweergave: Een uitzondering voor een onjuiste prijswaarde van abc geeft aan dat de veldprijs een getal moet zijn. Een uitzondering voor een onjuiste waarde voor de releasedatum van xyz-statussen Geef een geldige datum op.

HttpGet Alle methoden in de filmcontroller volgen een vergelijkbaar patroon. Ze krijgen een filmobject (of lijst met objecten, in het geval van Index) en geven het object (model) door aan de weergave. De Create methode geeft een leeg filmobject door aan de Create weergave. Alle methoden die gegevens maken, bewerken, verwijderen of anderszins wijzigen, doen dit in de [HttpPost] overbelasting van de methode. Het wijzigen van gegevens in een HTTP GET methode is een beveiligingsrisico. Het wijzigen van gegevens in een HTTP GET methode schendt ook de best practices voor HTTP en het architectuurpatroon REST , waarmee wordt aangegeven dat GET-aanvragen de status van uw toepassing niet mogen wijzigen. Met andere woorden, het uitvoeren van een GET-bewerking moet een veilige bewerking zijn die geen bijwerkingen heeft en uw persistente gegevens niet wijzigt.

Aanvullende bronnen

We hebben een goed begin met de film-app, maar de presentatie is niet ideaal, bijvoorbeeld ReleaseDate moet twee woorden zijn.

Indexweergave: Releasedatum is één woord (geen spatie) en elke releasedatum van de film toont een tijd van 12:00 uur

Open het Models/Movie.cs bestand en voeg de gemarkeerde regels toe die hieronder worden weergegeven:

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MvcMovie.Models;

public class Movie
{
    public int Id { get; set; }
    public string? Title { get; set; }
    
    [Display(Name = "Release Date")]
    [DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }
    public string? Genre { get; set; }
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }
}

DataAnnotations worden uitgelegd in de volgende handleiding. Het kenmerk Weergave geeft aan wat moet worden weergegeven voor de naam van een veld (in dit geval 'Releasedatum' in plaats van 'ReleaseDatum'). Het kenmerk DataType geeft het type van de gegevens (Datum) op, zodat de tijdgegevens die zijn opgeslagen in het veld niet worden weergegeven.

De [Column(TypeName = "decimal(18, 2)")] gegevensaantekening is vereist, zodat Entity Framework Core Price correct kan toewijzen aan valuta's in de database. Zie gegevenstypenvoor meer informatie.

Blader naar de Movies controller en houd de muisaanwijzer boven een koppeling Bewerken om de doel-URL weer te geven.

Een browservenster wordt weergegeven waarin de muis boven de koppeling Bewerken zweeft en een koppelings-URL https://localhost:5001/Movies/Edit/5 wordt getoond

De koppelingen Bewerken, Details en Verwijderen worden gegenereerd door de Core MVC Anchor Tag Helper in het Views/Movies/Index.cshtml bestand.

        <a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
        <a asp-action="Details" asp-route-id="@item.Id">Details</a> |
        <a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
    </td>
</tr>

Tag Helpers zorgen ervoor dat code aan de serverzijde kan deelnemen aan het maken en weergeven van HTML-elementen in Razor bestanden. In de bovenstaande code genereert de AnchorTagHelper html-kenmerkwaarde href dynamisch van de actiemethode controller en route-id. U gebruikt Bron weergeven vanuit uw favoriete browser of gebruik de ontwikkelhulpprogramma's om de gegenereerde markeringen te onderzoeken. Hieronder ziet u een deel van de gegenereerde HTML:

 <td>
    <a href="/Movies/Edit/4"> Edit </a> |
    <a href="/Movies/Details/4"> Details </a> |
    <a href="/Movies/Delete/4"> Delete </a>
</td>

Onthoud het formaat voor routering dat is ingesteld in het Program.cs bestand:

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

ASP.NET Core vertaalt https://localhost:5001/Movies/Edit/4 naar een verzoek aan de Edit actiemethode van de Movies controller met de parameter Id van 4. (Controllermethoden worden ook wel actiemethoden genoemd.)

Tag Helpers zijn een van de populairste nieuwe functies in ASP.NET Core. Zie Aanvullende bronnen voor meer informatie.

Open de Movies controller en bekijk de twee Edit actiemethoden. De volgende code toont de HTTP GET Edit methode, waarmee de film wordt opgehaald en het bewerkingsformulier wordt ingevuld dat door het Edit.cshtmlRazor bestand is gegenereerd.

// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie.FindAsync(id);
    if (movie == null)
    {
        return NotFound();
    }
    return View(movie);
}

De volgende code toont de methode HTTP POST Edit, die de geposte filmwaarden verwerkt.

// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
    if (id != movie.Id)
    {
        return NotFound();
    }

    if (ModelState.IsValid)
    {
        try
        {
            _context.Update(movie);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!MovieExists(movie.Id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToAction(nameof(Index));
    }
    return View(movie);
}

Het [Bind] kenmerk is één manier om te beschermen tegen over-posting. U moet alleen eigenschappen opnemen in het [Bind] kenmerk dat u wilt wijzigen. Zie Uw controller beschermen tegen overboeking voor meer informatie. ViewModels bieden een alternatieve methode om overboeking te voorkomen.

U ziet dat de tweede Edit actiemethode wordt voorafgegaan door het [HttpPost] kenmerk.

// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
    if (id != movie.Id)
    {
        return NotFound();
    }

    if (ModelState.IsValid)
    {
        try
        {
            _context.Update(movie);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!MovieExists(movie.Id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToAction(nameof(Index));
    }
    return View(movie);
}

Het HttpPost kenmerk geeft aan dat deze Edit methode alleenPOST voor aanvragen kan worden aangeroepen. U kunt het [HttpGet] kenmerk toepassen op de eerste bewerkingsmethode, maar dat is niet nodig omdat [HttpGet] dit de standaardinstelling is.

Het ValidateAntiForgeryToken kenmerk wordt gebruikt om vervalsing van een aanvraag te voorkomen en wordt gekoppeld aan een antiforgery-token dat is gegenereerd in het bewerkingsweergavebestand (Views/Movies/Edit.cshtml). Het bewerkingsweergavebestand genereert het antiforgery-token met de Helper voor formuliertags.

<form asp-action="Edit">

De Form Tag Helper genereert een verborgen antiforgery-token dat moet overeenkomen met het [ValidateAntiForgeryToken] gegenereerde antiforgery-token in de Edit methode van de Films-controller. Zie Cross-Site Request Forgery -aanvallen (XSRF/CSRF) voorkomen in ASP.NET Corevoor meer informatie.

De HttpGet Edit methode gebruikt de filmparameter ID , zoekt de film op met behulp van de Entity Framework-methode FindAsync en retourneert de geselecteerde film naar de bewerkingsweergave. Als een film niet kan worden gevonden, wordt NotFound (HTTP 404) geretourneerd.

// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie.FindAsync(id);
    if (movie == null)
    {
        return NotFound();
    }
    return View(movie);
}

Toen het scaffoldingsysteem de bewerkingsweergave maakte, onderzocht het de Movie-klasse en creëerde het code om <label> en <input>-elementen weer te geven voor elke eigenschap van de klasse. In het volgende voorbeeld ziet u de bewerkingsweergave die is gegenereerd door het Visual Studio-scaffolding-systeem:

@model MvcMovie.Models.Movie

@{
    ViewData["Title"] = "Edit";
}

<h1>Edit</h1>

<h4>Movie</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Edit">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <input type="hidden" asp-for="Id" />
            <div class="form-group">
                <label asp-for="Title" class="control-label"></label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="ReleaseDate" class="control-label"></label>
                <input asp-for="ReleaseDate" class="form-control" />
                <span asp-validation-for="ReleaseDate" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Genre" class="control-label"></label>
                <input asp-for="Genre" class="form-control" />
                <span asp-validation-for="Genre" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Price" class="control-label"></label>
                <input asp-for="Price" class="form-control" />
                <span asp-validation-for="Price" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Save" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

U ziet hoe de weergavesjabloon boven aan het bestand een @model MvcMovie.Models.Movie instructie bevat. @model MvcMovie.Models.Movie geeft aan dat de weergave verwacht dat het model voor de weergavesjabloon van het type Movieis.

De geveerde code maakt gebruik van verschillende Tag Helper-methoden om de HTML-opmaak te stroomlijnen. De Label Tag Helper geeft de naam van het veld ('Title', 'ReleaseDate', 'Genre' of 'Price') weer. De Helper voor invoertags geeft een HTML-element <input> weer. In de Helper voor validatietags worden validatieberichten weergegeven die aan die eigenschap zijn gekoppeld.

Voer de toepassing uit en navigeer naar de /Movies URL. Klik op een koppeling Bewerken . Bekijk de bron voor de pagina in de browser. De gegenereerde HTML voor het <form> element wordt hieronder weergegeven.

<form action="/Movies/Edit/7" method="post">
    <div class="form-horizontal">
        <h4>Movie</h4>
        <hr />
        <div class="text-danger" />
        <input type="hidden" data-val="true" data-val-required="The ID field is required." id="ID" name="ID" value="7" />
        <div class="form-group">
            <label class="control-label col-md-2" for="Genre" />
            <div class="col-md-10">
                <input class="form-control" type="text" id="Genre" name="Genre" value="Western" />
                <span class="text-danger field-validation-valid" data-valmsg-for="Genre" data-valmsg-replace="true"></span>
            </div>
        </div>
        <div class="form-group">
            <label class="control-label col-md-2" for="Price" />
            <div class="col-md-10">
                <input class="form-control" type="text" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="Price" name="Price" value="3.99" />
                <span class="text-danger field-validation-valid" data-valmsg-for="Price" data-valmsg-replace="true"></span>
            </div>
        </div>
        <!-- Markup removed for brevity -->
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
    <input name="__RequestVerificationToken" type="hidden" value="CfDJ8Inyxgp63fRFqUePGvuI5jGZsloJu1L7X9le1gy7NCIlSduCRx9jDQClrV9pOTTmqUyXnJBXhmrjcUVDJyDUMm7-MF_9rK8aAZdRdlOri7FmKVkRe_2v5LIHGKFcTjPrWPYnc9AdSbomkiOSaTEg7RU" />
</form>

De <input> elementen bevinden zich in een HTML <form> element waarvan action het kenmerk is ingesteld op posten op de /Movies/Edit/id URL. De formuliergegevens worden op de server geplaatst wanneer op de Save knop wordt geklikt. Op de laatste regel voor het afsluitende </form> element ziet u het verborgen XSRF-token dat is gegenereerd door de Helper voor formuliertags.

De POST-aanvraag verwerken

In de volgende lijst ziet u de [HttpPost] versie van de Edit actiemethode.

// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
    if (id != movie.Id)
    {
        return NotFound();
    }

    if (ModelState.IsValid)
    {
        try
        {
            _context.Update(movie);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!MovieExists(movie.Id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToAction(nameof(Index));
    }
    return View(movie);
}

Het [ValidateAntiForgeryToken] kenmerk valideert het verborgen XSRF-token dat is gegenereerd door de antiforgery-tokengenerator in de Helper voor formuliertags

Het modelbindingssysteem gebruikt de geplaatste formulierwaarden en maakt een Movie object dat wordt doorgegeven als de movie parameter. De ModelState.IsValid eigenschap controleert of de gegevens die in het formulier zijn ingediend, kunnen worden gebruikt om een Movie object te wijzigen (bewerken of bij te werken). Als de gegevens geldig zijn, worden deze opgeslagen. De bijgewerkte (bewerkte) filmgegevens worden opgeslagen in de database door de SaveChangesAsync methode van databasecontext aan te roepen. Nadat de gegevens zijn opgeslagen, wordt de gebruiker door de code omgeleid naar de Index actiemethode van de MoviesController klasse, waarin de filmverzameling wordt weergegeven, inclusief de zojuist aangebrachte wijzigingen.

Voordat het formulier op de server wordt geplaatst, controleert de clientvalidatie alle validatieregels op de velden. Als er validatiefouten zijn, wordt er een foutbericht weergegeven en wordt het formulier niet geplaatst. Als JavaScript is uitgeschakeld, hebt u geen validatie aan de clientzijde, maar detecteert de server de geplaatste waarden die niet geldig zijn en worden de formulierwaarden opnieuw weergegeven met foutberichten. Verderop in de zelfstudie bekijken we Modelvalidatie in meer detail. De Helper voor validatietags in de Views/Movies/Edit.cshtml weergavesjabloon zorgt ervoor dat de juiste foutberichten worden weergegeven.

Bewerkingsweergave: Een uitzondering voor een onjuiste prijswaarde van abc geeft aan dat de veldprijs een getal moet zijn. Een uitzondering voor een onjuiste waarde voor de releasedatum van xyz-statussen Geef een geldige datum op.

HttpGet Alle methoden in de filmcontroller volgen een vergelijkbaar patroon. Ze krijgen een filmobject (of lijst met objecten, in het geval van Index) en geven het object (model) door aan de weergave. De Create methode geeft een leeg filmobject door aan de Create weergave. Alle methoden die gegevens maken, bewerken, verwijderen of anderszins wijzigen, doen dit in de [HttpPost] overbelasting van de methode. Het wijzigen van gegevens in een HTTP GET methode is een beveiligingsrisico. Het wijzigen van gegevens in een HTTP GET methode schendt ook de best practices voor HTTP en het architectuurpatroon REST , waarmee wordt aangegeven dat GET-aanvragen de status van uw toepassing niet mogen wijzigen. Met andere woorden, het uitvoeren van een GET-bewerking moet een veilige bewerking zijn die geen bijwerkingen heeft en uw persistente gegevens niet wijzigt.

Aanvullende bronnen

We hebben een goed begin met de film-app, maar de presentatie is niet ideaal, bijvoorbeeld ReleaseDate moet twee woorden zijn.

Indexweergave: Releasedatum is één woord (geen spatie) en elke releasedatum van de film toont een tijd van 12:00 uur

Open het Models/Movie.cs bestand en voeg de gemarkeerde regels toe die hieronder worden weergegeven:

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MvcMovie.Models;

public class Movie
{
    public int Id { get; set; }
    public string? Title { get; set; }
    
    [Display(Name = "Release Date")]
    [DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }
    public string? Genre { get; set; }
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }
}

DataAnnotations worden uitgelegd in de volgende handleiding. Het kenmerk Weergave geeft aan wat moet worden weergegeven voor de naam van een veld (in dit geval 'Releasedatum' in plaats van 'ReleaseDatum'). Het kenmerk DataType geeft het type van de gegevens (Datum) op, zodat de tijdgegevens die zijn opgeslagen in het veld niet worden weergegeven.

De [Column(TypeName = "decimal(18, 2)")] gegevensaantekening is vereist, zodat Entity Framework Core Price correct kan toewijzen aan valuta's in de database. Zie gegevenstypenvoor meer informatie.

Blader naar de Movies controller en houd de muisaanwijzer boven een koppeling Bewerken om de doel-URL weer te geven.

Een browservenster wordt weergegeven waarin de muis boven de koppeling Bewerken zweeft en een koppelings-URL https://localhost:5001/Movies/Edit/5 wordt getoond

De koppelingen Bewerken, Details en Verwijderen worden gegenereerd door de Core MVC Anchor Tag Helper in het Views/Movies/Index.cshtml bestand.

        <a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
        <a asp-action="Details" asp-route-id="@item.Id">Details</a> |
        <a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
    </td>
</tr>

Tag Helpers zorgen ervoor dat code aan de serverzijde kan deelnemen aan het maken en weergeven van HTML-elementen in Razor bestanden. In de bovenstaande code genereert de AnchorTagHelper html-kenmerkwaarde href dynamisch van de actiemethode controller en route-id. U gebruikt Bron weergeven vanuit uw favoriete browser of gebruik de ontwikkelhulpprogramma's om de gegenereerde markeringen te onderzoeken. Hieronder ziet u een deel van de gegenereerde HTML:

 <td>
    <a href="/Movies/Edit/4"> Edit </a> |
    <a href="/Movies/Details/4"> Details </a> |
    <a href="/Movies/Delete/4"> Delete </a>
</td>

Onthoud het formaat voor routering dat is ingesteld in het Program.cs bestand:

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

ASP.NET Core vertaalt https://localhost:5001/Movies/Edit/4 naar een verzoek aan de Edit actiemethode van de Movies controller met de parameter Id van 4. (Controllermethoden worden ook wel actiemethoden genoemd.)

Tag Helpers zijn een van de populairste nieuwe functies in ASP.NET Core. Zie Aanvullende bronnen voor meer informatie.

Open de Movies controller en bekijk de twee Edit actiemethoden. De volgende code toont de HTTP GET Edit methode, waarmee de film wordt opgehaald en het bewerkingsformulier wordt ingevuld dat door het Edit.cshtmlRazor bestand is gegenereerd.

// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie.FindAsync(id);
    if (movie == null)
    {
        return NotFound();
    }
    return View(movie);
}

De volgende code toont de methode HTTP POST Edit, die de geposte filmwaarden verwerkt.

// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
    if (id != movie.Id)
    {
        return NotFound();
    }

    if (ModelState.IsValid)
    {
        try
        {
            _context.Update(movie);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!MovieExists(movie.Id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToAction(nameof(Index));
    }
    return View(movie);
}

Het [Bind] kenmerk is één manier om te beschermen tegen over-posting. U moet alleen eigenschappen opnemen in het [Bind] kenmerk dat u wilt wijzigen. Zie Uw controller beschermen tegen overboeking voor meer informatie. ViewModels bieden een alternatieve methode om overboeking te voorkomen.

U ziet dat de tweede Edit actiemethode wordt voorafgegaan door het [HttpPost] kenmerk.

// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
    if (id != movie.Id)
    {
        return NotFound();
    }

    if (ModelState.IsValid)
    {
        try
        {
            _context.Update(movie);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!MovieExists(movie.Id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToAction(nameof(Index));
    }
    return View(movie);
}

Het HttpPost kenmerk geeft aan dat deze Edit methode alleenPOST voor aanvragen kan worden aangeroepen. U kunt het [HttpGet] kenmerk toepassen op de eerste bewerkingsmethode, maar dat is niet nodig omdat [HttpGet] dit de standaardinstelling is.

Het ValidateAntiForgeryToken kenmerk wordt gebruikt om vervalsing van een aanvraag te voorkomen en wordt gekoppeld aan een antiforgery-token dat is gegenereerd in het bewerkingsweergavebestand (Views/Movies/Edit.cshtml). Het bewerkingsweergavebestand genereert het antiforgery-token met de Helper voor formuliertags.

<form asp-action="Edit">

De Form Tag Helper genereert een verborgen antiforgery-token dat moet overeenkomen met het [ValidateAntiForgeryToken] gegenereerde antiforgery-token in de Edit methode van de Films-controller. Zie Cross-Site Request Forgery -aanvallen (XSRF/CSRF) voorkomen in ASP.NET Corevoor meer informatie.

De HttpGet Edit methode gebruikt de filmparameter ID , zoekt de film op met behulp van de Entity Framework-methode FindAsync en retourneert de geselecteerde film naar de bewerkingsweergave. Als een film niet kan worden gevonden, wordt NotFound (HTTP 404) geretourneerd.

// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie.FindAsync(id);
    if (movie == null)
    {
        return NotFound();
    }
    return View(movie);
}

Toen het scaffoldingsysteem de bewerkingsweergave maakte, onderzocht het de Movie-klasse en creëerde het code om <label> en <input>-elementen weer te geven voor elke eigenschap van de klasse. In het volgende voorbeeld ziet u de bewerkingsweergave die is gegenereerd door het Visual Studio-scaffolding-systeem:

@model MvcMovie.Models.Movie

@{
    ViewData["Title"] = "Edit";
}

<h1>Edit</h1>

<h4>Movie</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Edit">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <input type="hidden" asp-for="Id" />
            <div class="form-group">
                <label asp-for="Title" class="control-label"></label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="ReleaseDate" class="control-label"></label>
                <input asp-for="ReleaseDate" class="form-control" />
                <span asp-validation-for="ReleaseDate" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Genre" class="control-label"></label>
                <input asp-for="Genre" class="form-control" />
                <span asp-validation-for="Genre" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Price" class="control-label"></label>
                <input asp-for="Price" class="form-control" />
                <span asp-validation-for="Price" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Save" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

U ziet hoe de weergavesjabloon boven aan het bestand een @model MvcMovie.Models.Movie instructie bevat. @model MvcMovie.Models.Movie geeft aan dat de weergave verwacht dat het model voor de weergavesjabloon van het type Movieis.

De geveerde code maakt gebruik van verschillende Tag Helper-methoden om de HTML-opmaak te stroomlijnen. De Label Tag Helper geeft de naam van het veld ('Title', 'ReleaseDate', 'Genre' of 'Price') weer. De Helper voor invoertags geeft een HTML-element <input> weer. In de Helper voor validatietags worden validatieberichten weergegeven die aan die eigenschap zijn gekoppeld.

Voer de toepassing uit en navigeer naar de /Movies URL. Klik op een koppeling Bewerken . Bekijk de bron voor de pagina in de browser. De gegenereerde HTML voor het <form> element wordt hieronder weergegeven.

<form action="/Movies/Edit/7" method="post">
    <div class="form-horizontal">
        <h4>Movie</h4>
        <hr />
        <div class="text-danger" />
        <input type="hidden" data-val="true" data-val-required="The ID field is required." id="ID" name="ID" value="7" />
        <div class="form-group">
            <label class="control-label col-md-2" for="Genre" />
            <div class="col-md-10">
                <input class="form-control" type="text" id="Genre" name="Genre" value="Western" />
                <span class="text-danger field-validation-valid" data-valmsg-for="Genre" data-valmsg-replace="true"></span>
            </div>
        </div>
        <div class="form-group">
            <label class="control-label col-md-2" for="Price" />
            <div class="col-md-10">
                <input class="form-control" type="text" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="Price" name="Price" value="3.99" />
                <span class="text-danger field-validation-valid" data-valmsg-for="Price" data-valmsg-replace="true"></span>
            </div>
        </div>
        <!-- Markup removed for brevity -->
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
    <input name="__RequestVerificationToken" type="hidden" value="CfDJ8Inyxgp63fRFqUePGvuI5jGZsloJu1L7X9le1gy7NCIlSduCRx9jDQClrV9pOTTmqUyXnJBXhmrjcUVDJyDUMm7-MF_9rK8aAZdRdlOri7FmKVkRe_2v5LIHGKFcTjPrWPYnc9AdSbomkiOSaTEg7RU" />
</form>

De <input> elementen bevinden zich in een HTML <form> element waarvan action het kenmerk is ingesteld op posten op de /Movies/Edit/id URL. De formuliergegevens worden op de server geplaatst wanneer op de Save knop wordt geklikt. Op de laatste regel voor het afsluitende </form> element ziet u het verborgen XSRF-token dat is gegenereerd door de Helper voor formuliertags.

De POST-aanvraag verwerken

In de volgende lijst ziet u de [HttpPost] versie van de Edit actiemethode.

// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
    if (id != movie.Id)
    {
        return NotFound();
    }

    if (ModelState.IsValid)
    {
        try
        {
            _context.Update(movie);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!MovieExists(movie.Id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToAction(nameof(Index));
    }
    return View(movie);
}

Het [ValidateAntiForgeryToken] kenmerk valideert het verborgen XSRF-token dat is gegenereerd door de antiforgery-tokengenerator in de Helper voor formuliertags

Het modelbindingssysteem gebruikt de geplaatste formulierwaarden en maakt een Movie object dat wordt doorgegeven als de movie parameter. De ModelState.IsValid eigenschap controleert of de gegevens die in het formulier zijn ingediend, kunnen worden gebruikt om een Movie object te wijzigen (bewerken of bij te werken). Als de gegevens geldig zijn, worden deze opgeslagen. De bijgewerkte (bewerkte) filmgegevens worden opgeslagen in de database door de SaveChangesAsync methode van databasecontext aan te roepen. Nadat de gegevens zijn opgeslagen, wordt de gebruiker door de code omgeleid naar de Index actiemethode van de MoviesController klasse, waarin de filmverzameling wordt weergegeven, inclusief de zojuist aangebrachte wijzigingen.

Voordat het formulier op de server wordt geplaatst, controleert de clientvalidatie alle validatieregels op de velden. Als er validatiefouten zijn, wordt er een foutbericht weergegeven en wordt het formulier niet geplaatst. Als JavaScript is uitgeschakeld, hebt u geen validatie aan de clientzijde, maar detecteert de server de geplaatste waarden die niet geldig zijn en worden de formulierwaarden opnieuw weergegeven met foutberichten. Verderop in de zelfstudie bekijken we Modelvalidatie in meer detail. De Helper voor validatietags in de Views/Movies/Edit.cshtml weergavesjabloon zorgt ervoor dat de juiste foutberichten worden weergegeven.

Bewerkingsweergave: Een uitzondering voor een onjuiste prijswaarde van abc geeft aan dat de veldprijs een getal moet zijn. Een uitzondering voor een onjuiste waarde voor de releasedatum van xyz-statussen Geef een geldige datum op.

HttpGet Alle methoden in de filmcontroller volgen een vergelijkbaar patroon. Ze krijgen een filmobject (of lijst met objecten, in het geval van Index) en geven het object (model) door aan de weergave. De Create methode geeft een leeg filmobject door aan de Create weergave. Alle methoden die gegevens maken, bewerken, verwijderen of anderszins wijzigen, doen dit in de [HttpPost] overbelasting van de methode. Het wijzigen van gegevens in een HTTP GET methode is een beveiligingsrisico. Het wijzigen van gegevens in een HTTP GET methode schendt ook de best practices voor HTTP en het architectuurpatroon REST , waarmee wordt aangegeven dat GET-aanvragen de status van uw toepassing niet mogen wijzigen. Met andere woorden, het uitvoeren van een GET-bewerking moet een veilige bewerking zijn die geen bijwerkingen heeft en uw persistente gegevens niet wijzigt.

Aanvullende bronnen

We hebben een goed begin met de film-app, maar de presentatie is niet ideaal, bijvoorbeeld ReleaseDate moet twee woorden zijn.

Indexweergave: Releasedatum is één woord (geen spatie) en elke releasedatum van de film toont een tijd van 12:00 uur

Open het Models/Movie.cs bestand en voeg de gemarkeerde regels toe die hieronder worden weergegeven:

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MvcMovie.Models
{
    public class Movie
    {
        public int Id { get; set; }
        public string? Title { get; set; }

        [Display(Name = "Release Date")]
        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }
        public string? Genre { get; set; }

        [Column(TypeName = "decimal(18, 2)")]
        public decimal Price { get; set; }
    }
}

DataAnnotations worden uitgelegd in de volgende handleiding. Het kenmerk Weergave geeft aan wat moet worden weergegeven voor de naam van een veld (in dit geval 'Releasedatum' in plaats van 'ReleaseDatum'). Het kenmerk DataType geeft het type van de gegevens (Datum) op, zodat de tijdgegevens die zijn opgeslagen in het veld niet worden weergegeven.

De [Column(TypeName = "decimal(18, 2)")] gegevensaantekening is vereist, zodat Entity Framework Core Price correct kan toewijzen aan valuta's in de database. Zie gegevenstypenvoor meer informatie.

Blader naar de Movies controller en houd de muisaanwijzer boven een koppeling Bewerken om de doel-URL weer te geven.

Een browservenster wordt weergegeven waarin de muis boven de koppeling Bewerken zweeft en een koppelings-URL https://localhost:5001/Movies/Edit/5 wordt getoond

De koppelingen Bewerken, Details en Verwijderen worden gegenereerd door de Core MVC Anchor Tag Helper in het Views/Movies/Index.cshtml bestand.

        <a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
        <a asp-action="Details" asp-route-id="@item.Id">Details</a> |
        <a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
    </td>
</tr>

Tag Helpers zorgen ervoor dat code aan de serverzijde kan deelnemen aan het maken en weergeven van HTML-elementen in Razor bestanden. In de bovenstaande code genereert de AnchorTagHelper html-kenmerkwaarde href dynamisch van de actiemethode controller en route-id. U gebruikt Bron weergeven vanuit uw favoriete browser of gebruik de ontwikkelhulpprogramma's om de gegenereerde markeringen te onderzoeken. Hieronder ziet u een deel van de gegenereerde HTML:

 <td>
    <a href="/Movies/Edit/4"> Edit </a> |
    <a href="/Movies/Details/4"> Details </a> |
    <a href="/Movies/Delete/4"> Delete </a>
</td>

Onthoud het formaat voor routering dat is ingesteld in het Program.cs bestand:

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

ASP.NET Core vertaalt https://localhost:5001/Movies/Edit/4 naar een verzoek aan de Edit actiemethode van de Movies controller met de parameter Id van 4. (Controllermethoden worden ook wel actiemethoden genoemd.)

Tag Helpers zijn een populaire functie in ASP.NET Core. Zie Aanvullende bronnen voor meer informatie.

Open de Movies controller en bekijk de twee Edit actiemethoden. De volgende code toont de HTTP GET Edit methode, waarmee de film wordt opgehaald en het bewerkingsformulier wordt ingevuld dat door het Edit.cshtmlRazor bestand is gegenereerd.

// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie.FindAsync(id);
    if (movie == null)
    {
        return NotFound();
    }
    return View(movie);
}

De volgende code toont de methode HTTP POST Edit, die de geposte filmwaarden verwerkt.

// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
    if (id != movie.Id)
    {
        return NotFound();
    }

    if (ModelState.IsValid)
    {
        try
        {
            _context.Update(movie);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!MovieExists(movie.Id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToAction(nameof(Index));
    }
    return View(movie);
}

Het [Bind] kenmerk is één manier om te beschermen tegen over-posting. U moet alleen eigenschappen opnemen in het [Bind] kenmerk dat u wilt wijzigen. Zie Uw controller beschermen tegen overboeking voor meer informatie. ViewModels bieden een alternatieve methode om overboeking te voorkomen.

U ziet dat de tweede Edit actiemethode wordt voorafgegaan door het [HttpPost] kenmerk.

// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
    if (id != movie.Id)
    {
        return NotFound();
    }

    if (ModelState.IsValid)
    {
        try
        {
            _context.Update(movie);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!MovieExists(movie.Id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToAction(nameof(Index));
    }
    return View(movie);
}

Het HttpPost kenmerk geeft aan dat deze Edit methode alleenPOST voor aanvragen kan worden aangeroepen. U kunt het [HttpGet] kenmerk toepassen op de eerste bewerkingsmethode, maar dat is niet nodig omdat [HttpGet] dit de standaardinstelling is.

Het ValidateAntiForgeryToken kenmerk wordt gebruikt om vervalsing van een aanvraag te voorkomen en wordt gekoppeld aan een antiforgery-token dat is gegenereerd in het bewerkingsweergavebestand (Views/Movies/Edit.cshtml). Het bewerkingsweergavebestand genereert het antiforgery-token met de Helper voor formuliertags.

<form asp-action="Edit">

De Form Tag Helper genereert een verborgen antiforgery-token dat moet overeenkomen met het [ValidateAntiForgeryToken] gegenereerde antiforgery-token in de Edit methode van de Films-controller. Zie Cross-Site Request Forgery -aanvallen (XSRF/CSRF) voorkomen in ASP.NET Corevoor meer informatie.

De HttpGet Edit methode gebruikt de filmparameter ID , zoekt de film op met behulp van de Entity Framework-methode FindAsync en retourneert de geselecteerde film naar de bewerkingsweergave. Als een film niet kan worden gevonden, wordt NotFound (HTTP 404) geretourneerd.

// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie.FindAsync(id);
    if (movie == null)
    {
        return NotFound();
    }
    return View(movie);
}

Toen het scaffoldingsysteem de bewerkingsweergave maakte, onderzocht het de Movie-klasse en creëerde het code om <label> en <input>-elementen weer te geven voor elke eigenschap van de klasse. In het volgende voorbeeld ziet u de bewerkingsweergave die is gegenereerd door het Visual Studio-scaffolding-systeem:

@model MvcMovie.Models.Movie

@{
    ViewData["Title"] = "Edit";
}

<h1>Edit</h1>

<h4>Movie</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Edit">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <input type="hidden" asp-for="Id" />
            <div class="form-group">
                <label asp-for="Title" class="control-label"></label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="ReleaseDate" class="control-label"></label>
                <input asp-for="ReleaseDate" class="form-control" />
                <span asp-validation-for="ReleaseDate" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Genre" class="control-label"></label>
                <input asp-for="Genre" class="form-control" />
                <span asp-validation-for="Genre" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Price" class="control-label"></label>
                <input asp-for="Price" class="form-control" />
                <span asp-validation-for="Price" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Save" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

U ziet hoe de weergavesjabloon boven aan het bestand een @model MvcMovie.Models.Movie instructie bevat. @model MvcMovie.Models.Movie geeft aan dat de weergave verwacht dat het model voor de weergavesjabloon van het type Movieis.

De geveerde code maakt gebruik van verschillende Tag Helper-methoden om de HTML-opmaak te stroomlijnen. De Label Tag Helper geeft de naam van het veld ('Title', 'ReleaseDate', 'Genre' of 'Price') weer. De Helper voor invoertags geeft een HTML-element <input> weer. In de Helper voor validatietags worden validatieberichten weergegeven die aan die eigenschap zijn gekoppeld.

Voer de toepassing uit en navigeer naar de /Movies URL. Klik op een koppeling Bewerken . Bekijk de bron voor de pagina in de browser. De gegenereerde HTML voor het <form> element wordt hieronder weergegeven.

<form action="/Movies/Edit/7" method="post">
    <div class="form-horizontal">
        <h4>Movie</h4>
        <hr />
        <div class="text-danger" />
        <input type="hidden" data-val="true" data-val-required="The ID field is required." id="ID" name="ID" value="7" />
        <div class="form-group">
            <label class="control-label col-md-2" for="Genre" />
            <div class="col-md-10">
                <input class="form-control" type="text" id="Genre" name="Genre" value="Western" />
                <span class="text-danger field-validation-valid" data-valmsg-for="Genre" data-valmsg-replace="true"></span>
            </div>
        </div>
        <div class="form-group">
            <label class="control-label col-md-2" for="Price" />
            <div class="col-md-10">
                <input class="form-control" type="text" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="Price" name="Price" value="3.99" />
                <span class="text-danger field-validation-valid" data-valmsg-for="Price" data-valmsg-replace="true"></span>
            </div>
        </div>
        <!-- Markup removed for brevity -->
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
    <input name="__RequestVerificationToken" type="hidden" value="CfDJ8Inyxgp63fRFqUePGvuI5jGZsloJu1L7X9le1gy7NCIlSduCRx9jDQClrV9pOTTmqUyXnJBXhmrjcUVDJyDUMm7-MF_9rK8aAZdRdlOri7FmKVkRe_2v5LIHGKFcTjPrWPYnc9AdSbomkiOSaTEg7RU" />
</form>

De <input> elementen bevinden zich in een HTML <form> element waarvan action het kenmerk is ingesteld op posten op de /Movies/Edit/id URL. De formuliergegevens worden op de server geplaatst wanneer op de Save knop wordt geklikt. Op de laatste regel voor het afsluitende </form> element ziet u het verborgen XSRF-token dat is gegenereerd door de Helper voor formuliertags.

De POST-aanvraag verwerken

In de volgende lijst ziet u de [HttpPost] versie van de Edit actiemethode.

// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
    if (id != movie.Id)
    {
        return NotFound();
    }

    if (ModelState.IsValid)
    {
        try
        {
            _context.Update(movie);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!MovieExists(movie.Id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToAction(nameof(Index));
    }
    return View(movie);
}

Het [ValidateAntiForgeryToken] kenmerk valideert het verborgen XSRF-token dat is gegenereerd door de antiforgery-tokengenerator in de Helper voor formuliertags

Het modelbindingssysteem gebruikt de geplaatste formulierwaarden en maakt een Movie object dat wordt doorgegeven als de movie parameter. De ModelState.IsValid eigenschap controleert of de gegevens die in het formulier zijn ingediend, kunnen worden gebruikt om een Movie object te wijzigen (bewerken of bij te werken). Als de gegevens geldig zijn, worden deze opgeslagen. De bijgewerkte (bewerkte) filmgegevens worden opgeslagen in de database door de SaveChangesAsync methode van databasecontext aan te roepen. Nadat de gegevens zijn opgeslagen, wordt de gebruiker door de code omgeleid naar de Index actiemethode van de MoviesController klasse, waarin de filmverzameling wordt weergegeven, inclusief de zojuist aangebrachte wijzigingen.

Voordat het formulier op de server wordt geplaatst, controleert de clientvalidatie alle validatieregels op de velden. Als er validatiefouten zijn, wordt er een foutbericht weergegeven en wordt het formulier niet geplaatst. Als JavaScript is uitgeschakeld, hebt u geen validatie aan de clientzijde, maar detecteert de server de geplaatste waarden die niet geldig zijn en worden de formulierwaarden opnieuw weergegeven met foutberichten. Verderop in de zelfstudie bekijken we Modelvalidatie in meer detail. De Helper voor validatietags in de Views/Movies/Edit.cshtml weergavesjabloon zorgt ervoor dat de juiste foutberichten worden weergegeven.

Bewerkingsweergave: Een uitzondering voor een onjuiste prijswaarde van abc geeft aan dat de veldprijs een getal moet zijn. Een uitzondering voor een onjuiste waarde voor de releasedatum van xyz-statussen Geef een geldige datum op.

HttpGet Alle methoden in de filmcontroller volgen een vergelijkbaar patroon. Ze krijgen een filmobject (of lijst met objecten, in het geval van Index) en geven het object (model) door aan de weergave. De Create methode geeft een leeg filmobject door aan de Create weergave. Alle methoden die gegevens maken, bewerken, verwijderen of anderszins wijzigen, doen dit in de [HttpPost] overbelasting van de methode. Het wijzigen van gegevens in een HTTP GET methode is een beveiligingsrisico. Het wijzigen van gegevens in een HTTP GET methode schendt ook de best practices voor HTTP en het architectuurpatroon REST , waarmee wordt aangegeven dat GET-aanvragen de status van uw toepassing niet mogen wijzigen. Met andere woorden, het uitvoeren van een GET-bewerking moet een veilige bewerking zijn die geen bijwerkingen heeft en uw persistente gegevens niet wijzigt.

Aanvullende bronnen

We hebben een goed begin met de film-app, maar de presentatie is niet ideaal, bijvoorbeeld ReleaseDate moet twee woorden zijn.

Indexweergave: Releasedatum is één woord (geen spatie) en elke releasedatum van de film toont een tijd van 12:00 uur

Open het Models/Movie.cs bestand en voeg de gemarkeerde regels toe die hieronder worden weergegeven:

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MvcMovie.Models
{
    public class Movie
    {
        public int Id { get; set; }
        public string Title { get; set; }

        [Display(Name = "Release Date")]
        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; }

        [Column(TypeName = "decimal(18, 2)")]
        public decimal Price { get; set; }
    }
}

In de volgende zelfstudie behandelen we DataAnnotations . Het kenmerk Weergave geeft aan wat moet worden weergegeven voor de naam van een veld (in dit geval 'Releasedatum' in plaats van 'ReleaseDatum'). Het kenmerk DataType geeft het type van de gegevens (Datum) op, zodat de tijdgegevens die zijn opgeslagen in het veld niet worden weergegeven.

De [Column(TypeName = "decimal(18, 2)")] gegevensaantekening is vereist, zodat Entity Framework Core Price correct kan toewijzen aan valuta's in de database. Zie gegevenstypenvoor meer informatie.

Blader naar de Movies controller en houd de muisaanwijzer boven een koppeling Bewerken om de doel-URL weer te geven.

Een browservenster wordt weergegeven waarin de muis boven de koppeling Bewerken zweeft en een koppelings-URL https://localhost:5001/Movies/Edit/5 wordt getoond

De koppelingen Bewerken, Details en Verwijderen worden gegenereerd door de Core MVC Anchor Tag Helper in het Views/Movies/Index.cshtml bestand.

        <a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
        <a asp-action="Details" asp-route-id="@item.ID">Details</a> |
        <a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
    </td>
</tr>

Tag Helpers zorgen ervoor dat code aan de serverzijde kan deelnemen aan het maken en weergeven van HTML-elementen in Razor bestanden. In de bovenstaande code genereert de AnchorTagHelper html-kenmerkwaarde href dynamisch van de actiemethode controller en route-id. U gebruikt Bron weergeven vanuit uw favoriete browser of gebruik de ontwikkelhulpprogramma's om de gegenereerde markeringen te onderzoeken. Hieronder ziet u een deel van de gegenereerde HTML:

 <td>
    <a href="/Movies/Edit/4"> Edit </a> |
    <a href="/Movies/Details/4"> Details </a> |
    <a href="/Movies/Delete/4"> Delete </a>
</td>

Onthoud het formaat voor routering dat is ingesteld in het Startup.cs bestand:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
});

ASP.NET Core vertaalt https://localhost:5001/Movies/Edit/4 naar een verzoek aan de Edit actiemethode van de Movies controller met de parameter Id van 4. (Controllermethoden worden ook wel actiemethoden genoemd.)

Zie Aanvullende bronnen voor meer informatie over Tag Helpers.

Open de Movies controller en bekijk de twee Edit actiemethoden. De volgende code toont de HTTP GET Edit methode, waarmee de film wordt opgehaald en het bewerkingsformulier wordt ingevuld dat door het Edit.cshtmlRazor bestand is gegenereerd.

// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie.FindAsync(id);
    if (movie == null)
    {
        return NotFound();
    }
    return View(movie);
}

De volgende code toont de methode HTTP POST Edit, die de geposte filmwaarden verwerkt.

// POST: Movies/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for 
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
    if (id != movie.ID)
    {
        return NotFound();
    }

    if (ModelState.IsValid)
    {
        try
        {
            _context.Update(movie);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!MovieExists(movie.ID))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToAction("Index");
    }
    return View(movie);
}

Het [Bind] kenmerk is één manier om te beschermen tegen over-posting. U moet alleen eigenschappen opnemen in het [Bind] kenmerk dat u wilt wijzigen. Zie Uw controller beschermen tegen overboeking voor meer informatie. ViewModels bieden een alternatieve methode om overboeking te voorkomen.

U ziet dat de tweede Edit actiemethode wordt voorafgegaan door het [HttpPost] kenmerk.

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
    if (id != movie.ID)
    {
        return NotFound();
    }

    if (ModelState.IsValid)
    {
        try
        {
            _context.Update(movie);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!MovieExists(movie.ID))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToAction(nameof(Index));
    }
    return View(movie);
}

Het HttpPost kenmerk geeft aan dat deze Edit methode alleenPOST voor aanvragen kan worden aangeroepen. U kunt het [HttpGet] kenmerk toepassen op de eerste bewerkingsmethode, maar dat is niet nodig omdat [HttpGet] dit de standaardinstelling is.

Het ValidateAntiForgeryToken kenmerk wordt gebruikt om vervalsing van een aanvraag te voorkomen en wordt gekoppeld aan een antiforgery-token dat is gegenereerd in het bewerkingsweergavebestand (Views/Movies/Edit.cshtml). Het bewerkingsweergavebestand genereert het antiforgery-token met de Helper voor formuliertags.

<form asp-action="Edit">

De Form Tag Helper genereert een verborgen antiforgery-token dat moet overeenkomen met het [ValidateAntiForgeryToken] gegenereerde antiforgery-token in de Edit methode van de Films-controller. Zie Cross-Site Request Forgery -aanvallen (XSRF/CSRF) voorkomen in ASP.NET Corevoor meer informatie.

De HttpGet Edit methode gebruikt de filmparameter ID , zoekt de film op met behulp van de Entity Framework-methode FindAsync en retourneert de geselecteerde film naar de bewerkingsweergave. Als een film niet kan worden gevonden, wordt NotFound (HTTP 404) geretourneerd.

// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie.FindAsync(id);
    if (movie == null)
    {
        return NotFound();
    }
    return View(movie);
}

Toen het scaffoldingsysteem de bewerkingsweergave maakte, onderzocht het de Movie-klasse en creëerde het code om <label> en <input>-elementen weer te geven voor elke eigenschap van de klasse. In het volgende voorbeeld ziet u de bewerkingsweergave die is gegenereerd door het Visual Studio-scaffolding-systeem:

@model MvcMovie.Models.Movie

@{
    ViewData["Title"] = "Edit";
}

<h1>Edit</h1>

<h4>Movie</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Edit">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <input type="hidden" asp-for="Id" />
            <div class="form-group">
                <label asp-for="Title" class="control-label"></label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="ReleaseDate" class="control-label"></label>
                <input asp-for="ReleaseDate" class="form-control" />
                <span asp-validation-for="ReleaseDate" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Genre" class="control-label"></label>
                <input asp-for="Genre" class="form-control" />
                <span asp-validation-for="Genre" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Price" class="control-label"></label>
                <input asp-for="Price" class="form-control" />
                <span asp-validation-for="Price" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Save" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

U ziet hoe de weergavesjabloon boven aan het bestand een @model MvcMovie.Models.Movie instructie bevat. @model MvcMovie.Models.Movie geeft aan dat de weergave verwacht dat het model voor de weergavesjabloon van het type Movieis.

De geveerde code maakt gebruik van verschillende Tag Helper-methoden om de HTML-opmaak te stroomlijnen. De Label Tag Helper geeft de naam van het veld ('Title', 'ReleaseDate', 'Genre' of 'Price') weer. De Helper voor invoertags geeft een HTML-element <input> weer. In de Helper voor validatietags worden validatieberichten weergegeven die aan die eigenschap zijn gekoppeld.

Voer de toepassing uit en navigeer naar de /Movies URL. Klik op een koppeling Bewerken . Bekijk de bron voor de pagina in de browser. De gegenereerde HTML voor het <form> element wordt hieronder weergegeven.

<form action="/Movies/Edit/7" method="post">
    <div class="form-horizontal">
        <h4>Movie</h4>
        <hr />
        <div class="text-danger" />
        <input type="hidden" data-val="true" data-val-required="The ID field is required." id="ID" name="ID" value="7" />
        <div class="form-group">
            <label class="control-label col-md-2" for="Genre" />
            <div class="col-md-10">
                <input class="form-control" type="text" id="Genre" name="Genre" value="Western" />
                <span class="text-danger field-validation-valid" data-valmsg-for="Genre" data-valmsg-replace="true"></span>
            </div>
        </div>
        <div class="form-group">
            <label class="control-label col-md-2" for="Price" />
            <div class="col-md-10">
                <input class="form-control" type="text" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="Price" name="Price" value="3.99" />
                <span class="text-danger field-validation-valid" data-valmsg-for="Price" data-valmsg-replace="true"></span>
            </div>
        </div>
        <!-- Markup removed for brevity -->
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
    <input name="__RequestVerificationToken" type="hidden" value="CfDJ8Inyxgp63fRFqUePGvuI5jGZsloJu1L7X9le1gy7NCIlSduCRx9jDQClrV9pOTTmqUyXnJBXhmrjcUVDJyDUMm7-MF_9rK8aAZdRdlOri7FmKVkRe_2v5LIHGKFcTjPrWPYnc9AdSbomkiOSaTEg7RU" />
</form>

De <input> elementen bevinden zich in een HTML <form> element waarvan action het kenmerk is ingesteld op posten op de /Movies/Edit/id URL. De formuliergegevens worden op de server geplaatst wanneer op de Save knop wordt geklikt. Op de laatste regel voor het afsluitende </form> element ziet u het verborgen XSRF-token dat is gegenereerd door de Helper voor formuliertags.

De POST-aanvraag verwerken

In de volgende lijst ziet u de [HttpPost] versie van de Edit actiemethode.

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
    if (id != movie.ID)
    {
        return NotFound();
    }

    if (ModelState.IsValid)
    {
        try
        {
            _context.Update(movie);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!MovieExists(movie.ID))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToAction(nameof(Index));
    }
    return View(movie);
}

Het [ValidateAntiForgeryToken] kenmerk valideert het verborgen XSRF-token dat is gegenereerd door de antiforgery-tokengenerator in de Helper voor formuliertags

Het modelbindingssysteem gebruikt de geplaatste formulierwaarden en maakt een Movie object dat wordt doorgegeven als de movie parameter. De ModelState.IsValid eigenschap controleert of de gegevens die in het formulier zijn ingediend, kunnen worden gebruikt om een Movie object te wijzigen (bewerken of bij te werken). Als de gegevens geldig zijn, worden deze opgeslagen. De bijgewerkte (bewerkte) filmgegevens worden opgeslagen in de database door de SaveChangesAsync methode van databasecontext aan te roepen. Nadat de gegevens zijn opgeslagen, wordt de gebruiker door de code omgeleid naar de Index actiemethode van de MoviesController klasse, waarin de filmverzameling wordt weergegeven, inclusief de zojuist aangebrachte wijzigingen.

Voordat het formulier op de server wordt geplaatst, controleert de clientvalidatie alle validatieregels op de velden. Als er validatiefouten zijn, wordt er een foutbericht weergegeven en wordt het formulier niet geplaatst. Als JavaScript is uitgeschakeld, hebt u geen validatie aan de clientzijde, maar detecteert de server de geplaatste waarden die niet geldig zijn en worden de formulierwaarden opnieuw weergegeven met foutberichten. Verderop in de zelfstudie bekijken we Modelvalidatie in meer detail. De Helper voor validatietags in de Views/Movies/Edit.cshtml weergavesjabloon zorgt ervoor dat de juiste foutberichten worden weergegeven.

Bewerkingsweergave: Een uitzondering voor een onjuiste prijswaarde van abc geeft aan dat de veldprijs een getal moet zijn. Een uitzondering voor een onjuiste waarde voor de releasedatum van xyz-statussen Geef een geldige datum op.

HttpGet Alle methoden in de filmcontroller volgen een vergelijkbaar patroon. Ze krijgen een filmobject (of lijst met objecten, in het geval van Index) en geven het object (model) door aan de weergave. De Create methode geeft een leeg filmobject door aan de Create weergave. Alle methoden die gegevens maken, bewerken, verwijderen of anderszins wijzigen, doen dit in de [HttpPost] overbelasting van de methode. Het wijzigen van gegevens in een HTTP GET methode is een beveiligingsrisico. Het wijzigen van gegevens in een HTTP GET methode schendt ook de best practices voor HTTP en het architectuurpatroon REST , waarmee wordt aangegeven dat GET-aanvragen de status van uw toepassing niet mogen wijzigen. Met andere woorden, het uitvoeren van een GET-bewerking moet een veilige bewerking zijn die geen bijwerkingen heeft en uw persistente gegevens niet wijzigt.

Aanvullende bronnen