MVC
Transkript
MVC
Michal Augustýn www.augi.cz ALWIL Software Microsoft Most Valuable Professional ASP.NET/IIS MVC v ASP.NET MVC Routing Controllery Views master pages kompozice framework pro tvorbu webového rozhraní na platformě ASP.NET používá návrhový vzor MVC – podobně jako Nette, Django, SpringMVC, RoR, ZendFW, … nyní ve verzi 2, pracuje se na verzi 3 rozšiřitelný/upravitelný v mnoha směrech open-source (licence Ms-PL) zdrojáky dostupné na Codeplex.com .NET Framework ~ Java C#, VB.NET, F#, IronPython, … Internet Information Services ~ Apache web.config ~ .htaccess module ~ module handler ~ handler ASP.NET je handler IIS ASP.NET WebForms MVC Požadavek GET http://domena.cz/produkt/zobraz/10 IIS moduly ASP.NET [ISAPI filter] handler moduly Výsledek <html>…</html> request 1 response routing 5 Controller 2-3 Model 4 View public class HomeController : Controller { public ActionResult Index() { ViewData["Message"] = "Welcome to ASP.NET MVC!"; return View(); } } public ActionResult About() { return View(); } defaultně se používá WebForms view-engine view == aspx stránka public ViewResult Show(int id) { } Product p = BusinessLayer.Load(id); return View("Show", p); <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Product>" %> <asp:Content ID="indexTitle" ContentPlaceHolderID="TitleContent" runat="server“>Home Page</asp:Content> <asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server"> <h2><%= Html.Encode(ViewData["Message"]) %></h2> <p><%= Html.Encode(ViewData.Model.Name) %></p> </asp:Content> určuje tvar url konfigurace v souboru Global.asax.cs pravidla se vyhodnocují v pořadí vložení mapuje zpracování url na kontroler a akční metodu umožňuje generování url výchozí nastavení: /Home/Product/20 routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = "" } // Parameter defaults ); třída odvozená od třídy Controller obsahuje akční metody (vrací ActionResult) 1. čte data z requestu 2. komunikuje s modelem 3. vybírá view a předává mu data k prezentaci Controller Model View parametry requestu mapovány na vstupní parametry akční metody („deserializace“) public ActionResult Show(int id) { … } Routovací parametry: controller, action, id POST parametry: product.Id, product.Name, product.Price public ActionResult Create(Product product) { … } manuálně: [Try]UpdateModel vlastní konverze - IModelBinder slouží k zápisu výsledku do HttpResponse public abstract class ActionResult { public abstract void ExecuteResult(ControllerContext context); } return return return return return return View("Index"); // ViewResult PartialView("Product"); // PartialViewResult Json(myObject); // JsonResult Redirect("http://www.bing.com/"); // RedirectResult RedirectToAction("Index"); // RedirectToRouteResult File("soubor.txt", "txt/plain"); // FilePathResult return new MyRssResult(myCollection); // Rss(myCollection) vlastní action-result na přesměrování public class MyRedirectResult : ActionResult { public string Url { get; set; } } public override void ExecuteResult(ControllerContext context) { context.HttpContext.Response.Redirect(this.Url); } return new MyRedirectResult { Url = "http://www.bing.com" }; hash-table ViewData 1. ViewData[“message”] = “Hello world!”; Model – libovolná třída 2. ViewData.Model = new MyViewModel(); typově bezpečné Controller Model View všechny produkty public ViewResult Index() { IEnumerable<Product> products = BusinessLayer.LoadAll(); return View(products); // ViewData.Model = products; } jeden produkt public ViewResult Show(int id) { Product p = BusinessLayer.Load(id); return View("Show", p); } editace produktu public ViewResult Update(int id) { Product p = BusinessLayer.Load(id); return View("Update", p); } [AcceptVerbs(HttpVerbs.Post)] public RedirectToRouteResult Update(int id, FormCollection formData) { Product p = BusinessLayer.Load(id); if (TryUpdateModel<IProduct>(p, formData.ToValueProvider())) { BusinessLayer.Update(p); } return RedirectToAction("Update", new { id = p.Id }); } master page určuje layout stránky definuje „díry“ k vyplnění (ContentPlaceHolder) content page plní ContentPlaceHoldery při zobrazení stránky řekneme jakou master page použít jak vyplnit jednotlivé díry <%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title> <link href="../../Content/Site.css" rel="stylesheet" type="text/css" /> </head> … <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Product>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Home Page - <%= Html.Encode(Model.Name) %> </asp:Content> … <% using (Html.BeginForm()) {%> <fieldset> <legend>Fields</legend> <p> <%= Html.LabelFor(model => model.Name) %> <%= Html.TextBoxFor(model => model.Name) %> <%= Html.ValidationMessageFor(model => model.Name) %> </p> <p> <%= Html.LabelFor(model => model.Price) %> <%= Html.TextBoxFor(model => model.Price) %> <%= Html.ValidationMessageFor(model => model.Price) %> </p> <p> <input type="submit" value="Save" /> </p> </fieldset> <% } %> <% using (Html.BeginForm()) {%> <fieldset> <legend>Fields</legend> <%= Html.EditorFor(model => model.Name) %> <%= Html.EditorFor(model => model.Price) %> <p> <input type="submit" value="Save" /> </p> </fieldset> <% } %> <% using (Html.BeginForm()) {%> <fieldset> <legend>Fields</legend> <%= Html.EditorForModel() %> <p> <input type="submit" value="Save" /> </p> </fieldset> <% } %> <% Html.EnableClientValidation(); %> <%= Ajax.ActionLink("Odkaz", "IndexAjax", "Home", new AjaxOptions { InsertionMode = InsertionMode.Replace, LoadingElementId = "loading-image", UpdateTargetId = "dynamic-content", }) %> standardní umístění ~/Views/{controller}/{view}.[aspx,ascx] ~/Views/Shared/{view}.[aspx,ascx] lze změnit (stejně jako vše) partial views: UserControls (ascx) dědí z ViewUserControl<TModel> Html.RenderPartial(“MyPView”, model) vyšší úroveň kompozice proběhne celý round-trip jde proti filozofii MVC, ale je užitečný Kdy použít RenderAction a kdy RenderPartial? Action – pro rendering nutná komunikace s modelem Partial – všechna data dostupná přijde request: routing: /Product/Show/21 {controller} = „Product“ {action} = „Show“ {id} = 21 model-binding: id = 21 public ViewResult Show(int id) { Product p = BusinessLayer.Load(id); return View("Show", p); } public ViewResult Show(int id) { Product p = BusinessLayer.Load(id); return View("Show", p); } <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Product>" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Product details </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2><%= Html.Encode(Model.Name) %></h2> <p><%= Html.Encode(Model.Description) %></p> <p>Price: <%= Html.Encode(Model.Price) %></p> </asp:Content> aspektové rozšíření akčních metod lze aplikovat i na celé controllery [Authorize(Roles = "Admin")] [OutputCache(CacheProfile="TestProfile")] [HandleError(View="Error")] public ActionResult Test() { return new EmptyResult(); } public interface IAuthorizationFilter { void OnAuthorization(AuthorizationContext filterContext); } public interface IActionFilter { void OnActionExecuting(ActionExecutingContext filterContext); void OnActionExecuted(ActionExecutedContext filterContext); } public interface IResultFilter { void OnResultExecuting(ResultExecutingContext filterContext); void OnResultExecuted(ResultExecutedContext filterContext); } public interface IExceptionFilter { void OnException(ExceptionContext filterContext); } 1.0 2.0 silně typovější Html.RenderAction display & edit templates 3.0 „komponenty“ (grid, captcha, …) multiple partial updates, client templates, scaffolding, DI, MEF, … MVC WebForms jednoduché čistý kód nutí správně strukturovat plná kontrola nad html zezačátku vyžaduje více znalostí složitější model RAD, komponentový vývoj odstínění od stavovosti http ViewState, PostBack http://asp.net/mvc http://haacked.com – Phil Haack http://weblogs.asp.net/ScottGu - ScottGu http://forum.builder.cz – české fórum i o .NET http://www.aspnetmvc.cz – snad už brzy a odpovědi…