Date post: | 15-Dec-2014 |
Category: |
Technology |
Upload: | james-johnson |
View: | 1,548 times |
Download: | 1 times |
A Real World MVC Application
with some other groovy stuff thrown in
James JohnsonDeveloper Advocates
Los Angeles C# User GroupTuesday, November 1, 2011
Who I am
Founder and President of the Inland Empire .NET User’s Group
Three time and current Microsoft MVP – CAD
Software developer by day
Serial netrepreneur by night
Partner in Developer Advocates
Easily distracted by acronyms and shiny objects
Developer Advocates
Helping small to medium size software companies through
• Evangelism and Advocacy• Blog Articles• Webcasts• Presentations• User group meetings• Code Camps• Regional Tech Conferences
Agenda
• Demo of web site• Comparing Web Forms to MVC• Entity Framework• Administration• Bad words• Uploading images• Ajax and JavaScript• Ratings• Paging• Searching• Tweeting
Aphirm.it
• 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
Aphirm.it
• Rotating aphirm.its• Simple registration• Beginner badge
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
ASP.NET MVC
ViewState
ASP.NET MVC
No ViewState
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
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
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
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
Entity Framework
A design pattern to defer initialization until needed
context.ContextOptions.DeferredLoadingEnabled=true;List<BookCase> cases = context.BookCase.ToList();foreach(var bookcase in cases){
var books = bookcase.Books;}
Lazy Loading
Entity Framework
Use if you will be needing every related entity
List<BookCase> cases = context.BookCase.Include(“Books”).ToList();
foreach(var bookcase in cases){
var books = bookcase.Books;}
Eager Loading
Entity Framework
• 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
Contexts
Entity Framework
public 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();
Contexts
Entity Framework
Contexts
private Student AddStudent(Student student, Course course){ student.Courses.Add(course); _db.SaveChanges();}
Didn’t work because course was in a different context
private Student AddStudent(Student student, Course course){ var newStudent = GetStudent(student.Id); var newCourse = GetCourse(course.Id); newStudent.Courses.Add(newCourse); _db.SaveChanges();}
Entity Framework
LINQ to Entities
• Very similar to LINQ to SQL• Major difference
LINQ to SQL – SingleOrDefault()LINQ to Entities – FirstOrDefault()
Entity Framework
LINQ to Entities
SelectingThing thing = _db.Things.Single(x=>x.Id == id);
Deletingpublic void DeleteThing(Thing thing){
_db.DeleteObject(thing);_db.SaveChanges();
}
Entity Framework
LINQ to Entities
Adding (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();}
Entity Framework
• 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
• stephenwalther.com• “Download the code” link
• Add the two projects to your solution• Add references to your project
Repositories
Entity Framework
using GenericRepositorypublic class MyController{ private readonly IGenericRepository _repo; private readonly CourseEntities _db;
public MyController() { _repo = new EFGenericRepository.EFGenericRepository(_db); }}
Repositories
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));
Aphirm.it
• 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
Aphirm.it
• Administration• Approve aphirm.its• Set IsApproved to true• Send email to user• Check for badges• Tweet new aphirm.it
Aphirm.it
SetBadges
public void SetBadges(Aphirmit affirmation) {
var memberId = affirmation.MemberId; _db.ResetPostBadges(memberId); //SP in database
//get all the aphirmations the user has createdvar aphList =
_aphirmitHelper.GetAphirmitsByMember(memberId).Where(x => x.IsApproved.Equals(true)).ToList();
var aphCount = aphList.Count; if (aphCount >= 0) //beginner
AddPostBadge(100, memberId);}
Aphirm.it
AddPostBadge
private void AddPostBadge(int badgeId, int memberId){ // BadgeId is the internal Id
var badge = _db.Badges.Single(x => x.BadgeId.Equals(badgeId));var newBadge = new MemberBadge()
{ MemberId = memberId,BadgeId = badge.Id};
_db.AddToMemberBadges(newBadge); _db.SaveChanges();
}
Aphirm.it
• 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)
Uploading Images
Aphirm.it
Uploading Images
[HttpPost]public ActionResult UploadAvatar(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");}
Aphirm.it
Uploading Images
function 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; }}
Aphirm.it
Uploading Images
function onAvatarComplete() { var userName = $("#avatarPath").val(); var url = "/Profile/GetMemberAvatar/" + userName; $.getJSON(url, function (json) {//append something to the string so that the image will be refreshed. json = json + "?" + new Date(); $("#memberAvatar").attr("src", json); });}
Aphirm.it
User Registration
• Be as minimal as possible• Don’t ask for all possible data at start• Go easy, can always come back for more
Aphirm.it
User Registration
• Use Ajax/JavaScript to help the user• Check for existing username before submitting
• Check for existing email and format
Aphirm.it
Ajax/JavaScript
Validate username
function 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"); } });}
Aphirm.it
Ajax/JavaScript
Validate username
[HttpGet]public JsonResult IsExistingUser(string name){ return Json(_memberHelper.IsExistingUser(name), JsonRequestBehavior.AllowGet);}
Aphirm.it
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
Aphirm.it
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);}
Aphirm.it
Bad Words
Need to check text for any bad words the user may have used
var status = false;var badWords = _repo.List<BadWord>().ToList();
foreach (var bWord in badWords.Where(bWord => aphirmit.Text.IndexOf(bWord.Word) > -1)){ status = true;}
Aphirm.it
Bad Words
var hasBadWords = _affirmationHelper.HasBadWords(affirmation);if (hasBadWords){ TempData["HasBadWords"] = true; return RedirectToAction("Edit", new {id = affirmation.Id});}
Aphirm.it
Bad Words
if(TempData["HasBadWords"] != null && (bool) TempData["HasBadWords"]){ <div class="editor-label error"> Your Aphirmit has some unsavory words. If you would like to have it published, you will need to clean it up. </div>}
Questions?
Thank you
James JohnsonEmail: [email protected]: www.latringo.meTwitter: latringoPayPal: [email protected]: www.slideshare.net/latringo/real-world-mvc
Inland Empire .NET User’s Group2nd Tuesday of each monthwww.iedotnetug.org