ASP.NET MVC v praxi od A do Z, 7. díl – CRUD II. část
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

ASP.NET MVC v praxi od A do Z, 7. díl – CRUD II. částASP.NET MVC v praxi od A do Z, 7. díl – CRUD II. část

 

ASP.NET MVC v praxi od A do Z, 7. díl – CRUD II. část

Google       Google       31. 8. 2009       17 832×

Jak jsme si posledně slíbili, dnes doděláme podporu pro přidávání a mazání večeří.

Začneme vytvořením podpory pro přidávání večeří a s tím související akční metodou Create.

Akční metoda Create

HTTP-GET

Nejdříve vytvoříme GET verzi naší nové metody, která se zavolá tehdy, když uživatel zadá URL „/Dinners/Create“, a vygeneruje formulář pro přidání nové večeře. Není tady moc co řešit, vše potřebné už umíme, takže do DinnersControlleru jen přidáme následující metodu:

// GET: /Dinners/Create
public ActionResult Create()
{
    Dinner dinner = new Dinner()
    {
        EventDate = DateTime.Now.AddDays(7)
    };

    return View(dinner);
}

Tato metoda vytvoří nový Dinner objekt s předem nastaveným časem konání večeře (to aby měl uživatel představu, v jakém formátu má datum zadat) a pak vrátí view, který teď přidáme.

Už tradičně klikneme pravým tlačítkem dovnitř metody, zvolíme položku „Add View“ a dialog nastavíme podle obrázku:

Vygenerovanou šablonu rovnou upravíme tak, aby vypadala následovně (je téměř identická s tou, kterou jsme vytvořili pro upravování večeří):

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<NerdDinner.Models.Dinner>" %>

<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
     Vytvořit večeři
</asp:Content>

<asp:Content ID="Main" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Vytvořit večeři</h2>

    <%=Html.ValidationSummary("Opravte prosím všechny chyby a zkuste to znovu.") %>
 
    <% using (Html.BeginForm()) {%>
  
        <fieldset>
            <p>
                <label for="Title">Název:</label>
                <%= Html.TextBox("Title") %>
                <%= Html.ValidationMessage("Title", "*") %>
            </p>
            <p>
                <label for="EventDate">Datum:</label>
                <%=Html.TextBox("EventDate") %>
                <%=Html.ValidationMessage("EventDate", "*") %>
            </p>
            <p>
                <label for="Description">Popis:</label>
                <%=Html.TextArea("Description") %>
                <%=Html.ValidationMessage("Description", "*") %>
            </p>
            <p>
                <label for="Address">Adresa:</label>
                <%=Html.TextBox("Address") %>
                <%=Html.ValidationMessage("Address", "*") %>
            </p>
            <p>
                <label for="Country">Země:</label>
                <%=Html.TextBox("Country") %>
                <%=Html.ValidationMessage("Country", "*") %>
            </p>
            <p>
                <label for="ContactPhone">Telefon:</label>
                <%=Html.TextBox("ContactPhone") %>
                <%=Html.ValidationMessage("ContactPhone", "*") %>
            </p>            
            <p>
                <label for="Latitude">Zem. šířka:</label>
                <%=Html.TextBox("Latitude") %>
                <%=Html.ValidationMessage("Latitude", "*") %>
            </p>
            <p>
                <label for="Longitude">Zem. délka:</label>
                <%=Html.TextBox("Longitude") %>
                <%=Html.ValidationMessage("Longitude", "*") %>
            </p>
            <p>
                <input type="submit" value="Uložit"/>
            </p>
        </fieldset>
    <% } 
%>
</asp:Content>

A je to, během pár minut jsme vytvořili šablonu pro přidávání nových večeří! Teď je na řadě vytvořit POST verzi metody Create.

HTTP-POST

