ASP.NET MVC

20
ASP.NET MVC Patterns and Anti- Patterns: Lessons from the Trenches

description

ASP.NET MVC. Patterns and Anti-Patterns: Lessons from the Trenches. Thanks to Our Host. Anti-Patterns: Things NOT to do. Return un-typed ViewData on a GET Pass low-level data-types on POST Pass FormCollection on POST Magic Strings in Views Logic in Views ‘Fat’ Controllers - PowerPoint PPT Presentation

Transcript of ASP.NET MVC

Page 1: ASP.NET MVC

ASP.NET MVC

Patterns and Anti-Patterns:Lessons from the Trenches

Page 2: ASP.NET MVC

Thanks to Our Host

Page 3: ASP.NET MVC
Page 4: ASP.NET MVC

Anti-Patterns: Things NOT to do• Return un-typed ViewData on a GET• Pass low-level data-types on POST• Pass FormCollection on POST• Magic Strings in Views• Logic in Views• ‘Fat’ Controllers• Domain Models passed to and from Views• Exposed Primary Keys in URLs• (unverifiable) Convention over Configuration

Page 5: ASP.NET MVC

Return Untyped ViewData on a GETpublic ActionResult Register(){

ViewData["PasswordLength"] = MembershipService.MinPasswordLength;return View();

}<p> Passwords are required to be a minimum of <

%=Html.Encode(ViewData["PasswordLength"])%> characters in length.

</p>

Page 6: ASP.NET MVC

Pass Low-Level data-types on POSTpublic ActionResult LogOn(string username,

string password)

{if (!ValidateLogOn(username, password)){

return View();}

}

Page 7: ASP.NET MVC

Pass FormCollection on POSTpublic ActionResult LogOn(FormCollection collection){

if (!ValidateLogOn(collection["userName"], collection["password"]))

{return View();

}}

Page 8: ASP.NET MVC

Magic Strings in Views<p>Please enter your username and password.<%= Html.ActionLink("Register", "Register")%> if you don't have an account.</p>

Page 9: ASP.NET MVC

Logic in Views<%if (((DateTime)ViewData["OrderDate"]) > new

DateTime(2009, 9, 1)){

foreach (Product product in (IList<Product>)ViewData["Products"])

{%><li><%=product.ProductName%></li>

<%}}%>

Page 10: ASP.NET MVC

‘Fat’ Controllers[AcceptVerbs(HttpVerbs.Post)]public ActionResult Edit(int id, FormCollection collection){

try{

var customer = customerRepository.Get(id);customer.Firstname = collection[("Firstname"];using(var tx = context.BeginTransaction()){

customerRepository.Save(customer);tx.Commit();

}return RedirectToAction("Index");

}catch{

return View();}

}

Page 11: ASP.NET MVC

Domain Models passed betw Viewspublic ActionResult List(int id){

var customer = customerRepository.Get(id);return View("Index", customer);

}

[AcceptVerbs(HttpVerbs.Post)]public ActionResult Edit(Customer customer){

customerRepository.Save(customer);return View("Index", customer);

}

Page 12: ASP.NET MVC

Exposed Primary Keys in URLshttp://host/{Controller}/{Action}/{id}

http://localhost/Customer/Edit/34http://localhost/Product/View/34

http://localhost/Customer/Edit/Bohlenhttp://localhost/Product/View/WSTV123

Page 13: ASP.NET MVC

(unverifiable) Convention over Configuration

public ActionResult Register(){ViewData["PasswordLength"] = MembershipService.MinPasswordLength;return View();

}

Page 14: ASP.NET MVC

Patterns: Things to DO• Strongly-Typed Model In and Model Out– ViewModels, UpdateModels

• Encapsulate View ‘decisions’ in ViewModels• Controller controls the View, NOT the app

Page 15: ASP.NET MVC

Strongly-Typed Model In and Outpublic ActionResult List(int number){

var customer = customerRepository.GetByNumber(number);var customerViewModel = new CustomerViewModel(customer);return View(“List", customerViewModel);

}[AcceptVerbs(HttpVerbs.Post)]public ActionResult Edit(CustomerUpdateModel updCustomer){

var customer=customerRepository.GetByNumber(updCustomer.Number);

updCustomer.ApplyChangesTo(customer);customerRepository.Save(customer);var customerViewModel = new CustomerViewModel(customer);return View("Index", customerViewModel);

}

Page 16: ASP.NET MVC

Encapsulate ‘decisions’ in ViewModels<%if (CustomerViewModel.HasRecentOrders)

{foreach (Product product in

(CustomerViewModel.Products){%>

<li><%=product.ProductName%></li><%}

}%>

Page 17: ASP.NET MVC

Controller controls the View, not the app[AcceptVerbs(HttpVerbs.Post)]public ActionResult Edit(CustomerUpdateModel updCustomer){

var customerViewModel=customerUpdateService(updCustomer)return View("Index", customerViewModel);

}

Page 18: ASP.NET MVC

Suggestions to Extend MVC• MVCContrib (mvccontrib.org)• xVal (xVal.CodePlex.com)• 1000s of JQuery Plugins

Page 19: ASP.NET MVC

Discussion• Other Experiences• Other Challenges• Other Recommendations

Page 20: ASP.NET MVC

Session Wrap-Up• Thoughts and Impressions– Positives and Deltas

• Discussion of Topics for Upcoming Meetings