# Saturday, 01 September 2012

This week I had the pleasure of speaking at devLINK.  I did 5 sessions over the 3 day conference and had a blast networking with the other speakers and attendees.  Kudos to the devLINK staff on a job well done.

Here are the 5 sessions I did at devLINK 2012 and links to the associated slides and demos.

posted on Saturday, 01 September 2012 18:45:00 (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Friday, 29 June 2012

A great new feature in ASP.NET MVC is the ability to bundle scripts and CSS files and register them as a group.  More detail on this functionality can be found here.  Because by default all the scripts and CSS classes in a new MVC 4 project are registered using bundles I felt a little dirty in my previous posts referencing my Kendo UI scripts and CSS files each individually.  I rectified that.

So I started the rectification process by adding entries to the BundleConfig.cs.  In this file is where you create and configure your bundles.  Out of the box there are a number of bundles configured so all I needed to was follow the same conventions when creating my bundles. 

bundles.Add(new ScriptBundle("~/bundles/kendojs").Include(
            "~/Scripts/jquery.min.js",
            "~/Scripts/kendo.all.min.js"));
 
bundles.Add(new StyleBundle("~/Content/kendocss").Include(
            "~/Content/kendo.common.min.css",
            "~/Content/kendo.default.min.css"));

Obviously I took the least amount of scripts I needed to get my contrived sample created, but you can add whatever scripts you need.

After creating the bundles I need to register or “Render” them as the method is called.  Have to admit I am not a fan of “Render” as the method name.  In the past “Render” has always had a visual connotation.  The registering of the bundles for this example is taking place in the _layout.cs, but you could do the same thing directly in your ASP.NET MVC View.

@Styles.Render([...other CSS bundles], "~/Content/kendocss")
@Scripts.Render([...other Script bundles],"~/bundles/kendojs")

And that’s it.  Now I have my Kendo UI scripts and CSS files registered/referenced/rendered using the new bundling features of ASP.NET MVC

Code is available on GitHub.

posted on Friday, 29 June 2012 15:38:27 (Central Daylight Time, UTC-05:00)  #    Comments [3]
# Monday, 25 June 2012

Note: If you are following along at home you may have noticed that the number of the series posts has changed.  I have taken some *poetic license* and decided that the previous post introducing Kendo UI for ASP.NET MVC was actually part part 3 of the original series on Kendo UI in ASP.NET MVC as well as part 1 of a new series on Kendo UI for ASP.NET MVC.  Clear as mud, right?

To stay in line, and catch up, with the pre-Kendo UI for ASP.NET MVC series this post is going to show you how to implement the Kendo UI AutoComplete control using the HtmlHelper extension.  In case you didn’t catch the original post on implementing the AutoComplete using Kendo UI (core/non-mvc) in ASP.NET MVC, the Kendo UI AutoComplete control is a text box that has an associated list of items that when text is entered into it a suggestion list is displayed allowing the user to select an item.

To get started follow steps 1 - 6 in the previous post to prep a new solution.

Next I created a server side model: Manufacturer.cs

namespace Part2_AutoComplete.Web.Models
{
    public class Manufacturer
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
}

As you can see the view the model is a very simple class that contains only an Id and a Name field.

After that I created my view: Index.cshtml

@using Kendo.Mvc.UI
@model IEnumerable<Part2_AutoComplete.Web.Models.Manufacturer>
@{
    ViewBag.Title = "Kendo UI for ASP.NET MVC: Part 2 - AutoComplete";
}
 
<h2>@ViewBag.Title</h2>
 
@(Html.Kendo().AutoComplete()
    .Name("manufacturerAutoComplete")
    .DataTextField("Name")
    .BindTo(Model)
    .Suggest(true)
    .Filter(FilterType.StartsWith)
    .Placeholder("Manufacturer...")
    .DataSource(source => {
            source.Read(read =>
               {
                        read.Action("GetManufacturers", "Home");
               }).ServerFiltering(true);
    })
)

Lastly we can code our controller: HomeController.cs

namespace Part2_AutoComplete.Web.Controllers {
 
    public class HomeController : Controller {
 
        public ActionResult Index() {
            return View(new List<Manufacturer> {new Manufacturer {Id = 1, Name = "Aston Martin"}});
        }
 
        [HttpGet]
        public JsonResult GetManufacturers() {
            string searchValue = Request.Params["filter[filters][0][value]"];
            IList<Manufacturer> manufacturers = BuildManufacturersList().Where(x => x.Name.StartsWith(searchValue, StringComparison.InvariantCultureIgnoreCase)).ToList();
            return Json(manufacturers, JsonRequestBehavior.AllowGet);
        }
 
        private IEnumerable<Manufacturer> BuildManufacturersList() {
            IList<Manufacturer> manufacturers = new List<Manufacturer>();
            manufacturers.Add(new Manufacturer {Id = 1, Name = "Aston Martin"});
            manufacturers.Add(new Manufacturer {Id = 2, Name = "Audi"});
            manufacturers.Add(new Manufacturer {Id = 3, Name = "Buggati"});
            manufacturers.Add(new Manufacturer {Id = 4, Name = "BMW"});
            manufacturers.Add(new Manufacturer {Id = 5, Name = "Chevrolet"});
            manufacturers.Add(new Manufacturer {Id = 6, Name = "Ferrari"});
            manufacturers.Add(new Manufacturer {Id = 7, Name = "Ford"});
            manufacturers.Add(new Manufacturer {Id = 8, Name = "Lamborghini"});
            manufacturers.Add(new Manufacturer {Id = 9, Name = "Mazda"});
            manufacturers.Add(new Manufacturer {Id = 10, Name = "McLaren"});
            manufacturers.Add(new Manufacturer {Id = 11, Name = "Mercedes Benz"});
            manufacturers.Add(new Manufacturer {Id = 12, Name = "Porsche"});
            return manufacturers;
        }
    }
}

That’s it.  Now that we are caught up with the transition to Kendo UI for ASP.NET MVC in the next post we can move on to something fresh and new…and Kendo UI certainly has a lot to offer in that area!

The code is available on GitHub.

posted on Monday, 25 June 2012 07:37:36 (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Tuesday, 19 June 2012

Back in April I started a series of posts related to using Kendo UI in ASP.NET MVC.  Last month the Kendo team released the first beta of Kendo UI for ASP.NET MVC.  So, long story short the blog posts on Kendo UI will continue but from this point forward they will move from implementing Kendo UI proper in ASP.NET MVC to using Kendo UI for ASP.NET MVC.

Kendo UI for ASP.NET MVC includes the complete Kendo UI suite (Web, Mobile, DataViz) plus a set .NET wrappers to be used with ASP.NET MVC that leverage exciting features of MVC such as data annotations, editor/display templates and validation.  Those of you still using the WebForms view engine are safe,  the wrappers work in both the Razor view engine and the WebForms view engine.

To get started download the Kendo UI for ASP.NET MVC bits and install them.  The bits include, what I would call, the Kendo UI core features plus all the ASP.NET MVC specific features so there is no need install both Kendo UI and Kendo UI for ASP.NET MVC.  If you already have Kendo UI core installed, don’t worry, the installer will adjust accordingly.

Once installed pull up the install location, for me it is “C:\Program Files (x86)\Telerik\Kendo UI for ASP.NET MVC Q2 2012 BETA”, and play around with the example projects by running “\Examples\StartExamples.exe”.

Now…let’s get it up and running in an ASP.NET MVC project.

NOTE: The Kendo UI for ASP.NET MVC documentation states that both MVC 3 and MVC 4 are supported even though the actual Kendo.MVC.dll resides in the “Mvc3” directory.

  1. Create a new ASP.NET MVC 3 or 4 project
  2. Add a reference to: [Kendo UI Directory]\Binaries\Mvc3\Kendo.Mvc.dll
  3. Copy the contents of [Kendo UI Directory]\Scripts to the Scripts folder of your MVC project
  4. Copy the contents of [Kendo UI Directory]\Content to the Content folder of your MVC project
  5. Reference the Kendo UI scripts and and CSS files in your layout page.
    *Note: If your using ASP.NET MVC 4 I suggest creating a bundler package

    <link rel="stylesheet" href="@Url.Content("~/Content/kendo.common.min.css")">
    <link rel="stylesheet" href="@Url.Content("~/Content/kendo.default.min.css")">
    <script src="@Url.Content("~/Scripts/jquery.min.js")"></script>
    <script src="@Url.Content("~/Scripts/kendo.web.min.js")"></script>
    <script src="@Url.Content("~/Scripts/kendo.aspnetmvc.min.js")"></script>
  6. Add a reference to the Kendu.Mvc.UI namespace to the <namespaces> section of the web.config to allow your views to know about the Kendo HTML Helper extensions.
    <add namespace="Kendo.Mvc.UI"/>
  7. Let’s test it out.  Open up Index.cshtml and create a Kendo UI control using the new HTML Helpers.
    @(Html.Kendo().DatePicker().Name("MyTestDatePicker"))

 

image

As with the previous parts of the series the code is available on GitHub.

posted on Tuesday, 19 June 2012 11:15:53 (Central Daylight Time, UTC-05:00)  #    Comments [6]
# Monday, 21 May 2012

Continuing from my previous post Getting Started with Kendo UI in ASP.NET MVC, let’s dive in to Kendo UI’s AutoComplete control.  The Kendo UI AutoComplete control is a text box that has an associated list of items that when text is entered into it a suggestion list is displayed allowing the user to select an item.

To get started I created a blank MVC project and wired up Kendo UI per the instructions in my Getting Started post.

Next I created a server side model: Manufacturer.cs

   1: namespace Part2_AutoComplete.Web.Models {
   2:  
   3:     public class Manufacturer {
   4:         public int Id { get; set; }
   5:         public string Name { get; set; }
   6:     }
   7: }

As you can see the view the model is a very simple class that contains only an Id and a Name field.

After that I created my view: Index.cshtml

   1: @model Part2_AutoComplete.Web.Models.Manufacturer
   2: @{
   3:     ViewBag.Title = "Getting Started With KendoUI - Part 2: Auto Complete";
   4: }
   5:  
   6: <script type="text/javascript">
   7:     $(document).ready(function () {
   8:         $("#Name").kendoAutoComplete({
   9:             minLength: 1,
  10:             dataTextField: "Name",
  11:             suggest: true,
  12:             filter: "startswith",
  13:             dataSource: { serverFiltering: true,  transport: {read: {url: "/Home/GetManufacturers/",dataType: "json", type: "POST"}}}
  14:         });
  15:     });
  16: </script>
  17:  
  18: <h2>@ViewBag.Title</h2>
  19:  
  20: @using(Html.BeginForm()) {
  21:     <div id="root">
  22:         <div id="manufacturers">
  23:             @Html.HiddenFor(x => x.Id)
  24:             <label for="input" class="info">Choose a car manufacturer:</label>
  25:             @Html.TextBoxFor(m => m.Name)
  26:             <div class="hint">Start typing the name of a car manufacturer <br/>(Aston Martin, Bugatti, Ferrari, Lamborghini, Porsche) </div>
  27:         </div>
  28:     </div>
  29:     <input type="submit" value="Send Back To Server"/>
  30:     <h3>@ViewBag.Message</h3>
  31: }

Assuming you are an ASP.NET MVC developer that uses Razor, the majority of the view code above should look familiar.  The lines to focus on are 8 – 14, which are the actual implementation of the Kendo UI AutoComplete.  Let’s break down the configuration options that I am passing to kendoAutoComplete:

  • minLength:  number of characters to be entered before filtering the data
  • dataTextField: field in the data source that represents the content of the list items
  • suggest: controls if the rest of the text for the item that matches is automatically displayed in the text box
  • filter: type of filtering to apply the data (“startswith”, “contains”, etc.)
  • dataSource: data that the control is bound to, can either be a JavaScript object or a Kendo UI DataSource
    • As you can see I am using a Kendo UI DataSource that makes an AJAX call to the GetManufactures method on the Home controller.

That is the complete client side implementation of the Kendo UI AutoComplete.  More details on what configuration is available for the AutoComplete can be found here.

Lastly we can code our controller: HomeController.cs

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Web.Mvc;
   5: using Part2_AutoComplete.Web.Models;
   6:  
   7: namespace Part2_AutoComplete.Web.Controllers {
   8:  
   9:     public class HomeController : Controller {
  10:  
  11:         [HttpGet]
  12:         public ActionResult Index() {
  13:             return View(new Manufacturer{Id = 1, Name = "Aston Martin"});
  14:         }
  15:  
  16:         [HttpPost]
  17:         public ActionResult Index(Manufacturer manufacturer) {
  18:             ViewBag.Message = string.Format("You selected \"{0}\" and sent it to the server!", manufacturer.Name);
  19:             return View();
  20:         }
  21:  
  22:         [HttpPost]
  23:         public JsonResult GetManufacturers() {
  24:             string searchValue = Request.Params["filter[filters][0][value]"];
  25:             IList<Manufacturer> manufacturers = BuildManufacturersList()
  26:                 .Where(x => x.Name.StartsWith(searchValue, StringComparison.InvariantCultureIgnoreCase)).ToList();
  27:             return Json(manufacturers);
  28:         }
  29:  
  30:         private IList<Manufacturer> BuildManufacturersList() {
  31:             IList<Manufacturer> manufacturers = new List<Manufacturer>();
  32:             manufacturers.Add(new Manufacturer {Id = 1, Name = "Aston Martin"});
  33:             manufacturers.Add(new Manufacturer {Id = 2, Name = "Audi"});
  34:             manufacturers.Add(new Manufacturer {Id = 3, Name = "Buggati"});
  35:             manufacturers.Add(new Manufacturer {Id = 4, Name = "BMW"});
  36:             manufacturers.Add(new Manufacturer {Id = 5, Name = "Chevrolet"});
  37:             manufacturers.Add(new Manufacturer {Id = 6, Name = "Ferrari"});
  38:             manufacturers.Add(new Manufacturer {Id = 7, Name = "Ford"});
  39:             manufacturers.Add(new Manufacturer {Id = 8, Name = "Lamborghini"});
  40:             manufacturers.Add(new Manufacturer {Id = 9, Name = "Mazda"});
  41:             manufacturers.Add(new Manufacturer {Id = 10, Name = "McLaren"});
  42:             manufacturers.Add(new Manufacturer {Id = 11, Name = "Mercedes Benz"});
  43:             manufacturers.Add(new Manufacturer {Id = 12, Name = "Porsche"});
  44:             return manufacturers;
  45:         } 
  46:     }
  47: }

The controller code is very straightforward.  Notice the GetManufacturers method that starts on line 30, it handles the AJAX request from the client and returns the JSON that is used to build the Kendo UI DataSource that drives that Kendo UI AutoComplete.

The code is available on GitHub.

If you haven’t checked out the recently released GitHub for Windows client, I highly suggest you check it out!

posted on Monday, 21 May 2012 15:18:54 (Central Daylight Time, UTC-05:00)  #    Comments [5]
# Monday, 30 April 2012

I have recently started diving in to Kendo UI and have decided to document that dive and blog about it.  So this is the first post in a series dedicated to using Kendo UI in ASP.NET MVC.

Kendo UI is a JavaScript toolset developed by Telerik that leverages jQuery, HTML5, CSS3, and JavaScript to provide rich UI widgets and an MVVM framework that is ‘scary fast’.  The thing that really drew me to Kendo UI in the first place is there native skinning on mobile devices.  Unlike vanilla jQuery Mobile that renders the same iOS-esque view on all mobile devices Kendo UI Mobile applies specific native-looking styles for iOS, Android, and Blackberry.  Over the series of posts I have planned we will cover exactly what Kendo UI brings to the table for both the ‘desktop’ web and the mobile web, but today I will cover getting Kendo UI installed and configured in an ASP.NET MVC application.

Before we dive in to getting the bits I want to prepare you…Kendo UI is not free.  I know, I was surprised by this as well and it actually delayed my dive in to it for a bit.  In all honesty I am still not 100% sure how I feel about it not being free.  What I do know is that as a long time user of Telerik products they produce damn good tooling and there support system is second to none.  If you want to just play around with Kendo UI there is a 60-day free trial available.

Update: I received a comment from a member of the KendoUI team, thanks John, and my statement above needs some clarification.  Kendo UI is dual licensed (GPLv3 and commercial), so although it is not free for commercial use they do support open source development.  You can can get the official terms here: http://www.kendoui.com/get-kendo-ui.aspx

Note: To prepare for experimenting with KendoUI I created an empty MVC 4 project, that of course is not empty, and removed all scirpt and css files (other than Site.css).  I then removed all script and css registrations in _Layout.cshtml.  I did this because I wanted to deal strictly with KendoUI without all the other *noise* of the other script references.

You can download the KendoUI bits here: http://www.kendoui.com/get-kendo-ui.aspx

Once downloaded and unzipped copy the contents of the ‘js’ directory to the ‘Scripts’ directory of your ASP.NET MVC application and the contents of the ‘styles’ directory to the ‘Content’ directory.

Next you need to register the scripts and CSS files that Kendo UI needs in the _Layout.cshtml.

_Layout.cshtml
  1. DOCTYPE html>
  2. <html>
  3.     <head>
  4.         <meta charset="utf-8" />
  5.         <meta name="viewport" content="width=device-width" />
  6.         <title>@ViewBag.Titletitle>
  7.         <script src="~/Scripts/jquery.min.js">script>
  8.         <script src="~/Scripts/kendo.all.min.js">script>
  9.         <link href="~/Content/kendo.common.min.css" rel="stylesheet" type="text/css"/>
  10.         <link href="~/Content/kendo.default.min.css" rel="stylesheet" type="text/css"/>
  11.     head>
  12.     <body>
  13.         @RenderBody()
  14.     body>
  15. html>

That’s it.  Kendo UI is now wired up.  Pretty much the same process as wiring up jQuery.  So now we can do a quick implementation to prove it.

If you followed my lead and created an empty project you you will need to create a controller and a view at this point.

The actual implementation of KendoUI is almost identical to that of jQuery which makes the ramp up time a lot less if you are familiar with jQuery.

Index.cshtml
  1. @{
  2.     ViewBag.Title = "Getting Started With KendoUI - Installation and Configuration";
  3. }
  4.  
  5. <script type="text/javascript">
  6.     $(document).ready(function(){
  7.         $("#datePicker").kendoDatePicker();
  8.     });
  9. script>
  10.  
  11. <h2>@ViewBag.Titleh2>
  12.  
  13. <input id="datePicker" />

As you can see on line 13 I have an input tag with and id of datepicker and then starting on line 5 I have my document ready function that selects the control with id of datepicker and calls the ‘kendoDatePicker’ function it.  The result is below.

 

KendoUI Calendar

In the next installment we will dig deeper into the different controls available in Kendo UI.

If you want to follow along with the source code it is available on GitHub.

posted on Monday, 30 April 2012 14:01:26 (Central Daylight Time, UTC-05:00)  #    Comments [13]
# Monday, 23 April 2012

Having been a part of many large enterprise ASP.NET MVC application implementations using test driven development I learned early on that separating your controller classes into a their own project significantly reduces the noise in your web project.  It wasn’t until a recent talk I gave to user group in my region that I realized that this isn’t a widely adopted practice.  For large applications with a lot of developers and a complex architecture I highly recommend it. 

Putting your controllers in a separate assembly is very straight forward.  First create a controllers project in your solution and then you just need to update your route registrations to tell them where to look for the controllers.

  1. routes.MapRoute(name: "Default", url: "{controller}/{action}/{id}",
  2.                 namespaces: new[] {"[Namespace of the Project that contains your controllers]"},
  3.                 defaults: new {controller = "Home", action = "Index", id = UrlParameter.Optional});

In order to tell ASP.NET MVC where to look for your controllers when registering your routes you use the ‘namespaces’ parameter of the MapRoute method as illustrated above.

I know that the concept of putting controllers in a separate assembly is a bit controversial and everyone seems to have a strong opinion either for or against, so let me know what side of the fence you fall on.

posted on Monday, 23 April 2012 08:02:14 (Central Daylight Time, UTC-05:00)  #    Comments [12]
# Monday, 06 February 2012

I have been working a lot with MVC sites lately and experimenting with how to make them *usable* on mobile browsers.  This is post is about the single line of mark-up you can add to your sites Master Page, or in this case your _Layout.cshtml.

Before I get to that line I am going to show you a quick screen shot of a vanilla MVC 3 application, that can be downloaded here.

First is a screen shot of the site running in a desktop browser.

image

 

Next, is the site rendered on Windows Phone 7, Android, and iPhone.

Windows Phone 7

Opera Mobile (Android)

iPhone

image image image

 

The first thing you notice is that iOS does a fairly good job adaptively rendering the site, damn Apple!  Next you will notice that all WP7 and Android do is zoom out so the site fits on the device.  A site of any significant content or functionality would be almost useless because of the amount of panning and zooming that would be required.  I am sure we have all dealt with sites on our mobile devices like that.  So what can we do to make the site render better in WP7 and Android?

You can actually get a long way towards perfect mobile rendering of your site by adding one simple html tag.

  1. <meta name="viewport" />

The meta viewport tag can be used to control how HTML content is displayed in mobile browsers.  The meta viewport tag has properties like width, height, minimum-scale, and maximum-scale.  In this example the particular property we are concerned with is the width property.  We want to tell the the browser to render our content width at the width of device.

  1. <meta name="viewport" content="width=device-width">

Let’s see what happens when we add that tag to the head of our _Layout.cshtml file

image

As you can see above, because the meta viewport tag only effects mobile browsers our desktop version looks exactly the same.  Let’s check on the mobile browsers.

Windows Phone 7

Opera Mobile (Android)

iPhone

image image image

The site looks much better on Windows Phone 7 and Android, and still looks the same in Apple.  So by adding that single line of mark-up we where able to give our mobile users a much better user experience.

Stay tuned for a future post on using CSS Media Queries to improve the mobile experience even further.

posted on Monday, 06 February 2012 08:15:38 (Central Standard Time, UTC-06:00)  #    Comments [2]
# Monday, 21 November 2011

If you ever need to redirect to a custom page in ASP.NET MVC when a user is either not authenticated or not authorized here is how you do it.

  1. Create a custom attribute that inherits from AuthorizeAttribute.
  2. Override the OnAuthorization method.
    • call the base OnAuthorization
    • Handle user not being authenticated
    • Handle user not being authorized
  3. Use the newly created attribute in your controller in place of the ASP.NET Authorize attribute

 

The Custom Attribute
  1. public class CustomAuthorizeAttribute : AuthorizeAttribute {
  2.  
  3.     public override void OnAuthorization(AuthorizationContext filterContext) {
  4.         base.OnAuthorization(filterContext);
  5.         if (!filterContext.HttpContext.User.Identity.IsAuthenticated) {
  6.             filterContext.Result = new RedirectResult("~/Account/Logon");
  7.             return;
  8.         }
  9.  
  10.         if (filterContext.Result is HttpUnauthorizedResult) {
  11.             filterContext.Result = new RedirectResult("~/Account/AccessDenied");
  12.             return;
  13.         }
  14.     }
  15. }
Example Controller Usage
  1. [CustomAuthorize(Roles = ("Admin,Manager"))]
  2. public ActionResult Index() {
  3.     return View("Index");
  4. }
posted on Monday, 21 November 2011 09:46:18 (Central Standard Time, UTC-06:00)  #    Comments [6]
# Monday, 14 November 2011

ASP.NET MVC has an HTML Helper DropDownListFor that takes an IEnumerable and creates a drop down list for it.  Often you want to create a drop down list for an Enum.  Of course you can do this without using an HTML Helper and use standard HTML controls but you don’t have the standard clean view code that HTML Helpers give you.  Extending and creating your own HTML Helpers is rather easy, as demonstrated in my last post. With that in mind I created an extension to DropDownListFor that will create a drop down list for an Enum type.

 

Enum Html Helper
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using System.Linq.Expressions;
  4. using DropDownListForEnumDemo.Extensions;
  5.  
  6. namespace System.Web.Mvc.Html {
  7.  
  8.     public static class EnumHtmlHelper {
  9.         
  10.         public static MvcHtmlString DropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression) {
  11.             return DropDownListFor(htmlHelper, expression, null, null);
  12.         }
  13.  
  14.         public static MvcHtmlString DropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, string optionLabel) {
  15.             return DropDownListFor(htmlHelper, expression, optionLabel, null);
  16.         }
  17.  
  18.         public static MvcHtmlString DropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes) {
  19.             return DropDownListFor(htmlHelper, expression, null, htmlAttributes);
  20.         }
  21.  
  22.         public static MvcHtmlString DropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, string optionLabel, object htmlAttributes) {
  23.             ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
  24.             Type enumType = Nullable.GetUnderlyingType(typeof (TEnum)) ?? typeof (TEnum);
  25.             IEnumerable<TEnum> enumValues = Enum.GetValues(enumType).Cast<TEnum>();
  26.             IEnumerable<SelectListItem> items = enumValues.Select(e => new SelectListItem {Text = e.ToString().FromCamelToProperCase(), Value = e.ToString(), Selected = e.Equals(metadata.Model)});
  27.             if (optionLabel != null) {
  28.                 new[] {new SelectListItem {Text = optionLabel}}.Concat(items);
  29.             }
  30.             return htmlHelper.DropDownListFor(expression, items, optionLabel, htmlAttributes);
  31.         }
  32.     }
  33. }

 

