real world mvc

43
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

Upload: james-johnson

Post on 15-Dec-2014

1.549 views

Category:

Technology


1 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Real World MVC

A Real World MVC Application

with some other groovy stuff thrown in

James JohnsonDeveloper Advocates

Los Angeles C# User GroupTuesday, November 1, 2011

Page 2: Real World MVC

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

Page 3: Real World MVC

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

Page 4: Real World MVC

Agenda

• Demo of web site• Comparing Web Forms to MVC• Entity Framework• Administration• Bad words• Uploading images• Ajax and JavaScript• Ratings• Paging• Searching• Tweeting

Page 5: Real World MVC

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

Page 6: Real World MVC

Aphirm.it

• Rotating aphirm.its• Simple registration• Beginner badge

Page 7: Real World MVC

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

Page 8: Real World MVC

ASP.NET MVC

ViewState

Page 9: Real World MVC

ASP.NET MVC

No ViewState

Page 10: Real World MVC

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

Page 11: Real World MVC

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

Page 12: Real World MVC

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

Page 13: Real World MVC

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

Page 14: Real World MVC

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

Page 15: Real World MVC

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

Page 16: Real World MVC

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

Page 17: Real World MVC

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

Page 18: Real World MVC

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();}

Page 19: Real World MVC

Entity Framework

LINQ to Entities

• Very similar to LINQ to SQL• Major difference

LINQ to SQL – SingleOrDefault()LINQ to Entities – FirstOrDefault()

Page 20: Real World MVC

Entity Framework

LINQ to Entities

SelectingThing thing = _db.Things.Single(x=>x.Id == id);

Deletingpublic void DeleteThing(Thing thing){

_db.DeleteObject(thing);_db.SaveChanges();

}

Page 21: Real World MVC

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();}

Page 22: Real World MVC

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

Page 23: Real World MVC

Entity Framework

using GenericRepositorypublic class MyController{ private readonly IGenericRepository _repo; private readonly CourseEntities _db;

public MyController() { _repo = new EFGenericRepository.EFGenericRepository(_db); }}

Repositories

Page 24: Real World MVC

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));

Page 25: Real World MVC

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

Page 26: Real World MVC

Aphirm.it

• Administration• Approve aphirm.its• Set IsApproved to true• Send email to user• Check for badges• Tweet new aphirm.it

Page 27: Real World MVC

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);}

Page 28: Real World MVC

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();             

}

Page 29: Real World MVC

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

Page 30: Real World MVC

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");}

Page 31: Real World MVC

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; }}

Page 32: Real World MVC

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); });}

Page 33: Real World MVC

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

Page 34: Real World MVC

Aphirm.it

User Registration

• Use Ajax/JavaScript to help the user• Check for existing username before submitting

• Check for existing email and format

Page 35: Real World MVC

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"); } });}

Page 36: Real World MVC

Aphirm.it

Ajax/JavaScript

Validate username

[HttpGet]public JsonResult IsExistingUser(string name){ return Json(_memberHelper.IsExistingUser(name), JsonRequestBehavior.AllowGet);}

Page 37: Real World MVC

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

Page 38: Real World MVC

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);}

Page 39: Real World MVC

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;}

Page 40: Real World MVC

Aphirm.it

Bad Words

var hasBadWords = _affirmationHelper.HasBadWords(affirmation);if (hasBadWords){ TempData["HasBadWords"] = true; return RedirectToAction("Edit", new {id = affirmation.Id});}

Page 41: Real World MVC

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>}

Page 42: Real World MVC

Questions?

Page 43: Real World MVC

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