Zkoumání metod Edit a zobrazení pro úpravy

od Rick Anderson

Note

Aktualizovaná verze tohoto kurzu je k dispozici tady pomocí nejnovější verze Visual Studio. V novém kurzu se používá ASP.NET Core MVC,která oproti tomuto kurzu přináší řadu vylepšení.

V tomto kurzu se ASP.NET Core MVC s kontrolery a zobrazeními. Razor Pages je nová alternativa v ASP.NET Core, což je stránkový programovací model, který usnadňuje a produktivnější vytváření webového uživatelského rozhraní. Doporučujeme vyzkoušet si tento Razor Pages před verzí MVC. Kurz Razor Pages:

  • Je jednodušší postupovat podle těchto pokynů.
  • Zabývá se více funkcemi.
  • Je upřednostňovaný přístup pro vývoj nových aplikací.

V této části proberete vygenerované Edit metody a zobrazení akcí pro kontroler videí. Ale nejdřív potrváme krátkému odklonování, aby bylo datum vydání lépe podrobnější. Otevřete soubor Models\Movie.cs a přidejte zvýrazněné řádky zobrazené níže:

using System;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;

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

        [Display(Name = "Release Date")]
        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; }
        public decimal Price { get; set; }
    }

    public class MovieDBContext : DbContext
    {
        public DbSet<Movie> Movies { get; set; }
    }
}

Můžete také nastavit jazykovou verzi, která bude specifická jako tato:

[Display(Name = "Release Date")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }

V dalším kurzu budeme pokrývat tato Anotace . Atribut Display určuje, co se má zobrazit pro název pole (v tomto případě "Datum vydání" místo "ReleaseDate"). Atribut DataType určuje typ dat, v tomto případě je to datum, takže se nezobrazí informace o čase uložené v poli. Atribut DisplayFormat je potřeba pro chybu v prohlížeči Chrome, která vykresluje formáty data nesprávně.

Spusťte aplikaci a přejděte k Movies řadiči. Podržte ukazatel myši na odkaz pro Úpravy a zobrazte tak adresu URL, na kterou odkazuje.

EditLink_sm

Odkaz Edit byl vygenerován Html.ActionLink metodou v zobrazení Views\Movies\Index.cshtml :

@Html.ActionLink("Edit", "Edit", new { id=item.ID })

HTML. ActionLink

HtmlObjekt je pomocník, který je vystaven pomocí vlastnosti základní třídy System. Web. Mvc. WebViewPage . ActionLinkMetoda pomocné rutiny usnadňuje dynamické generování hypertextových odkazů HTML, které odkazují na metody akcí na řadičích. Prvním argumentem ActionLink metody je text odkazu, který se má vykreslit (například <a>Edit Me</a> ). Druhý argument je název metody akce, která se má vyvolat (v tomto případě Edit Akce). Konečný argument je anonymní objekt , který generuje data trasy (v tomto případě ID 4).

Vygenerovaný odkaz uvedený na předchozím obrázku je http://localhost:1234/Movies/Edit/4 . Výchozí trasa (vytvořená v App _ Start\RouteConfig.cs) přebírá vzor adresy URL {controller}/{action}/{id} . Proto ASP.NET převede http://localhost:1234/Movies/Edit/4 požadavek na Edit metodu akce Movies kontroleru s parametrem, který se ID rovná 4. Projděte si následující kód ze souboru App _ Start\RouteConfig.cs . Metoda MapRoute se používá ke směrování požadavků HTTP na správnou metodu kontroleru a akce a zadání volitelného parametru ID. Metoda MapRoute je také používána HtmlHelpers , například ActionLink k vygenerování adres URL za daný kontroler, akce a veškerá data trasy.

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", 
            id = UrlParameter.Optional }
    );
}

Můžete také předat parametry metody akce pomocí řetězce dotazu. Například adresa URL http://localhost:1234/Movies/Edit?ID=3 také předá parametr ID 3 Edit metodě Action Movies kontroleru.

EditQueryString

Otevřete Movies kontroler. Následující dvě Edit metody akce jsou uvedeny níže.

// GET: /Movies/Edit/5
public ActionResult Edit(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    Movie movie = db.Movies.Find(id);
    if (movie == null)
    {
        return HttpNotFound();
    }
    return View(movie);
}

// POST: /Movies/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for 
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include="ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
    if (ModelState.IsValid)
    {
        db.Entry(movie).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(movie);
}

Všimněte si, že druhá Edit Metoda Action předchází HttpPost atribut. Tento atribut určuje, že přetížení Edit metody lze vyvolat pouze pro požadavky post. Můžete použít HttpGet atribut na první metodu Edit, ale to není nutné, protože je to výchozí. (Odkazujeme na metody akcí, které implicitně přiřazují HttpGet atribut jako HttpGet metody.) Atribut BIND je dalším důležitým mechanismem zabezpečení, který brání v navýšení dat z více než po data do modelu. Do atributu BIND, který chcete změnit, byste měli zahrnout pouze vlastnosti. Můžete si přečíst informace o tom, jak přeposílat, tak i atribut BIND v poznámce zabezpečení. V jednoduchém modelu použitém v tomto kurzu budeme svázat všechna data v modelu. Atribut ValidateAntiForgeryToken se používá k tomu, aby se zabránilo padělání požadavku a bylo spárováno s @Html.AntiForgeryToken() v souboru pro úpravy (Views\Movies\Edit.cshtml), část je zobrazena níže:

@model MvcMovie.Models.Movie

@{
    ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()    
    <div class="form-horizontal">
        <h4>Movie</h4>
        <hr />
        @Html.ValidationSummary(true)
        @Html.HiddenFor(model => model.ID)

        <div class="form-group">
            @Html.LabelFor(model => model.Title, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Title)
                @Html.ValidationMessageFor(model => model.Title)
            </div>
        </div>

@Html.AntiForgeryToken() generuje skrytý formulář tokenu proti padělání, který se musí shodovat s Edit metodou Movies kontroleru. Další informace o padělání požadavků pro více lokalit (označované také jako XSRF nebo CSRF) najdete v tématu můj kurz XSRF/CSRF prevence v MVC.

HttpGet Edit Metoda přebírá parametr ID filmu, vyhledá film pomocí Find metody Entity Framework a vrátí vybraný film do zobrazení pro úpravy. Pokud se video nenajde, vrátí se HttpNotFound . Když systém generování uživatelského rozhraní vytvořil zobrazení pro úpravy, zkontroloval Movie třídu a vytvořil kód pro vykreslení <label> a <input> prvky pro každou vlastnost třídy. Následující příklad ukazuje zobrazení pro úpravy, které bylo vygenerováno systémem pro generování uživatelského rozhraní sady Visual Studio:

@model MvcMovie.Models.Movie

@{
    ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()    
    <div class="form-horizontal">
        <h4>Movie</h4>
        <hr />
        @Html.ValidationSummary(true)
        @Html.HiddenFor(model => model.ID)

        <div class="form-group">
            @Html.LabelFor(model => model.Title, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Title)
                @Html.ValidationMessageFor(model => model.Title)
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.ReleaseDate, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.ReleaseDate)
                @Html.ValidationMessageFor(model => model.ReleaseDate)
            </div>
        </div>
        @*Genre and Price 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>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Všimněte si, jak šablona zobrazení obsahuje @model MvcMovie.Models.Movie příkaz v horní části souboru – určuje, že zobrazení očekává, že model pro šablonu zobrazení bude typu Movie .

Generovaný kód používá několik pomocných metod pro zjednodušení značek HTML. Html.LabelForPomocník zobrazuje název pole ( " title " , " ReleaseDate " , " Žánr " nebo " Price " ). Html.EditorForPomoc vykreslí prvek HTML <input> . Html.ValidationMessageForPomocník zobrazuje všechny ověřovací zprávy přidružené k této vlastnosti.

Spusťte aplikaci a přejděte na adresu URL /Movies . Klikněte na odkaz Upravit . V prohlížeči zobrazte zdroj stránky. KÓD HTML prvku formuláře je uveden níže.

<form action="/movies/Edit/4" method="post">
   <input name="__RequestVerificationToken" type="hidden" value="UxY6bkQyJCXO3Kn5AXg-6TXxOj6yVBi9tghHaQ5Lq_qwKvcojNXEEfcbn-FGh_0vuw4tS_BRk7QQQHlJp8AP4_X4orVNoQnp2cd8kXhykS01" />  <fieldset class="form-horizontal">
      <legend>Movie</legend>

      <input data-val="true" data-val-number="The field ID must be a number." data-val-required="The ID field is required." id="ID" name="ID" type="hidden" value="4" />

      <div class="control-group">
         <label class="control-label" for="Title">Title</label>
         <div class="controls">
            <input class="text-box single-line" id="Title" name="Title" type="text" value="GhostBusters" />
            <span class="field-validation-valid help-inline" data-valmsg-for="Title" data-valmsg-replace="true"></span>
         </div>
      </div>

      <div class="control-group">
         <label class="control-label" for="ReleaseDate">Release Date</label>
         <div class="controls">
            <input class="text-box single-line" data-val="true" data-val-date="The field Release Date must be a date." data-val-required="The Release Date field is required." id="ReleaseDate" name="ReleaseDate" type="date" value="1/1/1984" />
            <span class="field-validation-valid help-inline" data-valmsg-for="ReleaseDate" data-valmsg-replace="true"></span>
         </div>
      </div>

      <div class="control-group">
         <label class="control-label" for="Genre">Genre</label>
         <div class="controls">
            <input class="text-box single-line" id="Genre" name="Genre" type="text" value="Comedy" />
            <span class="field-validation-valid help-inline" data-valmsg-for="Genre" data-valmsg-replace="true"></span>
         </div>
      </div>

      <div class="control-group">
         <label class="control-label" for="Price">Price</label>
         <div class="controls">
            <input class="text-box single-line" 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" type="text" value="7.99" />
            <span class="field-validation-valid help-inline" data-valmsg-for="Price" data-valmsg-replace="true"></span>
         </div>
      </div>

      <div class="form-actions no-color">
         <input type="submit" value="Save" class="btn" />
      </div>
   </fieldset>
</form>

<input>Prvky jsou v elementu HTML, <form> jehož action atribut je nastaven na hodnotu post na adresu URL /Movies/Edit . Data formuláře budou při kliknutí na tlačítko Uložit publikována na serveru. Druhý řádek ukazuje skrytý token XSRF generovaný @Html.AntiForgeryToken() voláním.

Zpracovává se žádost POST.

Následující výpis zobrazuje HttpPost verzi Edit metody Action.

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include="ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
    if (ModelState.IsValid)
    {
        db.Entry(movie).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(movie);
}

Atribut ValidateAntiForgeryToken ověřuje token XSRF generovaný @Html.AntiForgeryToken() voláním v zobrazení.

Pořadač modelu ASP.NET MVC přebírá hodnoty v zaúčtovaném formuláři a vytvoří Movie objekt, který se předává jako movie parametr. ModelState.IsValidOvěřuje, že data odeslaná ve formuláři lze použít k úpravě (úpravě nebo aktualizaci) Movie objektu. Pokud jsou data platná, data videa se uloží do Movies kolekce db ( MovieDBContext instance). Nová data videa se uloží do databáze voláním SaveChanges metody MovieDBContext . Po uložení dat kód přesměruje uživatele na Index metodu Action MoviesController třídy, která zobrazí kolekci filmů, včetně změn, které byly právě provedeny.

Jakmile ověřování na straně klienta určí, že hodnota pole není platná, zobrazí se chybová zpráva. Pokud je JavaScript zakázaný, ověřování na straně klienta je zakázané. Server ale zjistí, že odeslané hodnoty nejsou platné, a hodnoty formuláře se zobrazí znovu s chybovými zprávami.

Ověření se podrobněji prozkoumá v tomto kurzu.

U Html.ValidationMessageFor pomocníků v šabloně zobrazení Edit. cshtml se postará o zobrazení příslušných chybových zpráv.

abcNotValid

Všechny HttpGet metody následují podobně jako vzor. Získají filmový objekt (nebo seznam objektů, v případě Index ) a předávají model do zobrazení. CreateMetoda předá prázdný objekt filmu do zobrazení pro vytváření. Všechny metody, které vytvářejí, upravují, odstraňují nebo jinak upravují data, jsou v HttpPost přetížení metody. Úprava dat v metodě HTTP GET je bezpečnostní riziko, jak je popsáno v příspěvku na blogu ASP.NET #46 Tip – nepoužívejte odstranit propojení, protože vytvářejí bezpečnostní otvory. Úpravy dat v metodě GET také porušují osvědčené postupy HTTP a model REST architektury, který určuje, že požadavky GET by neměly měnit stav aplikace. Jinými slovy, provádění operace GET by mělo být bezpečná operace, která nemá žádné vedlejší účinky a neupravuje vaše trvalá data.

ověření jQuery pro jiné než anglické národní prostředí

Pokud používáte počítač v češtině, můžete tuto část přeskočit a přejít k dalšímu kurzu. Verzi globalizace tohoto kurzu si můžete stáhnout tady. Kurz o tom, jak se na mezinárodní základě vychází, najdete v tématu Nadeem 's ASP.NET MVC 5 – mezinárodní.

Note

aby bylo možné podporovat ověřování jQuery pro jiné než anglické národní prostředí, které používá čárku ( " , " ) pro desetinné čárky a formáty kalendářních dat mimo USA, je nutné zahrnout globalize.js a konkrétní jazykové verze/globalize.cultures.js souboru (z https://github.com/jquery/globalize ) a JavaScriptu pro použití Globalize.parseFloat . Z NuGet můžete získat ověřování jQuery bez angličtiny. (Neinstalujte globalizaci, pokud používáte anglické národní prostředí.)

  1. V nabídce nástroje klikněte na Správce balíčků NuGeta pak klikněte na Spravovat balíčky NuGet pro řešení.

  2. V levém podokně vyberte Procházet *. * (Podívejte se na obrázek níže.)

  3. Do vstupního pole zadejte * globalizace * *.

    Vyberte jQuery.Validation.Globalize , vyberte MvcMovie a klikněte na nainstalovat. Soubor Scripts\jquery.globalize\globalize.js se přidá do vašeho projektu. Složka * Scripts\jquery.globalize\cultures * bude obsahovat mnoho souborů JavaScriptu jazykové verze. Poznámka: instalace tohoto balíčku může trvat pět minut.

    Následující kód ukazuje úpravy souboru Views\Movies\Edit.cshtml:

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")

<script src="~/Scripts/globalize/globalize.js"></script>
<script src="~/Scripts/globalize/cultures/globalize.culture.@(System.Threading.Thread.CurrentThread.CurrentCulture.Name).js"></script>
<script>
    $.validator.methods.number = function (value, element) {
        return this.optional(element) ||
            !isNaN(Globalize.parseFloat(value));
    }
    $(document).ready(function () {
        Globalize.culture('@(System.Threading.Thread.CurrentThread.CurrentCulture.Name)');
    });
</script>
<script>
    jQuery.extend(jQuery.validator.methods, {
        range: function (value, element, param) {
            //Use the Globalization plugin to parse the value
            var val = Globalize.parseFloat(value);
            return this.optional(element) || (
                val >= param[0] && val <= param[1]);
        }
    });
    $.validator.methods.date = function (value, element) {
        return this.optional(element) ||
            Globalize.parseDate(value) ||
            Globalize.parseDate(value, "yyyy-MM-dd");
    }
</script>
}

Chcete-li se vyhnout opakování tohoto kódu v každém zobrazení pro úpravy, můžete ho přesunout do souboru rozložení. Pokud chcete optimalizovat stažení skriptu, přečtěte si téma moje výukové sdružování a minifikace.

Další informace najdete v části ASP.NET MVC 3 – mezinárodní využití a ASP.NET MVC 3 – část 2 (NerdDinner).

Pokud se vám dočasná oprava nedaří ověřit ve svém národním prostředí, můžete vašemu počítači vynutit použití anglické angličtiny nebo můžete v prohlížeči zakázat JavaScript. Chcete-li vynutit, aby počítač používal anglickou angličtinu, můžete přidat prvek globalizace do kořenového souboru projektu web.config . Následující kód ukazuje prvek globalizace s jazykovou verzí nastavenou na USA angličtinu.

<system.web>
    <globalization culture ="en-US" />
    <!--elements removed for clarity-->
  </system.web>

V dalším kurzu implementujeme funkce vyhledávání.