Tato verze metody Create se zavolá ve chvíli, kdy uživatel klikne na tlačítko „Uložit“ ve formuláři. Stejně jako v případě upravování večeří, i zde nejdříve přidáme přetíženou verzi akční metody Create označenou atributem „AcceptVerbs“:

// POST: /Dinners/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Dinner dinner)
{
    // ...
}

Tím, že tato metoda přijímá Dinner parametr, docílíme toho, že ASP.NET MVC automaticky vezme zadaná data ve formuláři, vytvoří objekt typu Dinner a ten předá naší metodě, která ho zkontroluje a, pokud bude vše v pořádku, uloží do databáze. Implementace metody bude vypadat takto:

// POST: /Dinners/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Dinner dinner)
{
    if (ModelState.IsValid)
    {
        try
        {
            dinner.HostedBy = "Někdo";

            dinnerRepository.Add(dinner);
            dinnerRepository.Save();

            return RedirectToAction("Details", new { id = dinner.DinnerID });
        }
        catch
        {
            ModelState.AddRuleViolations(dinner.GetRuleViolations());
        }
    }

    return View(dinner);
}

Abychom viděli, jak to funguje, aplikaci spustíme a zadáme URL „/Dinners/Create“:

Všimněte si, že naše už dávno vytvořená validační logika funguje bezchybně i během vytváření večeří. Pořadatele večeře (vlastnost HostedBy) nastavujeme natvrdo v kódu, protože v budoucnu se budou moci uživatelé registrovat a jméno se bude doplňovat dynamicky podle právě přihlášeného uživatele.

Když opravíme všechny chyby a klikneme na tlačítko „Uložit“, vše by mělo proběhnout v pořádku a aplikace nás přesměruje na stránku s detaily nové večeře.

Akční metoda Delete

Díky této metodě, jak už název napovídá, budeme moci večeře mazat. Nejdříve implementujeme HTTP-GET, pak HTTP-POST.

HTTP-GET

Tato verze metody se zavolá, když uživatel zadá URL „/Dinners/Delete/{id}“, implementace bude vypadat takto:

// GET: /Dinners/Delete/1
public ActionResult Delete(int id)
{
    Dinner dinner = dinnerRepository.GetDinner(id);

    if (dinner == null)
        return View("NotFound");
    else
        return View(dinner);
}

Pokud nebude večeře, kterou chceme smazat, existovat, použijeme NotFound view, v opačném případě se použije Delete view, který teď vytvoříme. Tento krok děláme asi posté – jednoduše klikneme dovnitř metody Delete, zvolíme „Add View“ a dialog nastavíme podle obrázku:

Vytvoří se nám téměř prázdná šablona, kterou trochu doplníme, abychom dostali něco takového, jako ukazuje následující kód:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<NerdDinner.Models.Dinner>" %>

<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
    Potvrzení smazání:  <%=Html.Encode(Model.Title) %>
</asp:Content>

<asp:Content ID="Main" ContentPlaceHolderID="MainContent" runat="server">

    <h2>
        Potvrzení smazání
    </h2>

    <div>
        <p>Skutečně chcete smazat večeři s názvem: 
           <i> <%=Html.Encode(Model.Title) %>? </i> 
        </p>
    </div>
    
    <% using (Html.BeginForm()) {  %>
        <input name="confirmButton" type="submit" value="Smazat" />        
    <% } %>
     
</asp:Content>

Hned to můžeme na nějaké večeři vyzkoušet (URL ve tvaru „/Dinners/Delete/{id}“):

HTTP-POST

Teď máme stránku, která zobrazuje potvrzení ke smazání. Když uživatel klikne na tlačítko „Smazat“, zavolá se POST verze naší metody, to už teď jistě víte. Proto tuto přetíženou metodu hned vytvoříme, bude to opět záležitost minutky. Implementace je jednoduchá, zase vše zařídí repository třída, kterou jsme si kdysi napsali:

