mvc a new web project type for asp.net. an option. more control over your more control over your a...
TRANSCRIPT
The ASP.NET MVC Framework
Scott [email protected]://www.hanselman.com
INTROMVC
ASP.NET MVC is…
A new Web Project Type for ASP.NET.An option.More control over your <html/>A more easily Testable Framework.Not for everyone.
“ScottGu”
When I was born…
“The Gu”
“His Gu-ness”
“Sir”
“Master Chief Gu”
Demo – Hello MVC World
Don’t fall asleep, it’ll be worth it.
What’s the Point?This is not Web Forms 4.0
It’s about alternatives. Car vs. Motorcycle.
FlexibleExtend it. Or not.
FundamentalPart of System.Web and isn’t going anywhere.
Plays Well With OthersFeel free to use NHibernate for Models, Brail for Views and Whatever for Controllers.
Keep it simple and DRY
Goodness – Driving Goals
Maintain Clean Separation of ConcernsEasy Testing Red/Green TDD Highly maintainable applications by default
Extensible and PluggableSupport replacing any component of the system
Goodness – Driving Goals
Enable clean URLs and HTMLSEO and REST friendly URL structures
Great integration within ASP.NETAll the same providers still workMembership, Session, Caching, etc.ASP.NET Designer Surface in VS2008
RUDE Q&AMVC
Ok, um, a choice. I’m paralyzed.In what cases should I stick with WebForms over MVC?
What’s up with REST?
I hear ASP.NET MVC can do REST. When would I use MVC vs. ADO Data Extensions (Astoria) vs. WCF?
Haven’t I heard this before?What is the difference between MVP and MVC?
Widgets? Do we have those?What is the component story with MVC?
Ship it.
When will MVC RTM?
Introducing…
Microsoft Visual Business Enabler Studio 2008R3v2 September Technical Preview RefreshMSVBES2k8R3v2lptrczstr for short
Will Ship Soon…
Will Ship Soon…
Is it safe?
What about security?
Does it scale?
What about performance/scalability?
HOW IT WORKSMVC
27
MVCModel
ControllerView
A Little More Detail
Model
Controller
View
• Browser requests /Products/• Route is determined• Controller is activated• Method on Controller is invoke• Controller does some stuff• Renders View, passing in
custom ViewData• URLs are rendered,
pointing to other Controllers
Even More Detail – Request Flow
• You can futz at each step in the process
Request
Demo – Request Lifecycle
Digging deeper…
FEATURESMVC
URL Routing – Pretty URIsDevelopers adds Routes to a global RouteTableMapping creates a RouteData - a bag of key/values
RouteTable.Routes.Add( new Route("blog/bydate/{year}/{month}/{day}",
new MvcRouteHandler()){ Defaults = new RouteValueDictionary { {"controller", "blog"}, {"action", "show"} }, Constraints = new RouteValueDictionary { {"year", @"\d{1.4}"}, {"month", @"\d{1.2}"}, {"day", @"\d{1.2}"}} })
Demo – Routing
The route less travelled…
ExtensibilityViewsControllersModelsRoutes
…are all Pluggable
ViewEngineBaseView Engines render outputYou get WebForms by defaultCan implement your own
MVCContrib has ones for Brail, NvelocityNHaml is an interesting one to watch
View Engines can be used toOffer new DSLs to make HTML easierGenerate totally different mime/types
Images, RSS, JSON, XML, OFX, VCards, whatever.
View Engine Base Class
ViewEngineBase
public abstract class ViewEngineBase { public abstract void RenderView(ViewContext
viewContext); }
NHaml – Extreme Custom Views<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
AutoEventWireup="true" CodeBehind="List.aspx"
Inherits="MvcApplication5.Views.Products.List" Title="Products" %><asp:Content ContentPlaceHolderID="MainContentPlaceHolder"
runat="server"> <h2><%= ViewData.CategoryName %></h2> <ul> <% foreach (var product in ViewData.Products) { %> <li> <%= product.ProductName %> <div class="editlink"> (<%= Html.ActionLink("Edit", new { Action="Edit",
ID=product.ProductID })%>) </div> </li> <% } %> </ul> <%= Html.ActionLink("Add New Product", new { Action="New" }) %></asp:Content>
NHaml – Extreme Custom Views
%h2= ViewData.CategoryName %ul
- foreach (var product in ViewData.Products) %li = product.ProductName .editlink = Html.ActionLink("Edit", new { Action="Edit", ID=product.ProductID }) = Html.ActionLink("Add New Product", new { Action="New" })
HOW TO TEST ITMVC
Interfaces and TDDMockable Intrinsics
HttpContextBase, HttpResponseBase, HttpRequestBase
Extensibility IControllerIControllerFactoryIRouteHandlerViewEngineBase
Testing Controller ActionsNo requirement to test within ASP.NET runtime.
Use RhinoMocks or TypeMockCreate Test versions of the parts of the runtime you want to stub
[TestMethod]public void ShowPostsDisplayPostView() { TestPostRepository repository = new TestPostRepository(); TestViewEngine viewEngine = new TestViewEngine();
BlogController controller = new BlogController(…); controller.ShowPost(2);
Assert.AreEqual("showpost",viewEngine.LastRequestedView); Assert.IsTrue(repository.GetPostByIdWasCalled); Assert.AreEqual(2, repository.LastRequestedPostId);}
Demo – TDD
Wasn’t this demo technically supposed to be first?
Demo – Complete Application
It’s your thing. Do what you wanna do.
What’s the Point?This is not Web Forms 4.0
It’s about alternatives. Car vs. Motorcycle.
FlexibleExtend it. Or not.
FundamentalPart of System.Web and isn’t going anywhere.
Plays Well With OthersFeel free to use NHibernate for Models, Brail for Views and Whatever for Controllers.
Keep it simple and DRY
HAI!IM IN YR NorthwindHOW DUZ I ListProducts YR idPRODUCTS = GETPRODUCTS idOMG FOUND YR PRODUCTSIF U SEZIM OUTTA YR Northwind
LOLCODE.NET
HAI!WTF:I HAS A STRINGGIMMEH STRINGIM IN YR VAR UPPIN YR 0 TIL LENGTH OF STRINGVISIBLE “GIMMEE A ” STRING!!VARSTEPPINIM OUTTA YR VAROMGWTFHALP!
LOLCODE.NET
Be well,write good code,and stay in touch
[email protected]://hanselman.com
© 2008 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries.
The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after
the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.
APPENDIXMVC
Controller
Base Controller ClassBasic Functionality most folks will use
IController InterfaceUltimate Control for the Control Freak
IControllerFactoryFor plugging in your own stuff (IOC, etc)
Basic Controller HandlingScenarios, Goals and Design
URLs route to controller “actions”, not pages – mark actions in Controller.Controller executes logic, chooses view.All public methods are accessible
public void ShowPost(int id) { Post p = PostRepository.GetPostById(id); if (p != null) { RenderView("showpost", p); } else { RenderView("nosuchpost", id); }}
Controller Base Classpublic class Controller : IController { … protected virtual void Execute(ControllerContext
controllerContext); protected virtual void HandleUnknownAction(string
actionName); protected virtual bool InvokeAction(string actionName); protected virtual void InvokeActionMethod(MethodInfo
methodInfo); protected virtual bool OnError(string actionName, MethodInfo methodInfo, Exception exception); protected virtual void
OnActionExecuted(FilterExecutedContext filterContext);
protected virtual bool OnActionExecuting(FilterExecutedContext filterContext);
protected virtual void RedirectToAction(object values); protected virtual void RenderView(string viewName, string masterName, object viewData);}
Controller – Regular APIspublic class Controller : IController { … protected virtual void Execute(ControllerContext
controllerContext); protected virtual void HandleUnknownAction(string
actionName); protected virtual bool InvokeAction(string actionName); protected virtual void InvokeActionMethod(MethodInfo
methodInfo); protected virtual bool OnError(string actionName, MethodInfo methodInfo, Exception exception); protected virtual void
OnActionExecuted(FilterExecutedContext filterContext);
protected virtual bool OnActionExecuting(FilterExecutedContext filterContext); protected virtual void RedirectToAction(object values);
protected virtual void RenderView(string viewName, string masterName, object viewData);}
Controller – Customization APIs
public class Controller : IController { … protected virtual void Execute(ControllerContext
controllerContext); protected virtual void HandleUnknownAction(string
actionName); protected virtual bool InvokeAction(string actionName); protected virtual void InvokeActionMethod(MethodInfo
methodInfo); protected virtual bool OnError(string actionName, MethodInfo methodInfo, Exception exception); protected virtual void
OnActionExecuted(FilterExecutedContext filterContext);
protected virtual bool OnActionExecuting(FilterExecutedContext filterContext);
protected virtual void RedirectToAction(object values); protected virtual void RenderView(string viewName, string masterName, object viewData);}
Controller – Test Hooks public class Controller : IController { … protected virtual void Execute(ControllerContext
controllerContext); protected virtual void HandleUnknownAction(string
actionName); protected virtual bool InvokeAction(string actionName); protected virtual void InvokeActionMethod(MethodInfo
methodInfo); protected virtual bool OnError(string actionName, MethodInfo methodInfo, Exception exception); protected virtual void
OnActionExecuted(FilterExecutedContext filterContext);
protected virtual bool OnActionExecuting(FilterExecutedContext filterContext);
protected virtual void RedirectToAction(object values); protected virtual void RenderView(string viewName, string masterName, object viewData);}
Basic ViewsScenarios, Goals and Design:
Are for rendering/output. Pre-defined and extensible rendering helpers
Can use .ASPX, .ASCX, .MASTER, etc.Can replace with other view technologies:
Template engines (NVelocity, Brail, …).Output formats (images, RSS, JSON, …).Mock out for testing.
Controller sets data on the ViewLoosely typed or strongly typed data
ViewEngineBaseView Engines render outputYou get WebForms by defaultCan implement your own
MVCContrib has ones for Brail, NvelocityNHaml is an interesting one to watch
View Engines can be used toOffer new DSLs to make HTML easier to writeGenerate totally different mime/types
ImagesRSS, JSON, XML, OFX, etc.VCards, whatever.
View Engine Base Class
ViewEngineBase
public abstract class ViewEngineBase { public abstract void RenderView(ViewContext
viewContext); }
NHaml – Extreme Custom Views<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
AutoEventWireup="true" CodeBehind="List.aspx"
Inherits="MvcApplication5.Views.Products.List" Title="Products" %><asp:Content ContentPlaceHolderID="MainContentPlaceHolder"
runat="server"> <h2><%= ViewData.CategoryName %></h2> <ul> <% foreach (var product in ViewData.Products) { %> <li> <%= product.ProductName %> <div class="editlink"> (<%= Html.ActionLink("Edit", new { Action="Edit",
ID=product.ProductID })%>) </div> </li> <% } %> </ul> <%= Html.ActionLink("Add New Product", new { Action="New" }) %></asp:Content>
NHaml – Extreme Custom Views
%h2= ViewData.CategoryName %ul
- foreach (var product in ViewData.Products) %li = product.ProductName .editlink = Html.ActionLink("Edit", new { Action="Edit", ID=product.ProductID }) = Html.ActionLink("Add New Product", new { Action="New" })
Controller Factory
Scenarios, Goals and Design:Hook creation of controller instance
Dependency Injection.Object Interception.
public interface IControllerFactory { IController CreateController(RequestContext context, string controllerName);}
protected void Application_Start(object s, EventArgs e) { ControllerBuilder.Current.SetControllerFactory( typeof(MyControllerFactory));}
View Engine
Scenarios, Goals and Design:Mock out views for testingReplace ASPX with other technologies
public interface IViewEngine { void RenderView(ViewContext context); }
Inside controller class: this.ViewEngine = new XmlViewEngine(...);
RenderView("foo", myData);