Metody kontrolera i widoki w programie ASP.NET CoreController methods and views in ASP.NET Core

Przez Rick AndersonBy Rick Anderson

Mamy dobry początek aplikacji filmu, ale prezentacji nie jest najlepszym rozwiązaniem, na przykład ReleaseDate powinna być dwa słowa.We have a good start to the movie app, but the presentation isn't ideal, for example, ReleaseDate should be two words.

Widok indeksu: Data wydania jest jedno słowo (bez spacji) i każdy film Data wydania zawiera godzinę 12: 00

Otwórz Models/Movie.cs pliku i Dodaj wyróżnione wiersze, które przedstawiono poniżej:Open the Models/Movie.cs file and add the highlighted lines shown below:

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; }
    }
}

Omówione DataAnnotations w następnym samouczku.We cover DataAnnotations in the next tutorial. Wyświetlić atrybut określa, co będzie wyświetlone nazwy pola (w tym przypadku "Data wydania" zamiast "ReleaseDate").The Display attribute specifies what to display for the name of a field (in this case "Release Date" instead of "ReleaseDate"). DataType atrybut określa typ danych (Data), co nie jest wyświetlane informacje o godzinie, w tym polu.The DataType attribute specifies the type of the data (Date), so the time information stored in the field isn't displayed.

[Column(TypeName = "decimal(18, 2)")] Wymagana jest adnotacja danych, dzięki czemu można poprawnie mapowane na platformy Entity Framework Core Price walutę w bazie danych.The [Column(TypeName = "decimal(18, 2)")] data annotation is required so Entity Framework Core can correctly map Price to currency in the database. Aby uzyskać więcej informacji, zobacz typy danych.For more information, see Data Types.

Przejdź do Movies kontrolera i przytrzymasz wskaźnik myszy Edytuj link, aby wyświetlić docelowy adres URL.Browse to the Movies controller and hold the mouse pointer over an Edit link to see the target URL.

Okno przeglądarki z myszy nad łącze edycji i łącze adres Url https://localhost:5001/Movies/Edit/5 jest wyświetlany

Edytuj, szczegóły, i Usuń łącza są generowane przez Pomocnik tagu kotwicy MVC Core, w Views/Movies/Index.cshtml pliku.The Edit, Details, and Delete links are generated by the Core MVC Anchor Tag Helper in the Views/Movies/Index.cshtml file.

        <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>

Pomocnicy tagów umożliwiają uczestniczenie kodu po stronie serwera w tworzeniu i renderowaniu elementów HTML w plikach Razor.Tag Helpers enable server-side code to participate in creating and rendering HTML elements in Razor files. W powyższym kodzie AnchorTagHelper dynamicznie generuje kod HTML href wartość atrybutu z id metody i wyznaczać trasy akcji kontrolera. Możesz użyć Wyświetl źródło ze swojej ulubionej przeglądarce lub użyj narzędzia dla deweloperów do sprawdzenia wygenerowany kod znaczników.In the code above, the AnchorTagHelper dynamically generates the HTML href attribute value from the controller action method and route id. You use View Source from your favorite browser or use the developer tools to examine the generated markup. Poniżej przedstawiono część wygenerowanego kodu HTML:A portion of the generated HTML is shown below:

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

Odwołaj format routingu w Startup.cs pliku:Recall the format for routing set in the Startup.cs file:

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
});

Tłumaczy platformy ASP.NET Core https://localhost:5001/Movies/Edit/4 na żądanie, aby Edit metody akcji Movies kontroler z parametrem Id 4.ASP.NET Core translates https://localhost:5001/Movies/Edit/4 into a request to the Edit action method of the Movies controller with the parameter Id of 4. (Metody kontrolera są również znane jako metody akcji).(Controller methods are also known as action methods.)

Pomocników tagów są jednymi z najbardziej popularnych nowe funkcje w programie ASP.NET Core.Tag Helpers are one of the most popular new features in ASP.NET Core. Aby uzyskać więcej informacji, zobacz dodatkowe zasoby.For more information, see Additional resources.

Otwórz Movies kontrolera i zbadaj dwa Edit metody akcji.Open the Movies controller and examine the two Edit action methods. Poniższy kod przedstawia HTTP GET Edit metody, która pobiera film i wypełnia formularz edycji generowane przez Edit.cshtml pliku Razor.The following code shows the HTTP GET Edit method, which fetches the movie and populates the edit form generated by the Edit.cshtml Razor file.

// 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);
}

Poniższy kod przedstawia HTTP POST Edit metody, która przetwarza wartości przesłanych film:The following code shows the HTTP POST Edit method, which processes the posted movie values:

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

    var movie = await _context.Movie.SingleOrDefaultAsync(m => m.ID == id);
    if (movie == null)
    {
        return NotFound();
    }
    return View(movie);
}

Poniższy kod przedstawia HTTP POST Edit metody, która przetwarza wartości przesłanych film:The following code shows the HTTP POST Edit method, which processes the posted movie values:

// 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);
}

