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…