// POST: /Dinners/Delete/1
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Delete(int id, string confirmButton)
{

    Dinner dinner = dinnerRepository.GetDinner(id);

    if (dinner == null)
        return View("NotFound");

    dinnerRepository.Delete(dinner);
    dinnerRepository.Save();

    return View("Deleted");
}

Budeme potřebovat vytvořit nový view, který zobrazí zprávu o tom, že smazání proběhlo úspěšně. Klikneme dovnitř metody pravým tlačítkem a zvolíme „Add View“ (jaké to překvapení). Ovšem je tady malá změna, nic nebudeme nastavovat, políčko „Create a strongly-typed view“ by mělo být odškrtlé. Jen přejmenujeme šablonu na „Deleted“ a klikneme na tlačítko „Add“. Teď do šablony přidáme takovéto HTML:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
    Večeře smazána
</asp:Content>

<asp:Content ID="Main" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Večeře smazána</h2>

    <div>
        <p>Večeře byla úspěšně smazána.</p>
    </div>
    
    <div>
        <p><a href="/dinners">Klikněte pro zobrazení chystaných večeří</a></p>
    </div>
    
</asp:Content>

Když teď večeři smažeme, všechno proběhne v pořádku:

Bezpečnost při databindingu

Ukázali jsme si, jak je pomocí metody UpdateModel snadné automaticky vytáhnout zadaná data z formuláře a vytvořit pomocí nich nový Dinner objekt. Stejně jako spousta dalších věcí ve webovém programování, i toto přináší určitá rizika – uživatel ani náhodou nesmí být schopný upravit kolekci RSVPs (v ní budou uloženi uživatelé přihlášení k večeřím), nesmí ani moci upravit vlastnosti DinnerID nebo HostedBy. Zamezíme tomu tím, že třídu Dinner odekorujeme atributem Bind, ve kterém explicitně definujeme vlastnosti, které mají být zahrnuty v databindingu:

[Bind(Include = "Title,Description,EventDate,Address,Country,ContactPhone,Latitude,Longitude")]
public partial class Dinner
{ //...

CRUD je hotov!

Gratuluji, že jste to zvládli až sem, CRUD máme hotový. Naše aplikace tedy podporuje čtení, vytváření, mazání i upravování večeří. Ukažme si ještě zdrojový kód kompletního DinnersControlleru a na shledanou u příštího dílu, ve kterém si povíme o třídách ViewData a ViewModel.

using System;
using System.Linq;
using System.Web.Mvc;
using NerdDinner.Models;

namespace NerdDinner.Controllers
{
    public class DinnersController : Controller
    {
        DinnerRepository dinnerRepository = new DinnerRepository();

        // GET: /Dinners/
        public ActionResult Index()
        {
            var dinners = dinnerRepository.FindUpcomingDinners().ToList();
            return View(dinners);
        }

        // GET: /Dinners/Details/2
        public ActionResult Details(int id)
        {
            Dinner dinner = dinnerRepository.GetDinner(id);

            if (dinner == null)
                return View("NotFound");
            else
            {
                return View(dinner);
            }
        }

        // GET: /Dinners/Edit/2
        public ActionResult Edit(int id)
        {
            Dinner dinner = dinnerRepository.GetDinner(id);
            return View(dinner);
        }

        // POST: /Dinners/Edit/2
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(int id, FormCollection formValues)
        {
            Dinner dinner = dinnerRepository.GetDinner(id);
            try
            {
                UpdateModel(dinner);
                dinnerRepository.Save();

                return RedirectToAction("Details", new {id = dinner.DinnerID});
            }
            catch
            {
                ModelState.AddRuleViolations(dinner.GetRuleViolations());

                return View(dinner);
            }
        }

        // GET: /Dinners/Create
        public ActionResult Create()
        {
            Dinner dinner = new Dinner()
            {
                EventDate = DateTime.Now.AddDays(7)
            };

            return View(dinner);
        }

