Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Hinweis
Dies ist nicht die neueste Version dieses Artikels. Die aktuelle Version finden Sie in der .NET 10-Version dieses Artikels.
Warnung
Diese Version von ASP.NET Core wird nicht mehr unterstützt. Weitere Informationen finden Sie in der .NET- und .NET Core-Supportrichtlinie. Die aktuelle Version finden Sie in der .NET 10-Version dieses Artikels.
Wir haben einen guten Anfang für die Movie-App, aber die Präsentation ist nicht ideal, zum Beispiel sollte ReleaseDate aus zwei Wörtern bestehen.
Öffnen Sie die Datei Models/Movie.cs, und fügen Sie die nachfolgend gezeigten markierten Zeilen hinzu:
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 werden im nächsten Tutorial erklärt. Das Display-Attribut gibt an, was für den Namen eines Felds angezeigt werden soll (in diesem Fall „Release Date“ anstatt „ReleaseDate“). Das DataType-Attribut gibt den Typ der Daten an (Date).
Führen Sie die Anwendung mithilfe der obigen Datenanmerkungen aus, und aktualisieren Sie die /Movies Seite. Da das Ansichtsmark-up die Methoden @Html.DisplayNameFor und @Html.DisplayFor verwendet, um den Eigenschaftennamen und -wert zu rendern, zeigt die aktualisierte Index-Ansicht alle Felder ordnungsgemäß formatiert an. Beispielsweise ist das Veröffentlichungsdatum jetzt zwei Wörter.
Die Datenanmerkung [Column(TypeName = "decimal(18, 2)")] ist erforderlich, damit Entity Framework Core Price ordnungsgemäß einer Währung in der Datenbank zuordnen kann. Weitere Informationen finden Sie unter Datentypen.
Navigieren Sie zum Movies-Controller, und halten Sie den Mauszeiger über einen Bearbeiten-Link, um die Ziel-URL zu sehen.
Die Links Bearbeiten, Details und Löschen werden mithilfe des Core MVC Anchor Tag Helpers in der Datei Views/Movies/Index.cshtml generiert.
<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 ermöglichen serverseitigem Code das Mitwirken am Erstellen und Rendern von HTML-Elementen in Razor-Dateien. Im obigen Code generiert AnchorTagHelper dynamisch den HTML-href-Attributwert aus der Controlleraktionsmethode und der Routen-ID. Verwenden Sie in Ihrem bevorzugten Browser Quelltext anzeigen oder die Entwicklertools, um das generierte Markup zu untersuchen. Ein Teil des generierten HTML-Codes wird unten gezeigt:
<td>
<a href="/Movies/Edit/4"> Edit </a> |
<a href="/Movies/Details/4"> Details </a> |
<a href="/Movies/Delete/4"> Delete </a>
</td>
Rufen Sie sich das Format für routing in der Program.cs Datei in Erinnerung:
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}")
.WithStaticAssets();
ASP.NET Core übersetzt https://localhost:5001/Movies/Edit/4 in eine Anforderung an die Edit-Aktionsmethode des Movies-Controllers mit dem Id-Parameter 4. (Controllermethoden werden auch als Aktionsmethoden bezeichnet.)
Tag Helpers sind eines der am häufigsten verwendeten neuen Features in ASP.NET Core. Weitere Informationen finden Sie unter "Verwandte Inhalte".
Öffnen Sie den Movies-Controller, und untersuchen Sie die beiden Edit-Aktionsmethoden. Der folgende Code zeigt die HTTP GET Edit-Methode, die den Film abruft und das Bearbeitungsformular ausfüllt, das von der Edit.cshtmlRazor-Datei generiert wurde.
// 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);
}
Der folgende Code zeigt die HTTP POST Edit-Methode, die die übermittelten Filmdaten verarbeitet:
// 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);
}
Das [Bind]-Attribut ist eine Möglichkeit zum Schutz vor Over-Posting. Sie sollten nur Eigenschaften im [Bind]-Attribut aufnehmen, die Sie ändern möchten. Weitere Informationen finden Sie unter Schützen Sie Ihren Controller vor übermäßigem Posten.
ViewModels bieten einen alternativen Ansatz, um Over-Posting zu verhindern.
Beachten Sie, dass der zweiten Edit-Aktionsmethode das [HttpPost]-Attribut vorausgeht.
// 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);
}
Das HttpPost-Attribut gibt an, dass diese Edit-Methode nur für POST-Anfragen aufgerufen werden kann. Sie könnten das [HttpGet]-Attribut auf die erste Editiermethode anwenden, aber dies ist nicht erforderlich, da [HttpGet] die Standardeinstellung ist.
Das Attribut ValidateAntiForgeryToken wird verwendet, um die Fälschung einer Anfrage zu verhindern, und wird mit einem Antiforgery-Token gepaart, das in der Datei der Bearbeitungsansicht (Views/Movies/Edit.cshtml) erzeugt wird. Die Datei der Bearbeitungsansicht generiert das Antifälschungstoken mit dem Form Tag Helper.
<form asp-action="Edit">
Das Form Tag Helper generiert ein verstecktes Antifälschungstoken, das mit dem von [ValidateAntiForgeryToken] generierten Antifälschungstoken in der Edit-Methode des Filmecontrollers übereinstimmen muss. Weitere Informationen finden Sie unter Prevent Cross-Site Request Forgery (XSRF/CSRF) Attacks in ASP.NET Core (Verhindern von websiteübergreifenden Anforderungsfälschungen (XSRF/CSRF) in ASP.NET Core).
Die HttpGet Edit-Methode akzeptiert den Filmparameter ID, sucht den Film mit der FindAsync-Methode von Entity Framework und gibt den ausgewählten Film an die Bearbeitungsansicht zurück. Wenn ein Film nicht gefunden werden kann, wird NotFound (HTTP 404) zurückgegeben.
// 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);
}
Als das Gerüstsystem die Bearbeitungsansicht erstellt hat, wurde die Movie-Klasse überprüft und Code zum Rendern der <label>- und <input>-Elemente für jede Eigenschaft der Klasse erstellt. Das folgende Beispiel zeigt die Ansicht „Bearbeiten“, die vom Visual Studio-Scaffolding-System generiert wurde:
@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");}
}
Beachten Sie, dass die Ansichtsvorlage eine @model MvcMovie.Models.Movie-Anweisung am Anfang der Datei aufweist.
@model MvcMovie.Models.Movie gibt an, dass die Ansicht erwartet, dass das Modell für die Ansichtsvorlage den Typ Movie hat.
Der Gerüstcode verwendet mehrere Methoden von Tag Helpern, um das HTML-Markup zu vereinfachen. Das Label-Tag-Helper zeigt den Namen des Felds an („Title“, „ReleaseDate“, „Genre“ oder „Price“). Das Input Tag Helper rendert ein HTML-<input>-Element. Der Validation-Tag-Helper zeigt alle Validierungsmeldungen an, die dieser Eigenschaft zugeordnet sind.
Führen Sie die Anwendung aus, und navigieren Sie zur /Movies-URL. Klicken Sie auf den Link Bearbeiten. Zeigen Sie im Browser den Quelltext für die Seite an. Der generierte HTML-Code für das <form>-Element wird unten dargestellt.
<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>
Die <input>-Elemente sind in einem HTML <form>-Element enthalten, dessen action-Attribut so festgelegt ist, dass Beiträge an die URL /Movies/Edit/id gesendet werden. Die Formulardaten werden an den Server gesendet, wenn auf die Schaltfläche Save geklickt wird. Die letzte Zeile vor dem schließenden </form>-Element zeigt das ausgeblendete XSRF-Token, das durch das Hilfsprogramm für Formulartags generiert wurde.
Verarbeiten der POST-Anforderung
Das folgende Codelisting zeigt die [HttpPost]-Version der Edit-Action-Methode.
// 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);
}
Das [ValidateAntiForgeryToken]-Attribut validiert das versteckte XSRF-Token, das vom Antifälschungstoken-Generator im Taghilfsprogramm für Formulare erzeugt wurde.
Das Model-Binding-System nimmt die übermittelten Formularwerte entgegen und erstellt daraus ein Movie-Objekt, das als movie-Parameter übergeben wird. Die ModelState.IsValid-Eigenschaft überprüft, dass die im Formular übermittelten Daten verwendet werden können, um ein Movie-Objekt zu ändern (zu bearbeiten oder zu aktualisieren). Wenn die Daten gültig sind, werden sie gespeichert. Die aktualisierten (bearbeiteten) Filmdaten werden in der Datenbank gespeichert, indem die SaveChangesAsync-Methode des Datenbankkontexts aufgerufen wird. Nach dem Speichern der Daten leitet der Code den Benutzer an die Index-Aktionsmethode der MoviesController-Klasse weiter, die die Filmsammlung einschließlich der gerade vorgenommenen Änderungen anzeigt.
Bevor das Formular an den Server gesendet wird, prüft die clientseitige Validierung die Validierungsregeln auf den Feldern. Sind Validierungsfehler vorhanden, wird eine Fehlermeldung angezeigt, und das Formular wird nicht gesendet. Wenn JavaScript deaktiviert ist, erfolgt keine clientseitige Validierung. Der Server erkennt jedoch, dass die bereitgestellten Werte nicht gültig sind, und die Formularwerte werden wieder mit Fehlermeldungen angezeigt. Später in diesem Tutorial untersuchen wir die Modellvalidierung im Detail. Der Validation-Tag-Helper in der Ansichtsvorlage Views/Movies/Edit.cshtml übernimmt die Anzeige der entsprechenden Fehlermeldungen.
Alle HttpGet-Methoden im Movie-Controller folgen einem ähnlichen Muster. Sie erhalten ein Movie-Objekt (oder eine Liste von Objekten bei Index), und übergeben das Objekt (Modell) an die Ansicht. Die Create-Methode übergibt ein leeres Filmobjekt an die Ansicht Create. Alle Methoden, die Daten erstellen, bearbeiten, löschen oder in beliebiger Weise ändern, nutzen dazu die [HttpPost]-Überladung der Methode. Das Ändern von Daten in einer HTTP GET-Methode ist ein Sicherheitsrisiko. Das Ändern von Daten in einer HTTP GET-Methode verstößt außerdem gegen bewährte HTTP-Verfahren und das architektonische REST-Muster, das festlegt, dass GET-Anfragen den Zustand Ihrer Anwendung nicht ändern sollten. Mit anderen Worten: Die Durchführung eines GET-Vorgangs sollte ein sicherer Vorgang sein, der keine Nebenwirkungen hat und Ihre persistent gespeicherten Daten nicht verändert.
Verwandte Inhalte
- Globalisierung und Lokalisierung
- Einführung in Taghilfsprogramme
- Erstellen von Tag Helpers
- Verhindern von Angriffen durch websiteübergreifende Anforderungsfälschung (XSRF/CSRF) in ASP.NET Core
- Schützen Sie Ihren Controller vor Over-Posting
- ViewModels
- Form-Tag-Helper
- Tag Helper für Eingaben
- Tag-Hilfsprogramm
- Tag-Hilfsprogramm auswählen
- Validierungs-Tag-Helper
Wir haben mit der Film-App einen guten Anfang gemacht, aber die Darstellung ist nicht ideal; zum Beispiel sollte ReleaseDate aus zwei Wörtern bestehen.
Öffnen Sie die Datei Models/Movie.cs, und fügen Sie die nachfolgend gezeigten markierten Zeilen hinzu:
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 werden im nächsten Tutorial erklärt. Das Display-Attribut gibt an, was für den Namen eines Felds angezeigt werden soll (in diesem Fall „Release Date“ anstatt „ReleaseDate“). Das DataType-Attribut gibt den Typ der Daten (Datum) an, deshalb werden die im Feld gespeicherten Informationen zur Uhrzeit nicht angezeigt.
Führen Sie die Anwendung mithilfe der obigen Datenanmerkungen aus, und aktualisieren Sie die /Movies Seite. Da das Ansichtsmark-up die Methoden @Html.DisplayNameFor und @Html.DisplayFor verwendet, um den Eigenschaftennamen und -wert zu rendern, zeigt die aktualisierte Index-Ansicht alle Felder ordnungsgemäß formatiert an. Beispielsweise ist das Veröffentlichungsdatum jetzt zwei Wörter, und die Uhrzeitinformationen werden nicht mehr angezeigt.
Die Datenanmerkung [Column(TypeName = "decimal(18, 2)")] ist erforderlich, damit Entity Framework Core Price in der Datenbank korrekt als Währung abbilden kann. Weitere Informationen finden Sie unter Datentypen.
Navigieren Sie zum Movies-Controller, und halten Sie den Mauszeiger über einen Bearbeiten-Link, um die Ziel-URL zu sehen.
Die Links Bearbeiten, Details und Löschen werden in der Datei Views/Movies/Index.cshtml vom Core MVC-Anker-Tag-Helfer generiert.
<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 ermöglichen serverseitigem Code die Beteiligung an der Erstellung und dem Rendern von HTML-Elementen in Razor-Dateien. Im obigen Code generiert AnchorTagHelper dynamisch den Wert des HTML-Attributs href anhand der Actionmethode des Controllers und der Routen-ID. Verwenden Sie in Ihrem bevorzugten Browser Quelltext anzeigen oder nutzen Sie die Entwicklertools, um den generierten Markupcode zu untersuchen. Ein Teil des generierten HTML-Codes wird unten gezeigt:
<td>
<a href="/Movies/Edit/4"> Edit </a> |
<a href="/Movies/Details/4"> Details </a> |
<a href="/Movies/Delete/4"> Delete </a>
</td>
Erinnern Sie sich an das Format für routing, das in der Program.cs-Datei festgelegt wurde:
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
ASP.NET Core übersetzt https://localhost:5001/Movies/Edit/4 in eine Anfrage an die Edit-Aktionsmethode des Movies-Controllers mit dem Parameter Id mit dem Wert 4. (Controllermethoden werden auch als Aktionsmethoden bezeichnet.)
Tag Helpers sind eines der am häufigsten verwendeten neuen Features in ASP.NET Core. Weitere Informationen finden Sie unter "Verwandte Inhalte".
Öffnen Sie den Movies-Controller, und untersuchen Sie die beiden Edit-Aktionsmethoden. Der folgende Code zeigt die HTTP GET Edit-Methode, die den Film abruft und das Bearbeitungsformular mit Daten füllt, das in der Datei Edit.cshtmlRazor generiert wird.
// 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);
}
Der folgende Code zeigt die HTTP POST Edit-Methode, die die übermittelten Filmwerte verarbeitet:
// 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);
}
Das [Bind]-Attribut ist eine Möglichkeit zum Schutz vor Over-Posting. Sie sollten nur Eigenschaften im [Bind]-Attribut angeben, die Sie ändern möchten. Weitere Informationen finden Sie unter Schützen Sie Ihren Controller vor Overposting.
ViewModels bieten eine alternative Methode, um Overposting zu verhindern.
Beachten Sie, dass der zweiten Edit-Aktionsmethode das [HttpPost]-Attribut vorangestellt ist.
// 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);
}
Das HttpPost-Attribut gibt an, dass diese Edit-Methode nur für POST-Anfragen aufgerufen werden kann. Sie könnten das Attribut [HttpGet] für die erste Methode angeben, aber das ist nicht erforderlich, da [HttpGet] standardmäßig verwendet wird.
Das Attribut ValidateAntiForgeryToken wird verwendet, um das Fälschen einer Anforderung zu verhindern, und wird mit einem Antiforgery-Token verknüpft, das in der Datei der Bearbeitungsansicht (Views/Movies/Edit.cshtml) erzeugt wird. Die Datei der Editieransicht generiert das Antiforgerytoken mit dem Form Tag Helper.
<form asp-action="Edit">
Das Form Tag Helper generiert ein verstecktes Antifälschungstoken, das mit dem von [ValidateAntiForgeryToken] generierten Antifälschungstoken in der Edit-Methode des Filmecontrollers übereinstimmen muss. Weitere Informationen finden Sie unter Verhindern von siteübergreifenden Anforderungsfälschungen (XSRF/CSRF) in ASP.NET Core.
Die HttpGet Edit-Methode verwendet den Movie-ID-Parameter, sucht den Film mit der FindAsync-Methode von Entity Framework und gibt den ausgewählten Film an die Bearbeitungsansicht zurück. Wenn ein Film nicht gefunden werden kann, wird NotFound (HTTP 404) angezeigt.
// 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);
}
Als das Scaffolding-System die Bearbeitungsansicht erstellt hat, wurde die Movie-Klasse überprüft und Code zum Rendern der <label>- und <input>-Elemente für jede Eigenschaft der Klasse erstellt. Das folgende Beispiel zeigt die Bearbeitungsansicht, die vom Visual Studio-Scaffolding-System generiert wurde:
@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");}
}
Beachten Sie, dass die Ansichtsvorlage eine @model MvcMovie.Models.Movie-Anweisung am Anfang der Datei aufweist.
@model MvcMovie.Models.Movie gibt an, dass die Ansicht erwartet, dass das Modell für die Ansichtsvorlage den Typ Movie hat.
Der Gerüstcode verwendet mehrere Methoden von Tag-Helpern, um das HTML-Markup zu optimieren. Der Label-Tag-Helfer zeigt den Namen des Feldes an („Title“, „ReleaseDate“, „Genre“ oder „Price“). Der Input-Tag-Helper rendert ein HTML-<input>-Element. Das Validation-Tag-Helper zeigt Validierungsmeldungen an, die dieser Eigenschaft zugeordnet sind.
Führen Sie die Anwendung aus, und navigieren Sie zur /Movies-URL. Klicken Sie auf den Link Bearbeiten. Zeigen Sie im Browser den Quelltext für die Seite an. Der generierte HTML-Code für das <form>-Element wird unten gezeigt.
<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>
Die <input>-Elemente befinden sich in einem HTML <form>-Element, dessen action-Attribut so festgelegt ist, dass Daten an die URL /Movies/Edit/id gesendet werden. Die Formulardaten werden an den Server gesendet, wenn auf die Schaltfläche Save geklickt wird. Die letzte Zeile vor dem schließenden </form>-Element zeigt das ausgeblendete XSRF-Token, das durch den Form Tag Helper generiert wurde.
Verarbeitung der POST-Anfrage
Die folgende Auflistung zeigt die [HttpPost]-Version der Edit-Aktionsmethode.
// 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);
}
Das [ValidateAntiForgeryToken]-Attribut validiert das versteckte XSRF-Token, das vom Antifälschungstoken-Generator im Form Tag Helper erzeugt wurde.
Das Model-Binding-System verwendet die übermittelten Formularwerte und erstellt ein Movie-Objekt, das als movie-Parameter übergeben wird. Die ModelState.IsValid-Eigenschaft stellt sicher, dass die im Formular übermittelten Daten verwendet werden können, um ein Movie-Objekt zu ändern (zu bearbeiten oder zu aktualisieren). Wenn die Daten gültig sind, werden sie gespeichert. Die aktualisierten (bearbeiteten) Filmdaten werden in der Datenbank gespeichert, indem die SaveChangesAsync-Methode des Datenbankkontexts aufgerufen wird. Nach dem Speichern der Daten leitet der Code den Benutzer an die Index-Aktionsmethode der MoviesController-Klasse weiter, die die Filmsammlung einschließlich der gerade vorgenommenen Änderungen anzeigt.
Bevor das Formular an den Server gesendet wird, überprüft die clientseitige Validierung etwaige an den Feldern definierten Validierungsregeln. Sind Validierungsfehler vorhanden, wird eine Fehlermeldung angezeigt, und das Formular wird nicht gesendet. Wenn JavaScript deaktiviert ist, erfolgt keine Validierung auf Clientseite. Der Server erkennt jedoch, dass die übermittelten Werte nicht gültig sind, und die Formularwerte werden wieder mit Fehlermeldungen angezeigt. Später in diesem Tutorial untersuchen wir die Modellvalidierung im Detail. Der Validation-Tag-Helper in der Ansichtsvorlage Views/Movies/Edit.cshtml übernimmt die Anzeige der entsprechenden Fehlermeldungen.
Alle HttpGet-Methoden im Movie-Controller folgen einem ähnlichen Muster. Sie erhalten ein Filmobjekt (oder eine Liste von Objekten im Fall von Index) und übergeben das Objekt (Modell) an die Ansicht. Die Create-Methode übergibt ein leeres Filmobjekt an die Ansicht Create. Alle Methoden, die Daten erstellen, bearbeiten, löschen oder in beliebiger Weise ändern, tun dies in der [HttpPost]-Überladung der Methode. Das Ändern von Daten in einer HTTP GET-Methode ist ein Sicherheitsrisiko. Das Ändern von Daten in einer HTTP GET-Methode verstößt auch gegen die Best Practices für HTTP und das architektonische REST-Muster, das angibt, dass GET-Anforderungen den Status Ihrer Anwendung nicht ändern dürfen. Mit anderen Worten sollte das Ausführen einer GET-Operation eine sichere Operation sein, die keine Nebenwirkungen hat und Ihre persistierten Daten nicht verändert.
Verwandte Inhalte
- Globalisierung und Lokalisierung
- Einführung in Tag Helpers
- Tag Helpers erstellen
- Verhindern von Angriffen durch websiteübergreifende Anforderungsfälschung (XSRF/CSRF) in ASP.NET Core
- Schützen Sie Ihren Controller vor Over-Posting
- ViewModels
- Tag-Hilfsprogramm für das form-Element
- Input-Tag-Helper
- Tag Helper für Beschriftungen
- Tag-Helper auswählen
- Validierungs-Tag-Helper
Wir haben einen guten Anfang für die Movie-App, aber die Präsentation ist nicht ideal, zum Beispiel sollte ReleaseDate aus zwei Wörtern bestehen.
Öffnen Sie die Datei Models/Movie.cs, und fügen Sie die nachfolgend gezeigten markierten Zeilen hinzu:
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 werden im nächsten Tutorial erklärt. Das Display-Attribut gibt an, was für den Namen eines Felds angezeigt werden soll (in diesem Fall „Release Date“ anstatt „ReleaseDate“). Das DataType-Attribut gibt den Typ der Daten (Datum) an, daher werden die im Feld gespeicherten Informationen zur Uhrzeit nicht angezeigt.
Die Datenanmerkung [Column(TypeName = "decimal(18, 2)")] ist erforderlich, damit Entity Framework Core Price ordnungsgemäß einer Währung in der Datenbank zuordnen kann. Weitere Informationen finden Sie unter Datentypen.
Navigieren Sie zum Movies-Controller, und halten Sie den Mauszeiger über einen Bearbeiten-Link, um die Ziel-URL zu sehen.
Die Links Bearbeiten, Details und Löschen werden mithilfe des Core MVC Anchor Tag Helpers in der Datei Views/Movies/Index.cshtml generiert.
<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 ermöglichen serverseitigem Code das Mitwirken am Erstellen und Rendern von HTML-Elementen in Razor-Dateien. Im obigen Code generiert AnchorTagHelper dynamisch den HTML-href-Attributwert aus der Controlleraktionsmethode und der Routen-ID. Verwenden Sie in Ihrem bevorzugten Browser Quelltext anzeigen oder die Entwicklertools, um das generierte Markup zu untersuchen. Ein Teil des generierten HTML-Codes wird unten gezeigt:
<td>
<a href="/Movies/Edit/4"> Edit </a> |
<a href="/Movies/Details/4"> Details </a> |
<a href="/Movies/Delete/4"> Delete </a>
</td>
Rufen Sie sich das Format für routing in der Program.cs Datei in Erinnerung:
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
ASP.NET Core übersetzt https://localhost:5001/Movies/Edit/4 in eine Anforderung an die Edit-Aktionsmethode des Movies-Controllers mit dem Id-Parameter 4. (Controllermethoden werden auch als Aktionsmethoden bezeichnet.)
Tag Helpers sind eines der am häufigsten verwendeten neuen Features in ASP.NET Core. Weitere Informationen finden Sie unter "Verwandte Inhalte".
Öffnen Sie den Movies-Controller, und untersuchen Sie die beiden Edit-Aktionsmethoden. Der folgende Code zeigt die HTTP GET Edit-Methode, die den Film abruft und das Bearbeitungsformular ausfüllt, das von der Edit.cshtmlRazor-Datei generiert wurde.
// 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);
}
Der folgende Code zeigt die HTTP POST Edit-Methode, die die übermittelten Filmdaten verarbeitet:
// 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);
}
Das [Bind]-Attribut ist eine Möglichkeit zum Schutz vor Over-Posting. Sie sollten nur Eigenschaften im [Bind]-Attribut aufnehmen, die Sie ändern möchten. Weitere Informationen finden Sie unter Schützen Sie Ihren Controller vor übermäßigem Posten.
ViewModels bieten einen alternativen Ansatz, um Over-Posting zu verhindern.
Beachten Sie, dass der zweiten Edit-Aktionsmethode das [HttpPost]-Attribut vorausgeht.
// 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);
}
Das HttpPost-Attribut gibt an, dass diese Edit-Methode nur für POST-Anfragen aufgerufen werden kann. Sie könnten das [HttpGet]-Attribut auf die erste Editiermethode anwenden, aber dies ist nicht erforderlich, da [HttpGet] die Standardeinstellung ist.
Das Attribut ValidateAntiForgeryToken wird verwendet, um die Fälschung einer Anfrage zu verhindern, und wird mit einem Antiforgery-Token gepaart, das in der Datei der Bearbeitungsansicht (Views/Movies/Edit.cshtml) erzeugt wird. Die Datei der Bearbeitungsansicht generiert das Antifälschungstoken mit dem Form Tag Helper.
<form asp-action="Edit">
Das Form Tag Helper generiert ein verstecktes Antifälschungstoken, das mit dem von [ValidateAntiForgeryToken] generierten Antifälschungstoken in der Edit-Methode des Filmecontrollers übereinstimmen muss. Weitere Informationen finden Sie unter Prevent Cross-Site Request Forgery (XSRF/CSRF) Attacks in ASP.NET Core (Verhindern von websiteübergreifenden Anforderungsfälschungen (XSRF/CSRF) in ASP.NET Core).
Die HttpGet Edit-Methode verwendet den ID-Parameter eines Films, sucht den Film mit der FindAsync-Methode von Entity Framework, und gibt den ausgewählten Film an die Bearbeitungsansicht zurück. Wenn ein Film nicht gefunden werden kann, wird NotFound (HTTP 404) zurückgegeben.
// 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);
}
Als das Scaffolding-System die Bearbeitungsansicht erstellt hat, wurde die Movie-Klasse überprüft und Code zum Rendern der <label>- und <input>-Elemente für jede Eigenschaft der Klasse erstellt. Das folgende Beispiel zeigt die Bearbeitungsansicht, die vom Visual Studio-Scaffolding-System generiert wurde:
@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");}
}
Beachten Sie, dass die Ansichtsvorlage eine @model MvcMovie.Models.Movie-Anweisung am Anfang der Datei aufweist.
@model MvcMovie.Models.Movie gibt an, dass die Ansicht erwartet, dass das Modell für die Ansichtsvorlage den Typ Movie hat.
Der Gerüstcode verwendet mehrere Methoden von Tag-Helpern, um das HTML-Markup zu vereinfachen. Das Label-Tag-Helper zeigt den Namen des Felds an („Title“, „ReleaseDate“, „Genre“ oder „Price“). Das Input-Tag-Helper rendert ein HTML-<input>-Element. Das Validierungs-Tag-Helper zeigt alle Validierungsmeldungen an, die dieser Eigenschaft zugeordnet sind.
Führen Sie die Anwendung aus, und navigieren Sie zur /Movies-URL. Klicken Sie auf den Link Bearbeiten. Zeigen Sie im Browser den Quelltext der Seite an. Der generierte HTML-Code für das <form>-Element wird unten dargestellt.
<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>
Die <input>-Elemente sind in einem HTML <form>-Element enthalten, dessen action-Attribut so festgelegt ist, dass Beiträge an die URL /Movies/Edit/id gesendet werden. Die Formulardaten werden an den Server gesendet, wenn auf die Schaltfläche Save geklickt wird. Die letzte Zeile vor dem schließenden </form>-Element zeigt das ausgeblendete XSRF-Token, das durch den Form-Tag-Helper generiert wurde.
Verarbeiten der POST-Anforderung
Die folgende Liste zeigt die [HttpPost]-Version der Edit-Aktionsmethode.
// 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);
}
Das [ValidateAntiForgeryToken]-Attribut validiert das versteckte XSRF-Token, das vom Antifälschungstoken-Generator im Form Tag Helper erzeugt wurde.
Das Model Binding-System übernimmt die übermittelten Formularwerte und erstellt ein Movie-Objekt, das als movie-Parameter übergeben wird. Die ModelState.IsValid-Eigenschaft stellt sicher, dass die im Formular übermittelten Daten verwendet werden können, um ein Movie-Objekt zu ändern (zu bearbeiten oder zu aktualisieren). Wenn die Daten gültig sind, werden sie gespeichert. Die aktualisierten (bearbeiteten) Filmdaten werden in der Datenbank gespeichert, indem die SaveChangesAsync-Methode des Datenbankkontexts aufgerufen wird. Nach dem Speichern der Daten leitet der Code den Benutzer an die Index-Aktionsmethode der MoviesController-Klasse weiter, die die Filmsammlung einschließlich der gerade vorgenommenen Änderungen anzeigt.
Bevor das Formular an den Server übermittelt wird, prüft die clientseitige Validierung alle für die Felder definierten Validierungsregeln. Sind Validierungsfehler vorhanden, wird eine Fehlermeldung angezeigt, und das Formular wird nicht gesendet. Wenn JavaScript deaktiviert ist, erfolgt keine clientseitige Validierung, aber der Server stellt fest, dass die übermittelten Werte ungültig sind, und die Formularwerte werden erneut zusammen mit Fehlermeldungen angezeigt. Später in diesem Tutorial sehen wir uns die Modellvalidierung genauer an. Das Validation-Tag-Helper in der Ansichtsvorlage Views/Movies/Edit.cshtml übernimmt die Anzeige der entsprechenden Fehlermeldungen.
Alle HttpGet-Methoden im Movie-Controller folgen einem ähnlichen Muster. Sie erhalten ein Movie-Objekt (oder eine Liste von Objekten bei Index), und übergeben das Objekt (Modell) an die Ansicht. Die Create-Methode übergibt ein leeres Movie-Objekt an die Ansicht Create. Alle Methoden, die Daten erstellen, bearbeiten, löschen oder in beliebiger Weise ändern, nutzen dazu die [HttpPost]-Überladung der Methode. Das Ändern von Daten in einer HTTP GET-Methode ist ein Sicherheitsrisiko. Das Ändern von Daten in einer HTTP GET-Methode verstößt auch gegen bewährte HTTP-Methoden und das architektonische REST-Muster, das angibt, dass die GET-Anforderungen nicht den Status Ihrer Anwendung ändern dürfen. Die Durchführung eines GET-Vorgangs sollte also eine sichere Operation sein, die keine Nebenwirkungen hat und die persistierten Daten nicht ändert.
Verwandte Inhalte
- Globalisierung und Lokalisierung
- Einführung in Tag Helpers
- Tag-Hilfsprogramme für Autoren
- Verhindern von Angriffen durch websiteübergreifende Anforderungsfälschung (XSRF/CSRF) in ASP.NET Core
- Schützen Sie Ihren Controller vor Overposting
- ViewModels
- Formular-Tag-Helper
- Input-Tag-Helper
- Hilfsprogramm für Bezeichnungs-Tags
- Tag Helper auswählen
- Validierungs-Tag-Helper
Wir haben einen guten Anfang für die Film-App, aber die Darstellung ist nicht ideal, zum Beispiel sollte ReleaseDate aus zwei Wörtern bestehen.
Öffnen Sie die Datei Models/Movie.cs, und fügen Sie die nachfolgend gezeigten markierten Zeilen hinzu:
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 werden im nächsten Tutorial erklärt. Das Display-Attribut gibt an, was für den Namen eines Felds angezeigt werden soll (in diesem Fall „Release Date“ anstatt „ReleaseDate“). Das DataType-Attribut gibt den Typ der Daten (Datum) an, sodass die im Feld gespeicherten Informationen zur Uhrzeit nicht angezeigt werden.
Die Datenanmerkung [Column(TypeName = "decimal(18, 2)")] ist erforderlich, damit Entity Framework Core Price in der Datenbank ordnungsgemäß als Währung abbilden kann. Weitere Informationen finden Sie unter Datentypen.
Navigieren Sie zum Movies Steuerelement, und halten Sie den Mauszeiger über einen Bearbeiten-Link, um die Ziel-URL zu sehen.
Die Links Bearbeiten, Details und Löschen werden mithilfe des Core MVC-Anker-Tag-Helpers in der Datei Views/Movies/Index.cshtml generiert.
<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 ermöglichen serverseitigem Code das Mitwirken am Erstellen und Rendern von HTML-Elementen in Razor-Dateien. Im obigen Code generiert AnchorTagHelper dynamisch den HTML-href-Attributwert aus der Controlleraktionsmethode und der Routen-ID. Verwenden Sie in Ihrem bevorzugten Browser Quelltext anzeigen oder die Entwicklertools, um das generierte Markup zu untersuchen. Ein Teil des generierten HTML-Codes wird unten gezeigt:
<td>
<a href="/Movies/Edit/4"> Edit </a> |
<a href="/Movies/Details/4"> Details </a> |
<a href="/Movies/Delete/4"> Delete </a>
</td>
Beachten Sie das Format für routing, das in der Datei Program.cs festgelegt ist:
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
ASP.NET Core übersetzt https://localhost:5001/Movies/Edit/4 in eine Anforderung an die Edit-Aktionsmethode des Movies-Controllers mit dem Id-Parameter 4. (Controllermethoden werden auch als Aktionsmethoden bezeichnet.)
Tag Helpers sind eines der am häufigsten verwendeten neuen Features in ASP.NET Core. Weitere Informationen finden Sie unter "Verwandte Inhalte".
Öffnen Sie den Movies-Controller, und untersuchen Sie die beiden Edit-Aktionsmethoden. Der folgende Code zeigt die HTTP GET Edit-Methode, die den Film abruft und das Bearbeitungsformular ausfüllt, das von der Edit.cshtmlRazor-Datei generiert wurde.
// 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);
}
Der folgende Code zeigt die HTTP POST Edit-Methode, die die bereitgestellten Filmwerte verarbeitet:
// 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);
}
Das [Bind]-Attribut ist eine Möglichkeit zum Schutz vor Over-Posting. Sie sollten nur Eigenschaften im [Bind]-Attribut angeben, die Sie ändern möchten. Weitere Informationen finden Sie unter Schützen Sie Ihren Controller vor Overposting.
ViewModels bietet eine alternative Methode, um zu viele Angaben zu verhindern.
Beachten Sie, dass der zweiten Edit-Aktionsmethode das [HttpPost]-Attribut vorangestellt ist.
// 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);
}
Das HttpPost-Attribut gibt an, dass diese Edit-Methode nur für POST-Anfragen aufgerufen werden kann. Sie könnten das [HttpGet]-Attribut auf die erste Bearbeitungsmethode anwenden, aber dies ist nicht erforderlich, da [HttpGet] der Standardwert ist.
Das Attribut ValidateAntiForgeryToken wird verwendet, um das Fälschen einer Anforderung zu verhindern, und wird mit einem Antiforgery-Token gepaart, das in der Datei der Bearbeitungsansicht (Views/Movies/Edit.cshtml) erzeugt wird. Die Datei der Bearbeitungsansicht generiert das Antifälschungstoken mit dem Taghilfsprogramm für Formulare.
<form asp-action="Edit">
Das Form Tag Helper generiert ein verstecktes Antifälschungstoken, das mit dem von [ValidateAntiForgeryToken] generierten Antifälschungstoken in der Edit-Methode des Filmecontrollers übereinstimmen muss. Weitere Informationen finden Sie unter Prevent Cross-Site Request Forgery (XSRF/CSRF) Attacks in ASP.NET Core (Verhindern von websiteübergreifenden Anforderungsfälschungen (XSRF/CSRF) in ASP.NET Core).
Die HttpGet Edit-Methode verwendet den Filmparameter ID, sucht den Film mit der FindAsync-Methode von Entity Framework und gibt den ausgewählten Film an die Bearbeitungsansicht zurück. Wenn ein Film nicht gefunden werden kann, wird NotFound (HTTP 404) angezeigt.
// 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);
}
Als das Scaffolding-System die Bearbeitungsansicht erstellte, untersuchte es die Klasse Movie und erzeugte Code, um für jede Eigenschaft der Klasse <label>- und <input>-Elemente zu rendern. Das folgende Beispiel zeigt die Bearbeitungsansicht, die vom Visual Studio-Scaffolding-System generiert wurde:
@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");}
}
Beachten Sie, dass die Ansichtsvorlage eine @model MvcMovie.Models.Movie-Anweisung am Anfang der Datei aufweist.
@model MvcMovie.Models.Movie gibt an, dass die Ansicht erwartet, dass das Modell für die Ansichtsvorlage den Typ Movie hat.
Der generierte Code verwendet mehrere Tag-Helper-Methoden, um die HTML-Auszeichnung zu vereinfachen. Das Label-Tag-Helper zeigt den Namen des Felds an („Title“, „ReleaseDate“, „Genre“ oder „Price“). Das Input Tag Helper rendert ein HTML-<input>-Element. Das Validation Tag Helper zeigt Validierungsmeldungen an, die dieser Eigenschaft zugeordnet sind.
Führen Sie die Anwendung aus, und navigieren Sie zur /Movies-URL. Klicken Sie auf den Link Bearbeiten. Zeigen Sie im Browser den Quelltext für die Seite an. Der generierte HTML-Code für das <form>-Element wird unten dargestellt.
<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>
Die <input>-Elemente sind in einem HTML <form>-Element enthalten, dessen action-Attribut so festgelegt ist, dass an die URL /Movies/Edit/id gesendet wird. Die Formulardaten werden an den Server gesendet, wenn auf die Schaltfläche Save geklickt wird. Die letzte Zeile vor dem schließenden </form>-Element zeigt das ausgeblendete XSRF-Token, das durch das Hilfsprogramm für Formulartags generiert wurde.
Verarbeiten der POST-Anforderung
Die folgende Liste zeigt die [HttpPost]-Version der Edit-Aktionsmethode.
// 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);
}
Das [ValidateAntiForgeryToken]-Attribut validiert das versteckte XSRF-Token, das vom Antifälschungstoken-Generator im Form Tag Helper erzeugt wurde.
Das Model Binding-System übernimmt die übermittelten Formularwerte und erstellt ein Movie-Objekt, das als movie-Parameter übergeben wird. Die ModelState.IsValid-Eigenschaft stellt sicher, dass die im Formular übermittelten Daten verwendet werden können, um ein Movie-Objekt zu ändern (zu bearbeiten oder zu aktualisieren). Wenn die Daten gültig sind, werden sie gespeichert. Die aktualisierten (bearbeiteten) Filmdaten werden in der Datenbank gespeichert, indem die SaveChangesAsync-Methode des Datenbankkontexts aufgerufen wird. Nach dem Speichern der Daten leitet der Code den Benutzer an die Index-Aktionsmethode der MoviesController-Klasse weiter, die die Filmsammlung einschließlich der gerade vorgenommenen Änderungen anzeigt.
Bevor das Formular an den Server übermittelt wird, prüft die clientseitige Validierung alle für die Felder definierten Validierungsregeln. Sind Validierungsfehler vorhanden, wird eine Fehlermeldung angezeigt, und das Formular wird nicht gesendet. Wenn JavaScript deaktiviert ist, erfolgt keine clientseitige Validierung, aber der Server stellt fest, dass die übermittelten Werte ungültig sind, und die Formularwerte werden erneut zusammen mit Fehlermeldungen angezeigt. Später in diesem Tutorial sehen wir uns die Modellvalidierung genauer an. Das Validation-Tag-Helper in der Ansichtsvorlage Views/Movies/Edit.cshtml übernimmt die Anzeige der entsprechenden Fehlermeldungen.
Alle HttpGet-Methoden im Movie-Controller folgen einem ähnlichen Muster. Sie erhalten ein Movie-Objekt (oder eine Liste von Objekten bei Index), und übergeben das Objekt (Modell) an die Ansicht. Die Create-Methode übergibt ein leeres Movie-Objekt an die Ansicht Create. Alle Methoden, die Daten erstellen, bearbeiten, löschen oder in beliebiger Weise ändern, nutzen dazu die [HttpPost]-Überladung der Methode. Das Ändern von Daten in einer HTTP GET-Methode ist ein Sicherheitsrisiko. Das Ändern von Daten in einer HTTP GET-Methode verstößt auch gegen HTTP-Best-Practices und das architektonische REST-Muster, das angibt, dass GET-Anfragen den Status Ihrer Anwendung nicht ändern dürfen. Die Durchführung eines GET-Vorgangs sollte also eine sichere Operation sein, die keine Nebenwirkungen hat und die persistierten Daten nicht ändert.
Verwandte Inhalte
- Globalisierung und Lokalisierung
- Einführung in Tag Helpers
- Tag-Hilfsprogramme für Autoren
- Verhindern von Angriffen durch websiteübergreifende Anforderungsfälschung (XSRF/CSRF) in ASP.NET Core
- Schützen Sie Ihren Controller vor Overposting
- ViewModels
- Formular-Tag-Helper
- Input-Tag-Helper
- Hilfsprogramm für Bezeichnungs-Tags
- Tag Helper auswählen
- Validierungs-Tag-Helper
Wir haben einen guten Anfang für die Movie-App, aber die Darstellung ist nicht ideal, zum Beispiel sollte ReleaseDate aus zwei Wörtern bestehen.
Öffnen Sie die Datei Models/Movie.cs, und fügen Sie die nachfolgend gezeigten markierten Zeilen hinzu:
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 werden im nächsten Tutorial erklärt. Das Display-Attribut gibt an, was für den Namen eines Felds angezeigt werden soll (in diesem Fall „Release Date“ anstatt „ReleaseDate“). Das Attribut DataType gibt den Datentyp der Daten (Datum) an, sodass die im Feld gespeicherten Zeitinformationen nicht angezeigt werden.
Die Datenanmerkung [Column(TypeName = "decimal(18, 2)")] ist erforderlich, damit Entity Framework Core Price in der Datenbank ordnungsgemäß dem Datentyp „currency“ zuordnen kann. Weitere Informationen finden Sie unter Datentypen.
Navigieren Sie zum Movies-Controller, und halten Sie den Mauszeiger über einen Bearbeiten-Link, um die Ziel-URL zu sehen.
Die Links Bearbeiten, Details und Löschen werden mithilfe des Core MVC Anchor-Tag-Helpers in der Datei Views/Movies/Index.cshtml generiert.
<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 ermöglichen serverseitigem Code das Mitwirken am Erstellen und Rendern von HTML-Elementen in Razor-Dateien. Im obigen Code generiert AnchorTagHelper dynamisch den HTML-href-Attributwert aus der Controlleraktionsmethode und der Routen-ID. Verwenden Sie in Ihrem bevorzugten Browser Quelltext anzeigen oder die Entwicklertools, um das generierte Markup zu untersuchen. Ein Teil des generierten HTML ist unten dargestellt:
<td>
<a href="/Movies/Edit/4"> Edit </a> |
<a href="/Movies/Details/4"> Details </a> |
<a href="/Movies/Delete/4"> Delete </a>
</td>
Rufen Sie sich das Format für das in der Datei Program.cs festgelegte routing in Erinnerung:
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
ASP.NET Core wandelt https://localhost:5001/Movies/Edit/4 in eine Anforderung an die Edit-Aktionsmethode des Movies-Controllers mit dem Parameter Id mit dem Wert 4 um. (Controllermethoden werden auch als Aktionsmethoden bezeichnet.)
Tag Helpers sind ein beliebtes Feature in ASP.NET Core. Weitere Informationen zu ihnen finden Sie unter Verwandte Inhalte.
Öffnen Sie den Movies-Controller, und untersuchen Sie die beiden Edit-Aktionsmethoden. Der folgende Code zeigt die HTTP GET Edit-Methode, die das Movie-Objekt abruft und das Bearbeitungsformular ausfüllt, das von der Edit.cshtmlRazor-Datei generiert wurde.
// 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);
}
Der folgende Code zeigt die HTTP POST Edit-Methode, die die übermittelten Filmwerte verarbeitet:
// 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);
}
Das [Bind]-Attribut ist eine Möglichkeit zum Schutz vor Over-Posting. Sie sollten nur Eigenschaften im [Bind]-Attribut angeben, die Sie ändern möchten. Weitere Informationen finden Sie unter Schützen Sie Ihren Controller vor zu vielen Einträgen.
ViewModels bieten eine alternative Methode, um Overposting zu verhindern.
Beachten Sie, dass der zweiten Edit-Aktionsmethode das [HttpPost]-Attribut vorangestellt ist.
// 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);
}
Das HttpPost-Attribut gibt an, dass diese Edit-Methode nur für POST-Anfragen aufgerufen werden kann. Sie könnten das [HttpGet]-Attribut auf die erste Edit-Methode anwenden, aber dies ist nicht erforderlich, da [HttpGet] der Standardwert ist.
Das Attribut ValidateAntiForgeryToken wird verwendet, um die Fälschung einer Anforderung zu verhindern, und wird mit einem Antifälschungstoken gepaart, das in der Datei der Bearbeitungsansicht (Views/Movies/Edit.cshtml) erzeugt wird. Die Datei der Bearbeitungsansicht generiert das Antifälschungstoken mit dem Taghilfsprogramm für Formulare.
<form asp-action="Edit">
Das Form-Tag-Hilfsprogramm generiert ein verborgenes Antiforgery-Token, das mit dem in der Edit-Methode des Movies-Controllers von [ValidateAntiForgeryToken] generierten Antiforgery-Token übereinstimmen muss. Weitere Informationen finden Sie unter Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core.
Die HttpGet Edit-Methode übernimmt den Filmparameter ID, sucht den Film mit der FindAsync-Methode von Entity Framework und gibt den ausgewählten Film an die Bearbeitungsansicht zurück. Wenn ein Film nicht gefunden werden kann, wird NotFound (HTTP 404) zurückgegeben.
// 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);
}
Als das Scaffolding-System die Bearbeitungsansicht erstellt hat, wurde die Movie-Klasse überprüft und Code zum Rendern der <label>- und <input>-Elemente für jede Eigenschaft der Klasse erstellt. Das folgende Beispiel zeigt die Bearbeitungsansicht, die vom Visual Studio-Scaffolding-System generiert wurde:
@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");}
}
Beachten Sie, dass die Ansichtsvorlage eine @model MvcMovie.Models.Movie-Anweisung am Anfang der Datei aufweist.
@model MvcMovie.Models.Movie gibt an, dass das Modell der Ansichtsvorlage vom Typ Movie ist.
Der Gerüstcode verwendet mehrere Methoden von Tag Helpern, um das HTML-Markup zu optimieren. Das Label-Tag-Helper zeigt den Namen des Feldes an („Title“, „ReleaseDate“, „Genre“ oder „Price“). Das Input-Tag-Helper rendert ein HTML-<input>-Element. Der Validation Tag Helper zeigt alle Validierungsmeldungen an, die dieser Eigenschaft zugeordnet sind.
Führen Sie die Anwendung aus und gehen Sie zur URL /Movies. Klicken Sie auf den Link Bearbeiten. Zeigen Sie im Browser den Quelltext für die Seite an. Der generierte HTML-Code für das <form>-Element wird unten dargestellt.
<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>
Die <input>-Elemente sind in einem HTML <form>-Element enthalten, dessen action-Attribut so festgelegt ist, dass an die URL /Movies/Edit/id gesendet wird. Die Formulardaten werden an den Server gesendet, wenn auf die Schaltfläche Save geklickt wird. Die letzte Zeile vor dem schließenden </form>-Element zeigt das ausgeblendete XSRF-Token, das durch den Form-Tag-Helper generiert wurde.
Verarbeiten der POST-Anforderung
Die folgende Liste zeigt die [HttpPost]-Version der Edit-Aktionsmethode.
// 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);
}
Das [ValidateAntiForgeryToken]-Attribut validiert das versteckte XSRF-Token, das vom Antifälschungstoken-Generator im Form Tag Helper erzeugt wurde.
Das Model-Binding-System übernimmt die übermittelten Formularwerte und erstellt ein Movie-Objekt, das als movie-Parameter übergeben wird. Die ModelState.IsValid-Eigenschaft stellt sicher, dass die im Formular übermittelten Daten verwendet werden können, um ein Movie-Objekt zu ändern (zu bearbeiten oder zu aktualisieren). Wenn die Daten gültig sind, werden sie gespeichert. Die aktualisierten (bearbeiteten) Filmdaten werden in der Datenbank gespeichert, indem die SaveChangesAsync-Methode des Datenbankkontexts aufgerufen wird. Nach dem Speichern der Daten leitet der Code den Benutzer an die Index-Aktionsmethode der MoviesController-Klasse weiter, die die Filmsammlung einschließlich der gerade vorgenommenen Änderungen anzeigt.
Bevor das Formular an den Server gesendet wird, überprüft die clientseitige Validierung alle Validierungsregeln in den Feldern. Sind Validierungsfehler vorhanden, wird eine Fehlermeldung angezeigt, und das Formular wird nicht gesendet. Wenn JavaScript deaktiviert ist, erfolgt keine clientseitige Validierung. Der Server erkennt jedoch, dass die übermittelten Formularwerte nicht gültig sind, und die Formularwerte werden wieder mit Fehlermeldungen angezeigt. Später in diesem Tutorial untersuchen wir die Modellvalidierung im Detail. Der Validation-Tag-Helper in der Ansichtsvorlage Views/Movies/Edit.cshtml übernimmt die Anzeige der entsprechenden Fehlermeldungen.
Alle HttpGet-Methoden im Movie-Controller folgen einem ähnlichen Muster. Sie erhalten ein Filmobjekt (oder eine Liste von Objekten im Fall von Index) und übergeben das Objekt (Modell) an die Ansicht. Die Create-Methode übergibt ein leeres Filmobjekt an die Ansicht Create. Alle Methoden, die Daten erstellen, bearbeiten, löschen oder in beliebiger Weise ändern, tun dies in der [HttpPost]-Überladung der Methode. Das Ändern von Daten in einer HTTP GET-Methode ist ein Sicherheitsrisiko. Das Ändern von Daten in einer HTTP GET-Methode verstößt auch gegen die Best Practices für HTTP und das architektonische REST-Muster, das angibt, dass GET-Anforderungen den Status Ihrer Anwendung nicht ändern dürfen. Mit anderen Worten sollte das Ausführen einer GET-Operation eine sichere Operation sein, die keine Nebenwirkungen hat und Ihre persistierten Daten nicht verändert.
Verwandte Inhalte
- Globalisierung und Lokalisierung
- Einführung in Tag Helpers
- Tag Helpers erstellen
- Verhindern von Angriffen durch websiteübergreifende Anforderungsfälschung (XSRF/CSRF) in ASP.NET Core
- Schützen Sie Ihren Controller vor Over-Posting
- ViewModels
- Hilfsprogramm für Formulartags
- Input-Tag-Helper
- Tag Helper für Beschriftungen
- Tag-Helper auswählen
- Validierungs-Tag-Helper
Wir haben einen guten Anfang für die Movie-App, aber die Präsentation ist nicht ideal, zum Beispiel sollte ReleaseDate aus zwei Wörtern bestehen.
Öffnen Sie die Datei Models/Movie.cs, und fügen Sie die nachfolgend gezeigten markierten Zeilen hinzu:
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; }
}
}
Im nächsten Tutorial behandeln wir DataAnnotations. Das Display-Attribut gibt an, was für den Namen eines Felds angezeigt werden soll (in diesem Fall „Release Date“ anstatt „ReleaseDate“). Das DataType-Attribut gibt den Typ der Daten (Datum) an, damit die im Feld gespeicherten Informationen zur Uhrzeit nicht angezeigt werden.
Die Datenannotation [Column(TypeName = "decimal(18, 2)")] ist erforderlich, damit Entity Framework Core Price in der Datenbank korrekt dem Währungstyp zuordnen kann. Weitere Informationen finden Sie unter Datentypen.
Navigieren Sie zum Movies-Controller, und halten Sie den Mauszeiger über einen Bearbeiten-Link, um die Ziel-URL zu sehen.
Die Links Bearbeiten, Details und Löschen werden mithilfe des Core MVC Anchor Tag Helpers in der Datei Views/Movies/Index.cshtml generiert.
<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 ermöglichen serverseitigem Code das Mitwirken am Erstellen und Rendern von HTML-Elementen in Razor-Dateien. Im obigen Code generiert AnchorTagHelper dynamisch den HTML-href-Attributwert aus der Controlleraktionsmethode und der Routen-ID. Verwenden Sie in Ihrem bevorzugten Browser Quelltext anzeigen oder die Entwicklertools, um das generierte Markup zu untersuchen. Ein Teil des generierten HTML-Codes wird unten gezeigt:
<td>
<a href="/Movies/Edit/4"> Edit </a> |
<a href="/Movies/Details/4"> Details </a> |
<a href="/Movies/Delete/4"> Delete </a>
</td>
Rufen Sie sich das Format für routing in der Startup.cs Datei in Erinnerung:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
ASP.NET Core übersetzt https://localhost:5001/Movies/Edit/4 in eine Anforderung an die Edit-Aktionsmethode des Movies-Controllers mit dem Id-Parameter 4. (Controllermethoden werden auch als Aktionsmethoden bezeichnet.)
Weitere Informationen zu Tag Helpers finden Sie unter Verwandte Inhalte.
Öffnen Sie den Movies-Controller, und untersuchen Sie die beiden Edit-Aktionsmethoden. Der folgende Code zeigt die HTTP GET Edit-Methode, die den Film abruft und das Bearbeitungsformular ausfüllt, das von der Edit.cshtmlRazor-Datei generiert wurde.
// 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);
}
Der folgende Code zeigt die HTTP POST Edit-Methode, die die übermittelten Filmdaten verarbeitet:
// 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);
}
Das [Bind]-Attribut ist eine Möglichkeit zum Schutz vor Over-Posting. Sie sollten nur Eigenschaften im [Bind]-Attribut aufnehmen, die Sie ändern möchten. Weitere Informationen finden Sie unter Schützen Sie Ihren Controller vor übermäßigem Posten.
ViewModels bieten einen alternativen Ansatz, um Over-Posting zu verhindern.
Beachten Sie, dass der zweiten Edit-Aktionsmethode das [HttpPost]-Attribut vorausgeht.
[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);
}
Das HttpPost-Attribut gibt an, dass diese Edit-Methode nur für POST-Anfragen aufgerufen werden kann. Sie könnten das [HttpGet]-Attribut auf die erste Editiermethode anwenden, aber dies ist nicht erforderlich, da [HttpGet] die Standardeinstellung ist.
Das Attribut ValidateAntiForgeryToken wird verwendet, um die Fälschung einer Anfrage zu verhindern, und wird mit einem Antiforgery-Token gepaart, das in der Datei der Bearbeitungsansicht (Views/Movies/Edit.cshtml) erzeugt wird. Die Datei der Bearbeitungsansicht generiert das Antifälschungstoken mit dem Form Tag Helper.
<form asp-action="Edit">
Das Form Tag Helper generiert ein verstecktes Antifälschungstoken, das mit dem von [ValidateAntiForgeryToken] generierten Antifälschungstoken in der Edit-Methode des Filmecontrollers übereinstimmen muss. Weitere Informationen finden Sie unter Prevent Cross-Site Request Forgery (XSRF/CSRF) Attacks in ASP.NET Core (Verhindern von websiteübergreifenden Anforderungsfälschungen (XSRF/CSRF) in ASP.NET Core).
Die HttpGet Edit-Methode akzeptiert den Filmparameter ID, sucht den Film mit der FindAsync-Methode von Entity Framework und gibt den ausgewählten Film an die Bearbeitungsansicht zurück. Wenn ein Film nicht gefunden werden kann, wird NotFound (HTTP 404) zurückgegeben.
// 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);
}
Als das Scaffolding-System die Bearbeitungsansicht erstellt hat, wurde die Movie-Klasse überprüft und Code zum Rendern der <label>- und <input>-Elemente für jede Eigenschaft der Klasse erstellt. Das folgende Beispiel zeigt die Bearbeitungsansicht, die vom Visual Studio-Gerüstsystem generiert wurde:
@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");}
}
Beachten Sie, dass die Ansichtsvorlage eine @model MvcMovie.Models.Movie-Anweisung am Anfang der Datei aufweist.
@model MvcMovie.Models.Movie gibt an, dass das Modell der Ansichtsvorlage vom Typ Movie ist.
Der Gerüstcode verwendet mehrere Methoden von Tag Helpern, um das HTML-Markup zu optimieren. Das Label-Tag-Helper zeigt den Namen des Feldes an („Title“, „ReleaseDate“, „Genre“ oder „Price“). Das Input-Tag-Helper rendert ein HTML-<input>-Element. Der Validation Tag Helper zeigt alle Validierungsmeldungen an, die dieser Eigenschaft zugeordnet sind.
Führen Sie die Anwendung aus und gehen Sie zur URL /Movies. Klicken Sie auf den Link Bearbeiten. Zeigen Sie im Browser den Quelltext für die Seite an. Der generierte HTML-Code für das <form>-Element wird unten dargestellt.
<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>
Die <input>-Elemente sind in einem HTML <form>-Element enthalten, dessen action-Attribut so festgelegt ist, dass an die URL /Movies/Edit/id gesendet wird. Die Formulardaten werden an den Server gesendet, wenn auf die Schaltfläche Save geklickt wird. Die letzte Zeile vor dem schließenden </form>-Element zeigt das ausgeblendete XSRF-Token, das durch das Hilfsprogramm für Formulartags generiert wurde.
Verarbeiten der POST-Anforderung
Die folgende Liste zeigt die [HttpPost]-Version der Edit-Aktionsmethode.
[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);
}
Das [ValidateAntiForgeryToken]-Attribut validiert das versteckte XSRF-Token, das vom Antifälschungstoken-Generator im Form Tag Helper erzeugt wurde.
Das Model-Binding-System übernimmt die übermittelten Formularwerte und erstellt ein Movie-Objekt, das als movie-Parameter übergeben wird. Die ModelState.IsValid-Eigenschaft stellt sicher, dass die im Formular übermittelten Daten verwendet werden können, um ein Movie-Objekt zu ändern (zu bearbeiten oder zu aktualisieren). Wenn die Daten gültig sind, werden sie gespeichert. Die aktualisierten (bearbeiteten) Filmdaten werden in der Datenbank gespeichert, indem die SaveChangesAsync-Methode des Datenbankkontexts aufgerufen wird. Nach dem Speichern der Daten leitet der Code den Benutzer an die Index-Aktionsmethode der MoviesController-Klasse weiter, die die Filmsammlung einschließlich der gerade vorgenommenen Änderungen anzeigt.
Bevor das Formular an den Server gesendet wird, überprüft die clientseitige Validierung alle Validierungsregeln in den Feldern. Sind Validierungsfehler vorhanden, wird eine Fehlermeldung angezeigt, und das Formular wird nicht gesendet. Wenn JavaScript deaktiviert ist, erfolgt keine clientseitige Validierung. Der Server erkennt jedoch, dass die übermittelten Formularwerte nicht gültig sind, und die Formularwerte werden wieder mit Fehlermeldungen angezeigt. Später in diesem Tutorial untersuchen wir die Modellvalidierung im Detail. Der Validation-Tag-Helper in der Ansichtsvorlage Views/Movies/Edit.cshtml übernimmt die Anzeige der entsprechenden Fehlermeldungen.
Alle HttpGet-Methoden im Movie-Controller folgen einem ähnlichen Muster. Sie erhalten ein Filmobjekt (oder eine Liste von Objekten im Fall von Index) und übergeben das Objekt (Modell) an die Ansicht. Die Create-Methode übergibt ein leeres Filmobjekt an die Ansicht Create. Alle Methoden, die Daten erstellen, bearbeiten, löschen oder in beliebiger Weise ändern, tun dies in der [HttpPost]-Überladung der Methode. Das Ändern von Daten in einer HTTP GET-Methode ist ein Sicherheitsrisiko. Das Ändern von Daten in einer HTTP GET-Methode verstößt auch gegen die Best Practices für HTTP und das architektonische REST-Muster, das angibt, dass GET-Anforderungen den Status Ihrer Anwendung nicht ändern dürfen. Mit anderen Worten sollte das Ausführen einer GET-Operation eine sichere Operation sein, die keine Nebenwirkungen hat und Ihre persistierten Daten nicht verändert.
Verwandte Inhalte
- Globalisierung und Lokalisierung
- Einführung in Tag Helpers
- Tag Helpers erstellen
- Verhindern von Angriffen durch websiteübergreifende Anforderungsfälschung (XSRF/CSRF) in ASP.NET Core
- Schützen Sie Ihren Controller vor Over-Posting
- ViewModels
- Hilfsprogramm für Formulartags
- Input-Tag-Helper
- Tag Helper für Beschriftungen
- Tag-Helper auswählen
- Validierungs-Tag-Helper