1 / 20

ASP.NET MVC

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

Download Presentation

ASP.NET MVC

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

  2. Thanks to Our Host

  3. 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

  4. Return UntypedViewData on a GET public ActionResultRegister() { ViewData["PasswordLength"] = MembershipService.MinPasswordLength; return View(); } <p> Passwords are required to be a minimum of <%=Html.Encode(ViewData["PasswordLength"])%> characters in length. </p>

  5. Pass Low-Level data-types on POST public ActionResultLogOn(string username, string password) { if (!ValidateLogOn(username, password)) { return View(); } }

  6. Pass FormCollection on POST public ActionResultLogOn(FormCollection collection) { if (!ValidateLogOn(collection["userName"], collection["password"])) { return View(); } }

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

  8. Logic in Views <%if (((DateTime)ViewData["OrderDate"]) >new DateTime(2009, 9, 1)) { foreach(Productproductin (IList<Product>)ViewData["Products"]) {%> <li><%=product.ProductName%></li> <%} }%>

  9. ‘Fat’ Controllers [AcceptVerbs(HttpVerbs.Post)] public ActionResultEdit(intid, FormCollectioncollection) { try { var customer = customerRepository.Get(id); customer.Firstname= collection[("Firstname"]; using(vartx = context.BeginTransaction()) { customerRepository.Save(customer); tx.Commit(); } return RedirectToAction("Index"); } catch { return View(); } }

  10. Domain Models passed betw Views public ActionResultList(intid) { var customer = customerRepository.Get(id); return View("Index", customer); } [AcceptVerbs(HttpVerbs.Post)] public ActionResultEdit(Customercustomer) { customerRepository.Save(customer); return View("Index", customer); }

  11. Exposed Primary Keys in URLs http://host/{Controller}/{Action}/{id} http://localhost/Customer/Edit/34 http://localhost/Product/View/34 http://localhost/Customer/Edit/Bohlen http://localhost/Product/View/WSTV123

  12. (unverifiable) Convention over Configuration public ActionResultRegister() { ViewData["PasswordLength"] = MembershipService.MinPasswordLength; return View(); }

  13. 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

  14. Strongly-Typed Model In and Out public ActionResultList(intnumber) { var customer = customerRepository.GetByNumber(number); varcustomerViewModel = newCustomerViewModel(customer); return View(“List", customerViewModel); } [AcceptVerbs(HttpVerbs.Post)] public ActionResultEdit(CustomerUpdateModelupdCustomer) { var customer=customerRepository .GetByNumber(updCustomer.Number); updCustomer.ApplyChangesTo(customer); customerRepository.Save(customer); varcustomerViewModel = newCustomerViewModel(customer); return View("Index", customerViewModel); }

  15. Encapsulate ‘decisions’ in ViewModels <%if (CustomerViewModel.HasRecentOrders) { foreach(Productproductin (CustomerViewModel.Products) {%> <li><%=product.ProductName%></li> <%} }%>

  16. Controller controls the View, not the app [AcceptVerbs(HttpVerbs.Post)] public ActionResultEdit(CustomerUpdateModelupdCustomer) { varcustomerViewModel=customerUpdateService(updCustomer) return View("Index", customerViewModel); }

  17. Suggestions to Extend MVC • MVCContrib (mvccontrib.org) • xVal (xVal.CodePlex.com) • 1000s of JQueryPlugins

  18. Discussion • Other Experiences • Other Challenges • Other Recommendations

  19. Session Wrap-Up • Thoughts and Impressions • Positives and Deltas • Discussion of Topics for Upcoming Meetings

More Related