[Bind] Atrybut jest jednym ze sposobów, aby zapewnić ochronę przed polegającymi.The [Bind] attribute is one way to protect against over-posting. Powinien zawierać tylko właściwości w [Bind] atrybut, który chcesz zmienić.You should only include properties in the [Bind] attribute that you want to change. Aby uzyskać więcej informacji, zobacz chronić kontroler z nadmiernego księgowania.For more information, see Protect your controller from over-posting. Modele widoków zawierają alternatywne podejście, aby uniknąć nadmiernego ogłaszania.ViewModels provide an alternative approach to prevent over-posting.

Zwróć uwagę, drugi Edit metody akcji jest poprzedzony [HttpPost] atrybutu.Notice the second Edit action method is preceded by the [HttpPost] attribute.

[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);
}
// 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);
}

HttpPost Atrybut określa, że to Edit może być wywołana metoda tylko dla POST żądań.The HttpPost attribute specifies that this Edit method can be invoked only for POST requests. Można zastosować [HttpGet] atrybutu do pierwszego Edytuj metodę, ale nie jest konieczne ponieważ [HttpGet] jest ustawieniem domyślnym.You could apply the [HttpGet] attribute to the first edit method, but that's not necessary because [HttpGet] is the default.

ValidateAntiForgeryToken Atrybut jest używany do zapobiegania fałszowaniu żądania i parę przy użyciu tokenu zabezpieczającego przed sfałszowaniem generowane w pliku widoku edycji (Views/Movies/Edit.cshtml).The ValidateAntiForgeryToken attribute is used to prevent forgery of a request and is paired up with an anti-forgery token generated in the edit view file (Views/Movies/Edit.cshtml). Edytuj plik widoku generuje token zabezpieczający przed sfałszowaniem z Pomocnik tagu formularza.The edit view file generates the anti-forgery token with the Form Tag Helper.

<form asp-action="Edit">

Pomocnik tagu formularza generuje ukryte token zabezpieczający przed sfałszowaniem, które muszą być zgodne [ValidateAntiForgeryToken] wygenerowany token zabezpieczający przed sfałszowaniem w Edit metody kontrolera filmów.The Form Tag Helper generates a hidden anti-forgery token that must match the [ValidateAntiForgeryToken] generated anti-forgery token in the Edit method of the Movies controller. Aby uzyskać więcej informacji, zobacz ochrona przed fałszerstwem żądań.For more information, see Anti-Request Forgery.

HttpGet Edit Metoda przyjmuje filmu ID parametru wyszukuje filmu używający narzędzia Entity Framework FindAsync metodę i zwraca wybrany film do widoku edycji.The HttpGet Edit method takes the movie ID parameter, looks up the movie using the Entity Framework FindAsync method, and returns the selected movie to the Edit view. Jeśli nie można odnaleźć filmu, NotFound (HTTP 404) jest zwracany.If a movie cannot be found, NotFound (HTTP 404) is returned.

// 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);
}

Podczas tworzenia widoku edycji system scaffoldingu zbadane Movie klasy i utworzony kod do renderowania <label> i <input> elementy dla każdej właściwości klasy.When the scaffolding system created the Edit view, it examined the Movie class and created code to render <label> and <input> elements for each property of the class. Poniższy przykład przedstawia widok edycji, który został wygenerowany przez system scaffoldingu programu Visual Studio:The following example shows the Edit view that was generated by the Visual Studio scaffolding system:

@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");}
}

Zwróć uwagę, jak szablon widoku ma @model MvcMovie.Models.Movie instrukcji w górnej części pliku.Notice how the view template has a @model MvcMovie.Models.Movie statement at the top of the file. @model MvcMovie.Models.Movie Określa, czy widok oczekuje modelu dla widoku szablonu typu Movie.@model MvcMovie.Models.Movie specifies that the view expects the model for the view template to be of type Movie.

Utworzony szkielet kodu używa kilka metod pomocniczych znaczników uprościć kod znaczników HTML.The scaffolded code uses several Tag Helper methods to streamline the HTML markup. Pomocnik tagu etykiet Wyświetla nazwę pola ("Title", "ReleaseDate", "Gatunku" lub "Price").The - Label Tag Helper displays the name of the field ("Title", "ReleaseDate", "Genre", or "Price"). Pomocnik tagu dane wejściowe renderowanie kodu HTML <input> elementu.The Input Tag Helper renders an HTML <input> element. Pomocnik tagu weryfikacji wyświetla komunikaty weryfikacji skojarzony z tej właściwości.The Validation Tag Helper displays any validation messages associated with that property.

Uruchom aplikację, a następnie przejdź do /Movies adresu URL.Run the application and navigate to the /Movies URL. Kliknij przycisk Edytuj łącza.Click an Edit link. W przeglądarce Wyświetl źródło strony.In the browser, view the source for the page. Wygenerowany kod HTML dla <form> element znajdują się poniżej.The generated HTML for the <form> element is shown below.

<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>

