Real World MVC


Published on

Published in: Technology
  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide
  • This model helper creates the context if it is null, otherwise it just returns the context
  • This is how you setup the controller to use the repository. Create instances to the repository and context, then new up the repository with the context
  • As you can see, using the repository, greatly streamlines your code in how you interact with the entities.
  • Show code – AphirmitController – 139, Views/Aphirmits/View.cshtml - 74
  • Show code, Aphirmits/View.cshtml, line 80
  • AphirmitsController Line 69
  • Real World MVC

    1. 1. A Real World MVC Application with some other groovy stuff thrown in James Johnson Developer Advocates Los Angeles C# User Group Tuesday, November 1, 2011
    2. 2. Who I amFounder and President of the Inland Empire .NET User’s GroupThree time and current Microsoft MVP – CADSoftware developer by daySerial netrepreneur by nightPartner in Developer AdvocatesEasily distracted by acronyms and shiny objects
    3. 3. Developer AdvocatesHelping small to medium size software companies through• Evangelism and Advocacy• Blog Articles• Webcasts• Presentations • User group meetings • Code Camps • Regional Tech Conferences
    4. 4. Agenda• Demo of web site• Comparing Web Forms to MVC• Entity Framework• Administration• Bad words• Uploading images• Ajax and JavaScript• Ratings• Paging• Searching• Tweeting
    5. 5.• New thought and spiritual affirmations• Always have been a new thinker and hippie• Sister site to Windows Phone 7 app• Some bad words will be shown for the demo
    6. 6.• Rotating aphirm.its• Simple registration• Beginner badge
    7. 7. ASP.NET MVC• Models• Views• Controllers• ViewModels• No Postbacks• Very limited use of existing server controls• Clean HTML makes CSS and JavaScript easier• What all the cool kids are using these days
    8. 8. ASP.NET MVC ViewState
    9. 9. ASP.NET MVC No ViewState
    10. 10. Entity Framework• Version 4 released with .NET 4.0• New version (4.1) allows for model-first, code-first or database-first development• Maps POCO objects to database objects• A collection of things instead of a dataset of rows• “things” are the entities
    11. 11. Entity Framework• Why? • Adds a layer of abstraction between database and code • DBA can structure database how they want • Developer can map to the database how they want • Rename entities for more comfortable use • Entity Framework handles the mappings
    12. 12. Entity Framework• Entity Data Model – EDM • Deals with the entities and relationships they use• Entities • Instance of EntityType • Represent individual instances of the objects • Customer, book, shoe, aphirmit • Fully typed• Relationships between look up tables are mapped as associations in the EDMX
    13. 13. Entity Framework• csdl • Conceptual Schema Definition Language • The conceputal schema for the EDM • EntityContainer, EntitySet, EntityType definitions• ssdl • Store Schema Definition Language • Schematic representation of the data store• msl • Mapping Specification Language • Sits between the csdl and ssld and maps the entity properties
    14. 14. Entity Framework Lazy LoadingA design pattern to defer initialization until neededcontext.ContextOptions.DeferredLoadingEnabled=true;List<BookCase> cases = context.BookCase.ToList();foreach(var bookcase in cases){ var books = bookcase.Books;}
    15. 15. Entity Framework Eager LoadingUse if you will be needing every related entityList<BookCase> cases =context.BookCase.Include(“Books”).ToList();foreach(var bookcase in cases){ var books = bookcase.Books;}
    16. 16. Entity Framework Contexts• The context is the instance of the entity• Passing an entity around to tiers breaks the context• Just like the song, make sure the context remains the same
    17. 17. Entity Framework Contextspublic class ModelHelper{ private static CourseEntities _db; public static CourseEntities CourseEntities { get { if(_db == null) _db = new CourseEntities(); return _db; } set { _db = value; } } }private readonly CourseEntities _db = new CourseEntities();
    18. 18. Entity Framework Contextsprivate Student AddStudent(Student student, Course course){ student.Courses.Add(course); _db.SaveChanges();}Didn’t work because course was in a different contextprivate Student AddStudent(Student student, Course course){ var newStudent = GetStudent(student.Id); var newCourse = GetCourse(course.Id); newStudent.Courses.Add(newCourse); _db.SaveChanges();}
    19. 19. Entity Framework LINQ to Entities• Very similar to LINQ to SQL• Major difference LINQ to SQL – SingleOrDefault() LINQ to Entities – FirstOrDefault()
    20. 20. Entity Framework LINQ to EntitiesSelectingThing thing = _db.Things.Single(x=>x.Id == id);Deletingpublic void DeleteThing(Thing thing){ _db.DeleteObject(thing); _db.SaveChanges();}
    21. 21. Entity Framework LINQ to EntitiesAdding (Inserting)public void AddThing(Thing thing){ _db.AddToThings(thing) //this will be a list _db.SaveChanges() // of AddTo<Entities>}Editing (Updating)public void EditThing(Thing thing){ _db.Things.Attach(new Thing{Id=thing.Id}); _db.Things.ApplyCurrentValues(thing); _db.SaveChanges();}
    22. 22. Entity Framework Repositories• Repository pattern encapsulates code into a separate class• Allows for easy changes• Can use it to swith database providers or new technologies• Stephen Walther – ASP.NET MVC Framework, Sams • • “Download the code” link• Add the two projects to your solution• Add references to your project
    23. 23. Entity Framework Repositoriesusing GenericRepositorypublic class MyController{ private readonly IGenericRepository _repo; private readonly CourseEntities _db; public MyController() { _repo = new EFGenericRepository.EFGenericRepository(_db); }}
    24. 24. Entity Framework Repositories// get _repo.Get<Thing>(id);// edit _repo.Edit(thing);// create _repo.Create(thing);// delete _repo.Delete(thing);// list var list = _repo.List<Thing>().Where(x => x.Name.Contains(myName));
    25. 25.• New thought and spiritual affirmations• Always have been a new thinker and hippie• Sister site to Windows Phone 7 app• Some bad words will be shown for the demo
    26. 26.• Administration • Approve aphirm.its • Set IsApproved to true • Send email to user • Check for badges • Tweet new
    27. 27. SetBadgespublic void SetBadges(Aphirmit affirmation){ var memberId = affirmation.MemberId; _db.ResetPostBadges(memberId); //SP in database //get all the aphirmations the user has created var aphList = _aphirmitHelper.GetAphirmitsByMember(memberId) .Where(x => x.IsApproved.Equals(true)).ToList(); var aphCount = aphList.Count; if (aphCount >= 0) //beginner AddPostBadge(100, memberId);}
    28. 28. AddPostBadgeprivate void AddPostBadge(int badgeId, int memberId){ // BadgeIdis the internal Id varbadge = _db.Badges.Single(x => x.BadgeId.Equals(badgeId)); varnewBadge = new MemberBadge() { MemberId = memberId, BadgeId = badge.Id }; _db.AddToMemberBadges(newBadge); _db.SaveChanges();}
    29. 29. Uploading Images• Using Telerik MVC Upload control@Html.Telerik().Upload().Name("attachments").Async(async => async.Save("UploadAvatar", "Profile")).ClientEvents(events => events.OnSelect("onSelect")).ClientEvents(events => events.OnComplete("onAvatarComplete")).ShowFileList(false)
    30. 30. Uploading Images[HttpPost]public ActionResultUploadAvatar(IEnumerable<HttpPostedFileBase> attachments){ if (attachments == null) return Content("no file was uploaded"); HttpPostedFileBase img = attachments.ElementAt(0); var imagePath = _generalHelper.UploadAvatar(img); return Json(new { status = imagePath }, "text/plain");}
    31. 31. Uploading Imagesfunction onSelect(e) { var extArray = new Array(".png", ".gif", ".jpg", ".jpeg"); var $status = $("div.status"); $status.hide(); var file = e.files[0]; var inArray = $.inArray(file.extension, extArray); if (inArray == -1) { $("div.status").html("Sorry, only PNG, GIF, or JPG images are allowed.").show(); e.preventDefault(); return false; }}
    32. 32. Uploading Imagesfunction onAvatarComplete() { var userName = $("#avatarPath").val(); var url = "/Profile/GetMemberAvatar/" + userName; $.getJSON(url, function (json) {//append something to the string so that the image will berefreshed. json = json + "?" + new Date(); $("#memberAvatar").attr("src", json); });}
    33. 33. User Registration• Be as minimal as possible• Don’t ask for all possible data at start• Go easy, can always come back for more
    34. 34. User Registration• Use Ajax/JavaScript to help the user• Check for existing username before submitting• Check for existing email and format
    35. 35. Ajax/JavaScriptValidate usernamefunction validateUserName(elem) { var $elem = $(elem); var userName = $elem.val(); $elem.attr("valid", true); var url = "/Account/IsExistingUser/"; $.get(url, { name: userName }, function (json) { if (json) { $("#userNameTaken").fadeIn(); $elem.attr("valid", false).removeClass("valid").addClass("invalid"); } else { $("#userNameTaken").fadeOut(); $elem.removeClass("invalid").addClass("valid"); } });}
    36. 36. Ajax/JavaScriptValidate username[HttpGet]public JsonResult IsExistingUser(string name){ return Json(_memberHelper.IsExistingUser(name), JsonRequestBehavior.AllowGet);}
    37. 37. Paging• Use paging when there is more data than can easily be viewed• Easy to add page to display• There are several jQuery grids available • I just like mine
    38. 38. Paging[HttpGet]public ActionResult All(int? id){ int pageIndex; if (id == null) pageIndex = 0; else pageIndex = (int)id - 1; var pageSize = _generalHelper.GetListSize(); var affirmationList =_affirmationHelper.GetAphirmitRange(pageIndex, pageSize); decimal totalAffirmations = _affirmationHelper.GetApprovedCount(); var pageNumbers = Math.Ceiling(totalAffirmations / pageSize); ViewBag.PageNumbers = pageNumbers; ViewBag.CurrentPage = pageIndex; ViewBag.ListCount = pageSize; ViewBag.Total = totalAffirmations; return View("View", affirmationList);
    39. 39. Bad WordsNeed to check text for any bad words the user may have usedvar status = false;var badWords = _repo.List<BadWord>().ToList();foreach (var bWord in badWords.Where(bWord =>aphirmit.Text.IndexOf(bWord.Word) > -1)){ status = true;}
    40. 40. Bad Wordsvar hasBadWords = _affirmationHelper.HasBadWords(affirmation);if (hasBadWords){ TempData["HasBadWords"] = true; return RedirectToAction("Edit", new {id = affirmation.Id});}
    41. 41. Bad Wordsif(TempData["HasBadWords"] != null && (bool)TempData["HasBadWords"]){ <div class="editor-label error"> Your Aphirmit has some unsavory words. If you wouldlike to have it published, you will need to clean it up. </div>}
    42. 42. Questions?
    43. 43. Thank youJames JohnsonEmail: james.johnson@developeradvocates.comBlog: www.latringo.meTwitter: latringoPayPal: members@iedotnetug.orgSlides: Empire .NET User’s Group 2nd Tuesday of each month