Enum
  1. namespace DropDownListForEnumDemo.Enumerations {
  2.  
  3.     public enum Cars {
  4.         FerrariItalia = 0,
  5.         LamborghiniGallardoLP560,
  6.         LamborghiniAventador,
  7.         AstonMartinVantage,
  8.         Porsche911GT2,
  9.     }
  10. }

 

Model
  1. namespace DropDownListForEnumDemo.Models {
  2.  
  3.     public class CarsModel {
  4.         [Display(Name = "Select A Car:")]
  5.         [Required(ErrorMessage = "* Required")]
  6.         public Cars? SelectedCar { get; set; }
  7.     }
  8. }

 

View
  1. @{ViewBag.Title = "Home Page";}
  2. @using DropDownListForEnumDemo.Models
  3. @model CarsModel
  4. <h2>@ViewBag.Message</h2>
  5. @using (Html.BeginForm()) {
  6.     <div>
  7.         <fieldset>
  8.             <div class="editor-label">
  9.                 @Html.LabelFor(m => m.SelectedCar)
  10.             </div>
  11.             <div class="editor-field">
  12.                 @Html.DropDownListFor(m => m.SelectedCar, "-- Select --")
  13.                 @Html.ValidationMessageFor(m => m.SelectedCar)
  14.             </div>
  15.         </fieldset>
  16.         <input type="submit" value="Click Me"/>
  17.     </div>
  18. }

 

image

 

Note:  Because enumeration values have to adhere to the same naming conventions as variables I had to work some magic to get the display values formatted correctly.  OK, it’s really not magic…just a little RegEx Voo-Doo.

The code is available on GitHub

posted on Monday, 14 November 2011 08:46:32 (Central Standard Time, UTC-06:00)  #    Comments [3]
# Monday, 07 November 2011

ASP.NET MVC provides a lot of HTML Helpers that allow you to more easily with less code create your views.  Typically navigation in MVC is done using the ActionLink HTML Helper that allows you easily generate an html anchor tag that will redirect to a specified controller and action.  I found cases where I wanted my navigation to be done via a button rather than a link so I created my own HTML Helper to make this easier.

Code:

  1. using System.Web.Routing;
  2.  
  3. namespace System.Web.Mvc.Html {
  4.  
  5.     public static class ActionLinkButtonHelper {
  6.        
  7.         public static MvcHtmlString ActionLinkButton(this HtmlHelper htmlHelper, string buttonText, string actionName, string controllerName, RouteValueDictionary routeValues) {
  8.             string href = UrlHelper.GenerateUrl("default", actionName, controllerName, routeValues, RouteTable.Routes, htmlHelper.ViewContext.RequestContext, false);
  9.             string buttonHtml = string.Format("<input type=\"button\" title=\"{0}\" value=\"{0}\" onclick=\"location.href='{1}'\" class=\"button\" />",buttonText,href);
  10.             return new MvcHtmlString(buttonHtml);
  11.         }
  12.     }
  13. }