        // POST: /Dinners/Create
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Create(Dinner dinner)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    dinner.HostedBy = "Někdo";

                    dinnerRepository.Add(dinner);
                    dinnerRepository.Save();

                    return RedirectToAction("Details", new { id = dinner.DinnerID });
                }
                catch
                {
                    ModelState.AddRuleViolations(dinner.GetRuleViolations());
                }
            }

            return View(dinner);
        }

        // GET: /Dinners/Delete/1
        public ActionResult Delete(int id)
        {
            Dinner dinner = dinnerRepository.GetDinner(id);

            if (dinner == null)
                return View("NotFound");
            else
                return View(dinner);
        }

        // POST: /Dinners/Delete/1
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Delete(int id, string confirmButton)
        {

            Dinner dinner = dinnerRepository.GetDinner(id);

            if (dinner == null)
                return View("NotFound");

            dinnerRepository.Delete(dinner);
            dinnerRepository.Save();

            return View("Deleted");
        }
    }
}
Zdroj: http://nerddinnerbook.s3.amazonaws.com/Part5.htm

×Odeslání článku na tvůj Kindle

Zadej svůj Kindle e-mail a my ti pošleme článek na tvůj Kindle.
Musíš mít povolený příjem obsahu do svého Kindle z naší e-mailové adresy kindle@programujte.com.

E-mailová adresa (např. novak@kindle.com):

TIP: Pokud chceš dostávat naše články každé ráno do svého Kindle, koukni do sekce Články do Kindle.

2 názory  —  2 nové  
Hlasování bylo ukončeno    
0 hlasů
Google
Jakub studuje informatiku na FIT ČVUT, jeho oblíbenou platformou je .NET.
Web     Twitter     Facebook     LinkedIn    

Nové články

Obrázek ke článku Stavebnice umělé inteligence 1

Stavebnice umělé inteligence 1

Článek popisuje první část stavebnice umělé inteligence. Obsahuje lineární a plošnou optimalizaci.  Demo verzi je možné použít pro výuku i zájmovou činnost. Profesionální verze je určena pro vývojáře, kteří chtějí integrovat popsané moduly do svých systémů.

Obrázek ke článku Hybridní inteligentní systémy 2

Hybridní inteligentní systémy 2

V technické praxi využíváme často kombinaci různých disciplín umělé inteligence a klasických výpočtů. Takovým systémům říkáme hybridní systémy. V tomto článku se zmíním o určitém typu hybridního systému, který je užitečný ve velmi složitých výrobních procesech.

Obrázek ke článku Jak vést kvalitně tým v IT oboru: Naprogramujte si ty správné manažerské kvality

Jak vést kvalitně tým v IT oboru: Naprogramujte si ty správné manažerské kvality

Vedení týmu v oboru informačních technologií se nijak zvlášť neliší od jiných oborů. Přesto však IT manažeři čelí výzvě v podobě velmi rychlého rozvoje a tím i rostoucími nároky na své lidi. Udržet pozornost, motivaci a efektivitu týmu vyžaduje opravdu pevné manažerské základy a zároveň otevřenost a flexibilitu pro stále nové výzvy.

Obrázek ke článku Síla týmů se na home office může vytrácet. Odborníci radí, jak z pracovních omezení vytěžit maximum

Síla týmů se na home office může vytrácet. Odborníci radí, jak z pracovních omezení vytěžit maximum

Za poslední rok se podoba práce zaměstnanců změnila k nepoznání. Především plošné zavedení home office, které mělo být zpočátku jen dočasným opatřením, je pro mnohé už více než rok každodenní realitou. Co ale dělat, když se při práci z domova ztrácí motivace, zaměstnanci přestávají komunikovat a dříve fungující tým se rozpadá na skupinu solitérů? Odborníci na personalistiku dali dohromady několik rad, jak udržet tým v chodu, i když pracovní podmínky nejsou ideální.

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý