# Monday, December 05, 2011

Configuration of Entity Framework Code First is a necessary evil and you have to admit is a very well designed user friendly process.  But, in typical Microsoft fashion, the EF developers have given us more than one way to perform this configuration.

  1. Fluent API
    1. Fluent expression based configuration
    2. Performed during the OnModelCreating process of the DbContext.
    3. Allows for complex configurations that are not possible via Attribute based configuration
      Fluent Configuration
      1. protected override void OnModelCreating(DbModelBuilder modelBuilder) {
      2.     modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
      3.     modelBuilder.Entity<Model>().HasMany(x => x.AvailableEngines)
      4.         .WithMany(x => x.AvailableOn)
      5.         .Map(x => x.MapLeftKey("ModelId")
      6.         .MapRightKey("EngineId")
      7.         .ToTable("ModelEngine"));
      8.     modelBuilder.Entity<Model>().Ignore(x => x.SomeDerivedProperty);
      9.     base.OnModelCreating(modelBuilder);
      10. }

  2. Attributes
    1. Attribute based configuration
    2. Performed directly on the Domain Model Class/Property being configured
    3. Allows the non-EF specific attributes to be used in other pieces of your application
    4. Allows validation of your Model at any time
      Attribute Configuration
      1. public class Manufacturer {
      2.  
      3.     public long ManufacturerId { get; set; }
      4.  
      5.     [StringLength(40)]
      6.     [Required]
      7.     public string Name { get; set; }
      8.  
      9.     [Required]
      10.     [StringLength(40)]
      11.     public string Country { get; set; }
      12.  
      13.     [Required]
      14.     public DbGeography Location { get; set; }
      15.  
      16.     #region << Relationships >>
      17.  
      18.     public virtual IList<Model> Models { get; set; }
      19.  
      20.     #endregion
      21.  
      22. }

 

So…When do you use which!?

Use Fluent Configuration When:

  • Configuration is being done solely to make the database behave correctly.
  • Configuration has no effect on the design and/or behavior of your Domain Model.
  • Examples:
    • Specifying the database table the Domain Model is to be mapped to
    • Specifying the database table column the Domain Model Field is to be mapped to
    • Ignoring a Domain Model Field
    • Configuring the keys and table names for relationships not able to be picked up by EF

Use Attribute Configuration When:

  • Configuration solely applies to your Domain Model.
  • Configuration has no effect on the design and/or behavior of your Database.
  • Examples:
    • Making a field Required
    • Validating a field (String length, Range, etc.)
  • Also…Don’t forget that for the most part these Attributes are not EF specific and can be used in the UI with MVC.
posted on Monday, December 05, 2011 8:53:57 AM (Central Standard Time, UTC-06:00)  #    Comments [1]
# Monday, November 28, 2011

The jQuery Accordion control is great for creating rich interactive HTML menus.  I used it in a recent project where I wanted “Home” to be the top menu option.  I Googled around and wasn’t able to find a way to have a menu item with no children link to some URL.  So I played around for a bit and came up this solution. 

  1. $(function() {
  2.     $("#navigationMenu").accordion({ autoHeight: false });
  3.     $('#homeNavMenu').find('a').click(function() { window.location = '/'; });
  4. });
posted on Monday, November 28, 2011 9:52:57 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Monday, November 21, 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, November 21, 2011 9:46:18 AM (Central Standard Time, UTC-06:00)  #    Comments [9]
# Monday, November 14, 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, November 14, 2011 8:46:32 AM (Central Standard Time, UTC-06:00)  #    Comments [3]
# Monday, November 07, 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, November 07, 2011 8:53:15 AM (Central Standard Time, UTC-06:00)  #    Comments [2]