Create und Edit Update
Das folgende Beispiel erstellt ändert das Create
Formular in ein Edit Formular für Artikel.
Dabei wird folgend die View Edit als Eingabe-Formular zum
Erstellen neuer Datensätze verwendet, aber auch als reines
Update-Eingabeformular.
Öffnen der View
Das View-Formular wird entweder geöffnet über die
Controller-Action: Create() oder über Edit(ID)
Create
Im vorigen Tutorial wurde eine New-Methode und ein New-View
Formular verwendet.
Um der allgemeinen CRUD Definition
(Create-Refresh-Update-Delete) zu folgen wurde das Erstellen in Create
umbenannt.
Dabei öffnet Create() das Eingabeformular. Da das
Eingeben von Neuen Daten fast gleich ist zur Änderungs-Eingabe von Daten, wird
nur noch ein Formular mit dem Namen View-Edit verwendet.
Somit öffnet die Create() Methode im Controller das
Edit-Formular mit einem leeren Artikel
Create Methode
Im MVC Controller befindet sich die Methode Create() zum
Öffnen eines leeren Erstellungs-Formulars.
public IActionResult Create()
{
//----< Create New() >----
//*leeres
eingabe-formular fuer neuen Datensatz
IEnumerable<ModelBase_Produktgruppe > produktgruppen =
_context.tblBase_Produktgruppen.ToList();
ViewModels.ViewModel_Artikel_Edit
viewModel = new
ViewModels.ViewModel_Artikel_Edit
{
Artikel = new Model__Artikel(),
Produktgruppen =
produktgruppen
};
return View("Edit",viewModel);
//----</ Create New() >----
}
|
Edit(ID) Methode
Wird das Formular mit Edit geöffnet, dann muss man eine
ID mitübergeben.
Artikel = await _context.tbl_Artikel.SingleOrDefaultAsync(a => a.ID_Artikel ==
id),
|
Die ID wird aus der URL Adresse wie Artikel/Edit/5 als
Parameter übernommen
C# Code zum laden des Edit-Formulars
// GET: Produktgruppens/Edit/5
public async Task<IActionResult> Edit(int? id)
{
//--------< Edit(ID) >--------
//*open and load Edit View Form
if (id == null)
{
return NotFound();
}
//----<
Edit or Create >----
//*leeres
eingabe-formular fuer neuen Datensatz
IEnumerable<ModelBase_Produktgruppe> dropdown_produktgruppen =
_context.tblBase_Produktgruppen.ToList();
ViewModels.ViewModel_Artikel_Edit data = new ViewModels.ViewModel_Artikel_Edit
{
Artikel = await _context.tbl_Artikel.SingleOrDefaultAsync(a => a.ID_Artikel ==
id),
Produktgruppen =
dropdown_produktgruppen
};
return View("Edit", data);
//--------</ Edit(ID) >--------
}
|
Rücksenden des Edit-Formulars
Post-Back des Eingabe-Formulars
Wenn man ein ausgefülltes Erstellungs-Formular mit Save
absendet, dann werden die Formular-Daten vom Browser zum MVC Controller im IIS
Server gesandt.
Das Edit-Formular wird für Create als auch für
Edit-Vorgänge jeweils zur Edit-Methode im Controller gesandt.
Zur eindeutigeren Unterscheidung im Code hab ich die
Postback Edit(..) Methode deshalb auch Edit_Postback genannt.
Diese Action muss in die Form asp-action=Edit_Postback
geschrieben werden.
/Views/Artikel/Edit.cshtml
@model
ArtikelWeb.ViewModels.ViewModel_Artikel_Edit
..
<div class="row">
<div class="col-md-4">
<form asp-action="Edit_Postback">
..
</form>
</div>
</div>
|
Eingabe-Edit-Formular
Beim Edit Formular wird ein leerer Datensatz oder ein
einzelner Datensatz angezeigt.
Damit dieser eindeutig verarbeitet werden kann, muss die
ID als Hidden-Feld unsichtbar hinzugefügt werden.
<input type="hidden" asp-for="Artikel.ID_Artikel" />
@Html.AntiForgeryToken()
|
Das Feld wird mit der ID als Integer geladen. Beim Laden
über eine Create-Methode muss deshalb darauf geachtet werden, dass hier anstatt
Null eine 0 eingespeichert wird.
Ansonsten entsteht beim Versuch das Formular zu
speichern ein Validierungs-fehler (null zu int).
Dieseses Laden wird dadurch erreicht, indem man in
Create() einen leeren Artikel hinzufügt.
Artikel = new Model__Artikel(),
|
@model
ArtikelWeb.ViewModels.ViewModel_Artikel_Edit
@*ArtikelWeb.Models.Artikel*@
@{
ViewData["Title"] = "Edit or New";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>New</h2>
<h4>Artikel</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit_Postback">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Artikel.ID_Artikel" />
@Html.AntiForgeryToken()
<div class="form-group">
<label asp-for="Artikel.Artikelname" class="control-label"></label>
<input asp-for="Artikel.Artikelname" class="form-control" />
<span asp-validation-for="Artikel.Artikelname" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Artikel.Text_Content" class="control-label"></label>
<input asp-for="Artikel.Text_Content" class="form-control" />
<span asp-validation-for="Artikel.Text_Content" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Artikel.IDBase_Produktgruppe" class="control-label"></label>
<select asp-for="Artikel.IDBase_Produktgruppe"
class="form-control"
asp-items="@(new
SelectList(Model.Produktgruppen,"IDBase_Produktgruppe", "Produktgruppe"))"></select>
</div>
<div class="form-group">
<label asp-for="Artikel.dtEdit" class="control-label"></label>
<label asp-for="Artikel.dtEdit" class="control-label" />
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
|
Edit_Postback
Normalerweise wird das Formular an die Edit(Formulardaten)
Methode gesendet.
Damit man die Methode aber besser unterscheiden kann,
habe ich die Methode Edit_Postback genannt.
Die Daten werden als HttpPost gesendet und nicht über HttpGet.
Deshalb setzt man vor die Methode das Attribut [HttpPost]
Als Rücksende-Daten werden die Formulardaten im
Parameter übergeben.
ASP.Net MVC bindet dabei die Daten automatisch an den
Typ, welcher als Rückgabeparameter definiert wird. In diesem Fall werden die einzelnen Parameter
automatisch in ein ViewModel Artikel_Edit zugeordnet
DataBinding / Formdata Binding
ViewModels.ViewModel_Artikel_Edit
formData
|
Die Daten werden nur verarbeitet, wenn die Formular-Validierung
richtig ist. Das heißt, dass alle Eingabedaten den Vorgaben entsprechen wir
Zahl, Textlänge, Null und Integer.
Die Gültigkeit wird mit ModelState abgefragt.
if (ModelState.IsValid) {..}
|
Wenn das Formular von Create New kommt, dann ist die ID=0.
Dann muss wie in dem vorigen Tutorial der Datensatz neu erstellt werden.
if (id==0)
{
//----<
Create() >----
//*add
a new dataset
_context.Add(data);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
//----</
Create() >----
}
|
Wenn eine ID Vorhanden ist, dann werden die Daten in der
Datenbank geändert.
Hierzu wird aus der Datenbank-Schnittstelle das Datenset
mit der passenden ID geholt und dann alle einzelnen Eigenschaften übernommen.
Anschliessend wird mit SaveChangesAsync() die Daten von
lokalen Context-Zwischenspeicher zur SQL Server übernommen und aktualisert.
else
{
//----<
Update() >----
//*all
Datafields
//*_context.Update(data);
//--<
fields >--
//*save
defined fields
var dataInDb =
_context.tbl_Artikel.Single(a => a.ID_Artikel == id);
dataInDb.Artikelname = data.Artikelname;
dataInDb.Text_Content = data.Text_Content ;
dataInDb.IDBase_Produktgruppe =
data.IDBase_Produktgruppe ;
dataInDb.dtEdit = DateTime.Now;
//--</
fields >--
await
_context.SaveChangesAsync();
//----</
Update() >----
}
|
Man kann einfacher per Update(Dataset) gleich das lokalen
Speicher anpassen, aber dabei werden immer alle Eigenschaften übernommen.
//*all Datafields
//*_context.Update(data);
|
Edit Postback
Code in /Controller
// POST:
Produktgruppens/Edit/5
// To
protect from overposting attacks, please enable the specific properties you
want to bind to, for
//public async Task<IActionResult> Edit(int id,
[Bind("IDProduktgruppe,Produktgruppe")] ModelBase_Produktgruppe
produktgruppen)
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult>
Edit_Postback(int id,
ViewModels.ViewModel_Artikel_Edit formData )
{
//------------< Edit_Postback()
>------------
Model__Artikel data =
formData.Artikel;
if (id != data.ID_Artikel)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
if (id==0)
{
//----< Create() >----
//*add a new dataset
_context.Add(data);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
//return
RedirectToAction("Index", "Artikel");
//return View(data);
//----</ Create()
>----
}
else
{
//----< Update()
>----
//*all Datafields
//*_context.Update(data);
//--< fields >--
//*save defined fields
var dataInDb =
_context.tbl_Artikel.Single(a => a.ID_Artikel == id);
dataInDb.Artikelname
= data.Artikelname;
dataInDb.Text_Content
= data.Text_Content ;
dataInDb.IDBase_Produktgruppe = data.IDBase_Produktgruppe ;
dataInDb.dtEdit = DateTime.Now;
//--</ fields >--
await _context.SaveChangesAsync();
//----</ Update() >----
} }
catch (DbUpdateConcurrencyException)
{
//if
(!ProduktgruppenExists(produktgruppen.IDBase_Produktgruppe))
//{
//
return NotFound();
//}
//else
{
throw;
}
}
return RedirectToAction(nameof(Index));
//return View(nameof(New));
}
return View(nameof(Index));
//------------<
Edit_Postback() >------------
}
|
Visual
Studio: Controllers/ArtikelController.cs in C#