Example Usage:

  1. @Html.ActionLinkButton("Add", "AddSiteFromDistrict", "SiteMaintenance", new RouteValueDictionary(new { districtID = @Model.DistrictID }))
posted on Monday, 07 November 2011 08:53:15 (Central Standard Time, UTC-06:00)  #    Comments [2]
# Saturday, 29 October 2011

My latest project was being done in ASP.NET MVC3 and I needed to do some date validation that was beyond what was available out-of-the-box.  I Googled around the inter-webs for awhile and couldn’t find anything that met my needs so I decided to create my own set of extensions…and while I was at create my NuGet package and CodePlex project.

For some reason the validation attributes available for the Date data type are non-existence in MVC.  You can compare to another model field, but that only checks for equality.  You can use regular expressions, which is not fun, and you can only compare against static values, or you can create your own validation attributes…which is the route I chose.

I created custom validation attributes that I found that I needed in my projects and packed some up to make available to the masses.

EzValidation contains validation for:

  • Equal, NotEqual, Greater, Less, GreaterOrEqual, LessOrEqual
    • Available for all Primitive Data Types (including nullable)
    • Compare to another field in the Model
        1. [Equal("Email")]
        2. public string ConfirmEmail { get; set; }
    • Compare to a specific value
        1. [NotEqual("|28|")]
        2. public int Age {get; set;}
    • Compare to Current Date (Dates and Strings only)
        1. [Greater("CompareToCurrentDate")]
        2. public DateTime ADateInTheFuture { get; set; }
    • Compare to Yesterday's Date (Dates and Strings only)
        1. [Less("CompareToYesterday")]
        2. public DateTime DateBeforeYesterday { get; set; }
    • Compare to Tomorrow's Date (Dates and Strings only)
        1. [GreaterOrEqual("CompareToTomorrow")]
        2. public DateTime DateAfterTomorrow { get; set; }

     

    The source Code is available on CodePlex.

    The package can be installed via NuGet.  “package-install EzValidation"

    posted on Saturday, 29 October 2011 19:09:00 (Central Daylight Time, UTC-05:00)  #    Comments [1]
    # Friday, 29 May 2009

    I have a few issues with the standard ASP.NET MVC view engine.  First off it is too verbose…you have type too much and in my opinion the views don’t look like html.  Luckily there are alternatives.  One of the most popular ASP.NET MVC view engine replacements is Spark.  Spark is replacement view engine that allows you to type less and makes your Views much easier to read.  So for part 3 of NerdDinnerAdvanced I am replacing the built in ASP.NET MVC view engine with Spark.

    Replacing the view engine in the NerdDinnerAdvanced project was very straight forward.  Here are the steps.

      1. Reference Spark.dll and Spark.Web.MVC.dll in NerdDinnerAdvanced.UI
        Spark
      2. Register Spark as a view engine in Global.asax Application_Start
        /// <summary>
        /// Application Start
        /// </summary>
        protected void Application_Start() {
            RegisterRoutes(RouteTable.Routes);
            //Wire Up Spark as our ViewEngine (Step 1)
            SparkEngineStarter.RegisterViewEngine();
            //Initialize IoC
            InversionOfControlHelper.Initialize();
            //Wire up controller factory
            ControllerBuilder.Current.SetControllerFactory(new IoCControllerFactory());
        }
      3. Add a declaration for the Spark configuration section to the Web.config
        <!-- Spark Config Section Declaration (Step 2) -->
        <section name="spark" type="Spark.Configuration.SparkSectionHandler, Spark"/>
      4. Add Spark configuration to the Web.config
        <!-- Spark Configuration Section -->
        <spark>
            <compilation debug="true">
              <assemblies>
                <add assembly="NerdDinnerAdvanced.UI"/>
                <add assembly="System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
              </assemblies>
            </compilation>
            <pages>
              <namespaces>
                <add namespace="System.Collections.Generic"/>
                <add namespace="System.Linq"/>
                <add namespace="System.Web.Mvc"/>
                <add namespace="System.Web.Mvc.Html"/>
                <add namespace="System.Web.Mvc.Ajax"/>
                <add namespace="NerdDinnerAdvanced.Domain.Models" />
              </namespaces>
            </pages>
            <use content="MainContent" />
        </spark>
      5. Create Spark master page

        How master pages are implemented in Spark is very cool.  I am not going to go into details all the ways you can implement master pages in Spark, but you can check it out here.  I am going to use the default behavior in which Spark will look for a file name Application.spark in either the Views/Layout or Views/Shared folders and will apply that to all the views in project.  So I no longer have to explicitly tell my view what master to use. So to setup our master page we need to;

        1. Add a new class file under Views –> Shared and name it Application.spark.
        2. Copy all the code from Site.master into Application.spark
        3. Remove the Page directive
        4. Remove the title content place holder
        5. Replace the main content place holder with Spark content div
          <div id="content">
          </div>
        6. Replace all '<%= xxx %>' with '${ xxx }'
        7. You should end up with…
          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
          <html xmlns="http://www.w3.org/1999/xhtml">
          <head runat="server">
              <title></title>
              <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
              <script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
              <script src="/Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>    
              <script src="/Scripts/jQuery-1.3.2.js" type="text/javascript"></script>
          </head>
          <body>
              <div class="page">
           
                  <div id="header">
                      <div id="title">
                          <h1>Nerd Dinner For The Real World</h1>
                      </div>
                        
                      <div id="logindisplay">
                          <% Html.RenderPartial("LogOnUserControl"); %>
                      </div> 
                      <div id="menucontainer">
                          <ul id="menu">              
                              <li>${ Html.ActionLink("Find Dinner", "Index", "Dinners")}</li>
                              <li>${ Html.ActionLink("Host Dinner", "Create", "Dinners")}</li>
                              <li>${ Html.ActionLink("About","About","Home") }</li>
                          </ul>
                      </div>
                  </div>
           
                  <div id="main">
                      <div id="content">
                          <use content="MainContent" />
                      </div>
                      <div id="footer">
                      </div>
                  </div>
              </div>
          </body>
          </html>
      6. Convert our first page.  Home/Index.aspx
        1. Rename Index.aspx to Index.spark
        2. Remove Page directive
        3. Remove Title content
        4. Replace ASP main content tag with Spark main content tag
        5. Replace all '<%= xxx %>' with '${ xxx }'
      7. Now we ran it!  What to notice here is first of all it runs.  The second thing to notice is the really cool part.  We are seeing a view created using the Spark View Engine but we are displaying a partial view created using the standard ASP.NET MVC View Engine.  The Log In/Out user control is still being rendered by the default view engine.
      8. Now we are ready to convert the remaining pages.  One difference from the built in view engine is how you tell the view about the model.  You need to explicitly specify what model the view uses.
        <viewdata model="NerdDinnerAdvanced.UI.Utility.PaginatedCollection<NerdDinnerAdvanced.Domain.Models.Dinner>"/>


    The complete code can be downloaded here.  Stay tuned for part 4.

    posted on Friday, 29 May 2009 23:05:00 (Central Daylight Time, UTC-05:00)  #    Comments [7]
    # Wednesday, 27 May 2009

    In part 2 of the NerdDinnerAdvanced code I replaced the LinqToSql DAL with a DAL that uses NHibernate.  NHibernate is an open sourced object relational mapper.  If you are not familiar with ORM and/or NHibernate I highly suggest you check them out.  Because of the way we architected our project in Part 1 implementing an NHibernate DAL had little to no impact on any code above the DAL.

    To start I re-structured the project a little.  I created a NerdDinnerAdvanced.Data.LinqToSql project and moved the LinqToSql DinnerRepository and the NerdDinner.dbml file into the new project.  This left just the IDinnerRepository in the NerdDinnerAdvanced.Data project.  You could certainly move the IDinnerRepository class to the NerdDinnerAdvanced.Common project and remove the NerdDinnerAdvanced.Data project if you wish.

    DataAndLinqToSql

    Now it was time to create my NHibernate mappings.  If you are not familiar with how ORM’s work the basic concept is that the ORM framework maps data from a database to your entity/domain objects In order to accomplish this you need to tell the ORM what tables/columns map to what objects/fields and this is typically done via an XML file.  In this case we only have 2 objects to map, Dinner and Rsvp, so the mapping would not be complex.  Often, though, you are dealing with hundreds of objects with a lot of fields and the management of the XML mapping files can get very difficult.  For this reason, and because I wanted to have a chance to play with it, I decided to use Fluent NHibernate to do my mapping.  Fluent NHibernate allows you to do your mappings using strongly typed C# code.

    In my NerdDinnerAdvanced.Domain project I created a new folder called Mappings and added two mapping classes, one for each of my two domain objects.

    Mappings

     

    Because this is not a Fluent NHibernate tutorial I am not going to go into detail on how you create the mappings…and for the most part it is fairly intuitive.

     /// <summary>
     /// Fluent NHibernate mapping for the Dinner class
     /// </summary>
     public class DinnerMap : ClassMap<Dinner> {
         
         public DinnerMap() {
             WithTable("Dinners");
             SetAttribute("lazy", "false");
             Id(x => x.DinnerId);
             Map(x => x.Title);
             Map(x => x.Description);
             Map(x => x.EventDate);
             Map(x => x.HostedBy);
             Map(x => x.Address);
             Map(x => x.Country);
             Map(x => x.ContactPhone);
             Map(x => x.Latitude);
             Map(x => x.Longitude);
             HasMany(x => x.Rsvps).Inverse().KeyColumnNames.Add("DinnerId").Cascade.All().SetAttribute("lazy", "false");
         }
     }

    Next it was time to create the NHibernate DAL so I added a NerdDinnerAdvanced.Data.NHibernate project to the solution.  The first thing you have to do when using NHibernate, after creating your mapping files, is create your NHibernate Session class.  Session to NHibernate is like DataContext to Linq.   The Session for the most part contains connection string and mapping info and it is the mediator between you and your data.

        /// <summary>
        /// NHibernate session factory
        /// </summary>
        public class SessionFactory {
    
            public static ISessionFactory CreateSessionFactory() {
                return Fluently.Configure()
                    .Database(MsSqlConfiguration.MsSql2005.ConnectionString(c => c.Is("Data Source=keith-166938fd4;Initial Catalog=NerdDinner;Integrated Security=True")))  
                    .Mappings(m =>  m.FluentMappings.AddFromAssemblyOf<Dinner>())  
                    .BuildSessionFactory();  
            }
            
        }

    After creating the NHibernate Session class I can now implement my DinnerRepository using NHibernate.  Below is an example of the FindAllDinners method.

            /// <summary>
    /// Returns a list of all dinners
    /// </summary>
    /// <returns>List of all dinners</returns>
    public IQueryable<Dinner> FindAllDinners() {
    var sessionFactory = SessionFactory.CreateSessionFactory();
    using (var session = sessionFactory.OpenSession()) {
    using (session.BeginTransaction()) {
    return session.CreateCriteria(typeof(Dinner)).List<Dinner>().AsQueryable();
    }
    }
    }

    After completing the DinnerRepository we can tell our application to use the the new DAL by changing one line in our InversionOfControlHelper class.

            /// <summary>
            /// Initializes the inversion of control mappings
            /// </summary>
            public static void Initialize() {
    StructureMapConfiguration.ResetAll();
    //Tell Structure Map we are using Fluent mapping rather than onfiguration file based mapping! StructureMapConfiguration.UseDefaultStructureMapConfigFile = false;
    //This is the only line of code outside of the DAL that needed to be modified to implement the NHibernate data access layer! //StructureMapConfiguration.BuildInstancesOf<IDinnerRepository>().TheDefaultIsConcreteType<Data.LinqToSql.DinnerRepository>();
    StructureMapConfiguration.BuildInstancesOf<IDinnerRepository>().TheDefaultIsConcreteType<Data.NHibernate.DinnerRepository>();
    StructureMapConfiguration.BuildInstancesOf<IDinnerServices>().TheDefaultIsConcreteType<DinnerServices>();
    }

    Once again the complete source can be downloaded here.  Stay tuned for Part 3!

    posted on Wednesday, 27 May 2009 08:52:17 (Central Daylight Time, UTC-05:00)  #    Comments [12]
    # Saturday, 16 May 2009

    The first chapter of Professional ASP.NET MVC 1.0 walks you through creating the basic NerdDinner site.  This is a great introduction to ASP.NET MVC but really isn’t something you could as reference for creating a real world ASP.MVC site.  With this in mind I set out on a multi part project to create a real world ASP.NET reference application based on the base NerdDinner code.

    It the first installation of what I am calling NerdDinnerAdvanced I extended the base NerdDinner code in the following ways;

      • Created 3-tier architecture.  One of the major misconceptions about ASP.NET MVC is that it is a UI framework.  I think this is mainly due to the fact that the major changes that developers need to wrap their head around are in the UI.  To help alleviate this misconception I structured the MVC project architecturally that developers who have experience in n-tier architecture will find familiar.
         The layers, as you can see highlighted above, are UI, Business, and Data.  Because of the overall simplistic nature of the underlying code I did not include a Service layer.  The other projects are shared by the layers.  The Domain project contains my models and the Common project contains common utility classes.

     

      • The base NerdDinner code used LINQ to SQL and was content with passing the LINQ to SQL entities between the layers of the application.  I would guess that Mr. Gu did this for simplicity and brevity and not a show of best practice.  If you are asking yourself what is wrong with architecting around LINQ to SQL entities I would recommend picking up Dino Esposito’s latest book.  The main reason is that you are tightly coupling yourself to the database.  So in my Domain project I created a Models namespace and created Dinner, Rsvp, and DinnerFormView domain objects.

     

      •   Implemented Inversion Of Control/Dependency Injection using Structure Map.  The base NerdDinner code used manual IoC/Di in the DinnersController but I decided to take that a step further because I am on a bit of an Ioc/Di fix lately.  I implemented it on the repository and the dinner services business object as well as the Dinner and Rsvp controllers.

     

      • Implemented a full suite of unit testing using MOQ for mocking objects.

    The code can be downloaded here.  Stay tuned for the next installment which will include nHibernate as the DAL.

    posted on Saturday, 16 May 2009 16:10:32 (Central Daylight Time, UTC-05:00)  #    Comments [6]
    # Wednesday, 13 May 2009

    I recently finished reading the first chapter of ASP.NET MVC 1.0, which deals strictly with the Nerd Dinner site that 3 of the 4 authors of the book put together.  This book has been a delight to read to this point and I highly recommend it.  In reading the first chapter I wrote  the code along with the book.  I wanted to make the code a source of reference for me in the future so while I was coding I added comments detailing points of interest from the book.  Along the way I thought making it available to the masses might be a good idea.  Since I wasn't sure on the legal ramifications of putting exact text from a book into my code comments I contacted one of the authors.  I received an email from said author a day later and he stated, and I quote “I say blog first, ask permission later.”  So that is exactly what I am doing.  You can download the full source here. Below is a sample...

            /// <summary>
            /// Attempts to perform an edit on the Dinner with the provided id using the provided formValues
            /// URL     :   /Dinners/Edit/[id]
            /// Verb    :   Post
            /// Purpose :   Save the form changes for a particular Dinner to the database
            /// </summary>
            /// <param name="id">Id of dinner to edit</param>
            /// <param name="formValues">Incoming form parameters</param>
            /// <returns>Details for view for the dinner that was edited</returns>
            /// <remarks>
            /// The "AcceptVerbs" attribute indicates it handles HTTP Post scenarios.
            /// When the attribute is applied to overloaded action methods ASP.NET MVC
            /// automatically handles dispatching to the appropriate action method depending
            /// on the incoming HTTP verb.
            /// For details on why MVC differentiates via HTTP verbs and doesn't use the 
            /// multiple URL approach see page 64.
            /// </remarks>
            [AcceptVerbs(HttpVerbs.Post)]
            public ActionResult Edit(int id, FormCollection formValues) {
                //Call method on our DinnerRepository to get the Dinner being edited
                var dinner = _dinnerRepository.GetDinner(id);
                //Verify that a dinner was found
                if (dinner == null)
                    return View("NotFound");
                //Verify that the logged-in user matches the dinner host
                if (!dinner.IsHostedBy(User.Identity.Name))
                    return View("InvalidOwner");
                //The "try" block will catch errors in calling UpdateModel or when we
                //try and save the DinnerRepository, which will throw if the Dinner object
                //we are tyring to save is invalid because of a rule violation.
                try {
                    //The "UpdateModel" helper method on the Controller base class supports updating
                    //the properties of the object being passed to it using the incoming form parameters.
                    //It uses reflection to determine the property names on the object, and then automatically
                    //converts and assigns values to them based on the input values submitted by the client.
                    //The method will automatically update the "ModelState" collection when it encounters errors
                    //while trying to assign form values to properties on the model object.  For example putting 
                    //something other than a DateTime in the EventDate field.
                    UpdateModel(dinner);
                    //Persist the changes
                    _dinnerRepository.Save();
                    //Return the Details view for the dinner being edited
                    return RedirectToAction("Details", new{id = dinner.DinnerId});
                }
                catch {
                    //Handle edit errors
                    //****** The code below was refactored to an extension method in the class ControllerHelpers
                    ////Loop through the rule violations and add to ModelState
                    //foreach (var issue in dinner.GetRuleViolations()){
                    //    //The "ModelState" property collection provides a way to indicate that
                    //    //errors exist with a model object being passed to a view.  Error entries
                    //    //within the the "ModelState" collection identify the name of the model 
                    //    //property with the issue and allow a human-friendly error message to be specified.
                    //    //HTML helper methods like "HTML.TextBox" check the "ModelState" collection to see 
                    //    //if there were any errors associated with the property on the model object the control
                    //    //is associated with.  If it determines that there was an error it renders the submitted user
                    //    //input as the value and adds a CSS error class to the markup it generates.
                    //    ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
                    //}
                    ModelState.AddRuleViolations(dinner.GetRuleViolations());
                    //Example below uses ViewData...which is not strongly-typed
                    //Add the SelectList to ViewData so the Countries drop down list is populated when rendered
                    //ViewData["countries"] = new SelectList(PhoneValidator.Countries, dinner.Country);
                    //Example using ViewModel which is strongly-typed
                    return View(new DinnerFormViewModel(dinner));
                    //Return the Dinner view
                    //return View(dinner);
                }
            }


    posted on Wednesday, 13 May 2009 17:17:26 (Central Daylight Time, UTC-05:00)  #    Comments [6]