<input> Elementy znajdują się w HTML <form> elementu którego action ma ustawioną wartość atrybutu Opublikuj /Movies/Edit/id adresu URL.The <input> elements are in an HTML <form> element whose action attribute is set to post to the /Movies/Edit/id URL. Dane formularza zostaną opublikowane na serwerze po Save przycisku.The form data will be posted to the server when the Save button is clicked. Ostatni wiersz przed tagiem zamykającym </form> element pokazuje ukryte XSRF token generowane przez Pomocnik tagu formularza.The last line before the closing </form> element shows the hidden XSRF token generated by the Form Tag Helper.

Przetwarzanie żądania POSTProcessing the POST Request

Poniższej przedstawiono listę [HttpPost] wersję Edit metody akcji.The following listing shows the [HttpPost] version of the Edit action method.

[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);
}
// 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);
}

[ValidateAntiForgeryToken] Atrybut weryfikuje ukryte XSRF token wygenerowany przez generator tokenów zabezpieczających przed sfałszowaniem w Pomocnik tagu formularzaThe [ValidateAntiForgeryToken] attribute validates the hidden XSRF token generated by the anti-forgery token generator in the Form Tag Helper

Wiązanie modelu systemu przyjmuje wartości przesłanego formularza i tworzy Movie obiektu, który jest przekazywany jako movie parametru.The model binding system takes the posted form values and creates a Movie object that's passed as the movie parameter. ModelState.IsValid Metoda sprawdza, czy dane dostarczone w formie może służyć do modyfikowania (edycji lub aktualizacja) Movie obiektu.The ModelState.IsValid method verifies that the data submitted in the form can be used to modify (edit or update) a Movie object. Jeśli dane są prawidłowe, są zapisywane.If the data is valid, it's saved. Dane zaktualizowane movie (edytowanych) są zapisywane w bazie danych przez wywołanie metody SaveChangesAsync metoda kontekst bazy danych.The updated (edited) movie data is saved to the database by calling the SaveChangesAsync method of database context. Po zapisaniu danych, kod przekierowuje użytkownika do Index metody akcji MoviesController klasy, która wyświetla kolekcji film, w tym zmiany wprowadzone przed chwilą.After saving the data, the code redirects the user to the Index action method of the MoviesController class, which displays the movie collection, including the changes just made.

Zanim opublikowania formularza z serwerem, weryfikacji po stronie klienta sprawdza reguł sprawdzania poprawności w polach.Before the form is posted to the server, client-side validation checks any validation rules on the fields. Jeśli występują błędy sprawdzania poprawności, jest wyświetlany komunikat o błędzie i formularza nie jest opublikowane.If there are any validation errors, an error message is displayed and the form isn't posted. Obsługa języka JavaScript jest wyłączona, nie będziesz mieć weryfikacji po stronie klienta, ale serwer wykryje opublikowanych wartości, które nie są prawidłowe i wartości formularza zostanie wyświetlony ponownie, z komunikatów o błędach.If JavaScript is disabled, you won't have client-side validation but the server will detect the posted values that are not valid, and the form values will be redisplayed with error messages. W dalszej części tego samouczka omówiony sprawdzania poprawności modelu bardziej szczegółowo.Later in the tutorial we examine Model Validation in more detail. Pomocnik tagu weryfikacji w Views/Movies/Edit.cshtml Wyświetl szablon dba o wyświetlaniu odpowiedniego komunikatu o błędzie.The Validation Tag Helper in the Views/Movies/Edit.cshtml view template takes care of displaying appropriate error messages.

Edytuj widok: Wyjątek dla nieprawidłowej wartości cen ABC, informacja o tym, że pola Cena musi być liczbą.

Wszystkie HttpGet metodami w kontrolerze filmu wykonaj podobny wzorzec.All the HttpGet methods in the movie controller follow a similar pattern. Staną się obiekt filmu (lub listę obiektów, w przypadku Index) i przekazać obiekt (model) do widoku.They get a movie object (or list of objects, in the case of Index), and pass the object (model) to the view. Create Metoda przekazuje obiekt pusty filmu w taki sposób, aby Create widoku.The Create method passes an empty movie object to the Create view. Wszystkie metody, które tworzenie, edytowanie, usuwanie lub inny sposób modyfikować danych, należy więc w [HttpPost] przeciążenia metody.All the methods that create, edit, delete, or otherwise modify data do so in the [HttpPost] overload of the method. Modyfikowanie danych w HTTP GET metoda stanowi zagrożenie bezpieczeństwa.Modifying data in an HTTP GET method is a security risk. Modyfikowanie danych w HTTP GET metoda również narusza HTTP najlepszych rozwiązań i architektury REST wzorca, który określa, że żądania GET nie powinno się zmieniać stan aplikacji.Modifying data in an HTTP GET method also violates HTTP best practices and the architectural REST pattern, which specifies that GET requests shouldn't change the state of your application. Innymi słowy wykonywanie operacji GET powinna być bezpieczne operacji, która ma żadnych efektów ubocznych i nie modyfikuje utrwalonych danych.In other words, performing a GET operation should be a safe operation that has no side effects and doesn't modify your persisted data.

Dodatkowe zasobyAdditional resources