MOGenerator and XCode4 integration guide

Posted May 31st, 2011 in Software Development by ryan

This article will not serve as an introduction to MOGenerator or it’s abilities – that subject has been covered elsewhere. The sole purpose of this guide is to provide you with the steps necessary to get MOGenerator pseudo-integrated with XCode 4, at least as much as possible at this time.

To summarize, we’ll be adding custom build steps to your project which instruct XCode to run shell scripts to process Core Data Model files. These scripts will determine the correct model version, call mogenerator to generate/update the entity classes, and then call momc to compile the model (this is usually performed by xcode, but since we’re inserting a new build rule for model files we need to handle it). I have tested these instructions on several different iOS projects, with multiple models and model versions.

Step 0) Download and install MOGenerator if you haven’t already. I used MOGenerator ver 1.22.

Step 1) Download the MOGenerator scripts and copy into a location in your project. For the purposes of this tutorial, I’ll put them in a folder named ‘scripts’ at the root of the project directory.

  • REQUIRED: Modify the script to suits your needs. You will need to change the name of the ManagedObject class your entities should inherit from, and you may want to change the output directory. For an explanation of each parameter please refer to the MOGenerator documentation.

Step 2) On the “Build Rules” tab of your target in XCode, add two build rules; one for “Data model files” and another for “Data model version files”

  • a. Change the Process dropdown to “Data Model Files”
  • b. Change the Using dropdown to “Custom Script”

Step 3) Put the path to the scripts in your project. In this example, they are in a folder “scripts” in the same directory as the Project file (Here is a list of all XCode environment variables).

Step 4) Add the output file pattern so XCode is knows what this custom step produces.

Step 5) Repeat steps 2-4 for the Data Model Version files. Take note that the file type processed, script executed, and output from this step are different. Refer to the screenshot

Step 6) Build your project.

Step 7) Any entities which are new (that is, which MOGenerator has not encountered in a previous build) will need to be manually added to your project. This step only needs to be performed when you have new entities, not during updates to existing entities.

If you have multiple targets in your project which utilize your data model, you’ll need to add these build steps for each target to make sure the model is kept up to date for each target.

I’d like to thank Jean-Denis Muys for providing the XCode4 integration steps needed to make this possible, and Jonathan Rentzsch for creating mogenerator.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Model Validation in ASP.NET MVC3

Posted February 17th, 2011 in Software Development by Matt

One of the cool new features in MVC3 is enhanced support for model validation via the IValidatableObject interface. By implementing this interface, a model class signals that it is in charge of at least some of the work required to validate itself. One of the best aspects of this new feature is that it integrates seamlessly with MVC’s model state validation.

There are already several examples available of the basic use of this feature in MVC3, so I thought we’d take a look at a somewhat more complex scenario. In this somewhat contrived example, the user will submit a review of a restaurant meal. We’ll be asking for an overall rating from 1 to 5, and for each menu item, the user will submit the name of the item, whether or not it was acceptable, and if it was not acceptable, why. In doing so, we’ll see how to implement IValidatableObject for a composite model class.

Here’s our basic top-level model object.

using System.ComponentModel.DataAnnotations;
 
namespace IValidatableObjectDemo.Models
{
    public class MenuRatingModel
    {
        [Display(Name="Overall Rating")]
        [Required]
        public byte OverallRating { get; set; }
        public MenuRatingListEntryModel[] ListEntries { get; set; }
    }
}

We’re taking advantage of some of the attributes in the System.ComponentModel.DataAnnotations namespace, and later, when we look at the view, we’ll see how they come in handy. Our top-level model object contains an array of sub-items of type MenuRatingListEntryModel, the initial definition of which looks like this.

using System.ComponentModel.DataAnnotations;
 
namespace IValidatableObjectDemo.Models
{
    public class MenuRatingListEntryModel
    {
        [Display(Name="Menu Item")]
        [Required]
        public string MenuItemName { get; set; }
 
        [Display(Name="Satisfactory?")]
        public bool WasSatisfactory { get; set; }
 
        [Display(Name="If not satisfactory, explain why.")]
        public string Explanation { get; set; }
    }
}

Naturally, we’ll need a controller, so here’s the code to serve up the form.

using System.Collections.Generic;
using System.Web.Mvc;
using IValidatableObjectDemo.Models;
 
namespace IValidatableObjectDemo.Controllers
{
    public partial class MenuRatingController : Controller
    {
        [HttpGet]
        public virtual ActionResult Index()
        {
            var model = new MenuRatingModel();
            List entries = new List();
            model.ListEntries = new []
                                    {
                                        new MenuRatingListEntryModel(),
                                        new MenuRatingListEntryModel(),
                                        new MenuRatingListEntryModel(),
                                        new MenuRatingListEntryModel()
                                    };
            return View(Views.Index, model);
        }
 
        [HttpPost]
        public virtual ActionResult Index(MenuRatingModel model)
        {
            if( ! ModelState.IsValid)
            {
                return View(Views.Index, model);
            }
            return Content("Submission successful.");
        }
    }
}

We’re creating an instance of the model pre-populated with four entries for menu items. Dynamically adding menu items is certainly doable; it’s beyond the scope of what we’re covering here, but Steve Sanderson has covered it on his blog. Note the line that returns the ViewResult; we’re using the T4MVC T4 template, which greatly reduces the need for magic string values to denote controller, action, and view names. If you’re not using it, you should be.

Here’s the first implementation of our view. We’re using the new Razor View Engine included with MVC3; it’s actually the default View Engine when creating a new MVC3 project, and after you use it for a while, you’ll see why. It’s much more elegant, concise, and readable than the old WebForms engine.

@model IValidatableObjectDemo.Models.MenuRatingModel
 
@{
 ViewBag.Title = "Menu Rating";
}
 
<h2>Menu Rating</h2>
@using (Html.BeginForm())
{
 <div id="overallRating">
@Html.LabelFor(m => m.OverallRating)
 @for (int ratingCounter = 1; ratingCounter <= 5; ratingCounter++)
 {
 @Html.RadioButtonFor(m => m.OverallRating, ratingCounter, new { id = "OverallRating_" + ratingCounter })
 @ratingCounter
 }
 @Html.ValidationMessageFor(m => m.OverallRating)
 </div>
 for (int entryCounter = 0; entryCounter < Model.ListEntries.Length; entryCounter++)
 {
 <div id="entryRating_@(entryCounter)">
 @Html.LabelFor(m => m.ListEntries[entryCounter].MenuItemName)
 @Html.EditorFor(m => m.ListEntries[entryCounter].MenuItemName)
 @Html.ValidationMessageFor(m => m.ListEntries[entryCounter].MenuItemName)
 
 @Html.LabelFor(m => m.ListEntries[entryCounter].WasSatisfactory)
 @Html.EditorFor(m => m.ListEntries[entryCounter].WasSatisfactory)
 @Html.ValidationMessageFor(m => m.ListEntries[entryCounter].WasSatisfactory)
 
 @Html.LabelFor(m => m.ListEntries[entryCounter].Explanation)
 @Html.EditorFor(m => m.ListEntries[entryCounter].Explanation)
 @Html.ValidationMessageFor(m => m.ListEntries[entryCounter].Explanation)
 </div>
 }
 <input type="submit" value="Submit Rating" />
}

When we use Html.LabelFor, MVC will automatically detect the [Display] attribute we included in the model and use it for the label text. If you load this up and try to submit without entering any values, the [Required] attribute we added will work its magic. Additionally, if you’re using jQuery Validation along with jQuery unobtrusive validation, these errors will be displayed on the client without any form post happening. Nice.

Simple (attempted) postback with basic validation

This is all well and good, but we’re going to add additional levels of validation. First, we want to ensure that, if the user has not checked the “satisfactory” box for a menu item, they must enter an explanation. Here’s where IValidatableObject comes into play. By implementing the IValidatableObject interface, we can handle simple object-level validation in the model itself. Here’s the new definition of the MenuRatingListEntryModel class.

using System.ComponentModel.DataAnnotations;
 
namespace IValidatableObjectDemo.Models
{
    public class MenuRatingListEntryModel : IValidatableObject
    {
        [Display(Name="Menu Item")]
        [Required]
        public string MenuItemName { get; set; }
 
        [Display(Name="Satisfactory?")]
        public bool WasSatisfactory { get; set; }
 
        [Display(Name="If not satisfactory, explain why.")]
        public string Explanation { get; set; }
 
        public System.Collections.Generic.IEnumerable Validate(ValidationContext validationContext)
        {
            if( ! WasSatisfactory && string.IsNullOrEmpty(Explanation))
            {
                yield return new ValidationResult("Please explain why.", new []{"Explanation"});
            }
        }
    }
}

We’re implementing the IValidatableObject interface and fulfilling the sole method in that interface, Validate(). Within the Validate() method, you can return a list of ValidationResult instances, each of which has an error message and a sub-list of property names to which the error applies. In our case, we’re only checking for one error, and we’re applying it to a single property (Explanation). Note that the string value provided to the ValidationResult must match the property name. This is how MVC matches up the ValidationResult to a ModelState entry.

Now here’s the cool part. If you try to do a partial submission now (let’s say, entering menu item names, checking “Satisfactory” for only two items, and providing no explanation), here’s what you get on the POST.

We have not altered our controller code in any way. Instead, the MVC3 Framework helpfully checks our model object(s) to see if they are IValidatableObjects, and if they are, it runs the validation code and adds any ValidationResults returned as ModelState errors. Now that’s handy.

Let’s move on to another task. Let’s suppose we want to add a constraint that says the user can’t submit the same item twice, so we want to check that the menu item name is unique. Initially, I thought we could take care of this sort of thing in the MenuRatingListEntryModel class, but we can’t. When the model binding process occurs and the Validate() method is called, it’s called when the MenuRatingListEntryModel instance is hydrated from the POST data and BEFORE it is attached to the parent model instance. This means we’ll have to take care of it in the parent model class. Here’s the revised definition.

using System.ComponentModel.DataAnnotations;
using System.Linq;
 
namespace IValidatableObjectDemo.Models
{
    public class MenuRatingModel : IValidatableObject
    {
        [Display(Name="Overall Rating")]
        [Required]
        public byte OverallRating { get; set; }
        public MenuRatingListEntryModel[] ListEntries { get; set; }
 
        public System.Collections.Generic.IEnumerable Validate(ValidationContext validationContext)
        {
            var grouping = this.ListEntries.GroupBy(listEntry => listEntry.MenuItemName.ToLowerInvariant());
            var duplicates = grouping.Where(group => group.Count() > 1);
            foreach(var duplicate in duplicates)
            {
                yield return new ValidationResult(
                    string.Format("You entered {0} {1} times", duplicate.Key, duplicate.Count()),
                    new [] {"ListEntries"}
                    );
            }
        }
    }
}

We’re using a bit of LINQ to find any list entries that have duplicate values entered for the menu item, regardless of casing. We’ll also add a ValidationMessageFor() call to our view on line 18, which will generate a validation message for the ListEntries property. Again, note that the property name returned in our ValidationResult matches this property name.

<div>
@Html.LabelFor(m => m.OverallRating)
    @for (int ratingCounter = 1; ratingCounter <= 5; ratingCounter++)
      {
          @Html.RadioButtonFor(m => m.OverallRating, ratingCounter, new { id = "OverallRating_" + ratingCounter })
          @ratingCounter
      }</div>
 
      @Html.ValidationMessageFor(m => m.OverallRating)
      @Html.ValidationMessageFor(m => m.ListEntries)

Here’s the result of a post with a duplicate submission.

While this approach streamlines things considerably, there are some definite downsides to consider.

  • If model validation fails on the child object, the validation code on the parent object is run, but for some reason the parent ValidationResult(s) returned do not get appended as errors to the model state. That is, you’ll see errors for the child object(s), but the errors for the parent object will not display until the child errors are cleared. This will probably require a deeper dive into the MVC3 source code to find out why.
  • If multiple errors are returned for the same property, only one is displayed in a single ValidationMessageFor() call. This can be remedied with a ValidationSummary, but that may not fit within your design guidelines; also, if you intend to rate multiple menus on the same page, the ValidationSummary presents its own set of problems.

If you’ve got solutions for these issues, let us know. Source code can be downloaded here.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Getting rid of Magic Strings in Entity Framework 4 Includes

Posted January 31st, 2011 in Software Development by Matt

One way to optimize Entity Framework queries is to gather all the information you KNOW you will need at the time the query is executed, to avoid additional deferred queries. A common way of doing this is by using the .Include() method, which specifies additional tables/entities to be pulled at the time the query is run. There’s a minor problem with this; the .Include() method takes a string to indicate the objects to retrieve. This presents a significant problem for Agile developers, or any situation where your database or object schema is likely to undergo any significant amount of churn or refactoring. Consider the following excerpt from an Entity Framework 4 EDMX file, where we have a Job Entity and a parent JobType entity.

edmx

When we retrieve a job and want to include the job type information as part of the same query, the initial implementation would look something like this.

Not so hot
  1. Job job = entityContext.Jobs
  2. .Include(“JobType”)
  3. .SingleOrDefault(j => j.JobId == jobId);

I don’t know about you, but the use of a magic string value to represent the parent table leaves me with a feeling of impending doom. If you decide to rename your parent entity to JobCategory, or introduce another entity between JobType and Job, your code will fail and you won’t catch it until execution time.

Magic strings are undergoing something of a renaissance in Microsoft technologies, and it’s a little disconcerting. ASP.NET MVC is riddled with them, and a group of like-minded developers have come up with the wonderful T4MVC template to eliminate or greatly reduce the need for these pesky buggers. It’s a tremendous boon to insulate your code against refactoring.

In our current project, we are using the ADO.NET Self-Tracking Entity Generator Template to create entities that keep track of their own changes but which are ignorant of their storage mechanism. Our application server tier is implemented in WCF, and this template is well-suited to architectures where the consuming application and the application server are both .NET-based.

Eliminating the magic strings requires a minor modification to the T4 template that generates the entities. Our insertion begins after line 194 of this template, which ends the region that generates complex properties for our entities, and before navigation properties are generated. Here’s what we’re inserting.

  1. region.Begin(“Include Reference Names”);
  2. #>
  3. public static <#=(entity.BaseType == null ? “” : “new “)#>class IncludeReferences
  4. {
  5. <#
  6. foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
  7. {
  8. #>
  9. public static readonly string For<#=code.Escape(navProperty)#> = “<#=code.Escape(navProperty)#>”;
  10. <#
  11. }
  12. #>
  13. }
  14. <#
  15. region.End();

When T4 is run again, we get something like the following added to our entity definition for the Job class.

  1. #region Include Reference Names
  2. public static class IncludeReferences
  3. {
  4. public static readonly string ForJobType = “JobType”;
  5. }
  6. #endregion

A public static inner class is generated for each entity, allowing us to rewrite our EF query like so:

Feels Better
  1. Job job = entityContext.Jobs
  2. .Include(Job.IncludeReferences.ForJobType)
  3. .SingleOrDefault(j => j.JobId == jobId);

Are the magic strings still there? Absolutely. But they’re defined in such a way that if your database schema or entity model change significantly, your code will break at compile time, which is vastly preferable to a run-time code bomb.

OK, what about those queries where we need to retrieve entities that are more than one level away? Consider the following additional excerpt from the EDMX. A job is at a location, and a location is tied to a state/province.

edmx

No problem.

  1. Job job = entityContext.Jobs
  2. .Include(Job.IncludeReferences.ForJobType)
  3. .Include(Job.IncludeReferences.ForLocation)
  4. .Include(Job.IncludeReferences.ForLocation + “.” + Location.IncludeReferences.ForStateProvince)
  5. .FirstOrDefault(j => j.JobId == jobId);

This can now devolve into a heated debate vis-à-vis the relative merits of appending strings vs. String.Format() vs. String.Join(). Nothing like bringing a gun to a knife-fight.

FINAL NOTE:

Hey, what’s with the “new”? Well, if you are using any sort of entity inheritance, your child entities will use the new keyword to mask any references from the parent class. This will come up if you are using either of the inheritance schemes available in EF4, which are table-per-hierarchy (TPH) and table-per-type (TPT). If you are using TPT, be aware that there are significant performance considerations.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

MVC – Validating Additional Required Inputs

Posted September 26th, 2010 in Uncategorized by cody

In MVC, common validation can be done with a trivial amount of code using attributes on your model views, but once you step outside of the simple required, length, and type validations things can get complicated in a hurry.

Our client needed a view that required the user to provide additonal input if a question was answered as yes.  Providing this functionality required more than a simple [Required] attribute on the display model.

There are multiple ways this can be done; this post will provide a quick tutorial on how we went about implementing a solution.

We had already chosen to use the JQuery validation library provided by the MVC2 template.  The function __MVC_EnableClientValidation(validationContext) in the MicrosoftMvcJQueryValidation.js file must be modified to add hidden elements to the “ignore” list:

   1: var options = {
   2:         errorClass: "input-validation-error",
   3:         //validClass: "",
   4:         errorElement: "span",
   5:         errorPlacement: function (error, element) {
   6:             var messageSpan = fieldToMessageMappings[element.attr("name")];
   7:             $(messageSpan).empty();
   8:             $(messageSpan).removeClass("field-validation-valid");
   9:             $(messageSpan).addClass("field-validation-error");
  10:             //error.removeClass("input-validation-error");
  11:             error.addClass("field-validation-error");
  12:             error.attr("_for_validation_message", messageSpan);
  13:             error.appendTo(messageSpan);
  14:         },
  15:         messages: errorMessagesObj,
  16:         rules: rulesObj,
  17:         invalidHandler: function () { theForm.trigger('invalidHandler'); },
  18:         ignore: ":not(:visible)",
  19:         success: function (label) {
  20:             var messageSpan = $(label.attr("_for_validation_message"));
  21:             $(messageSpan).empty();
  22:             $(messageSpan).addClass("field-validation-valid");
  23:             $(messageSpan).removeClass("field-validation-error");
  24:         }
  25:     };

The next step is to create your question/additional input model:

   1: [Required()]
   2: [Display(Name = "Do you like MVC2 better than WebForms?")]
   3: [YesNoControl(new string[2] { "Date", "Why" }, "DoesLikeMvcBetter")]
   4: public bool DoesLikeMvcBetter{ get; set; }
   5: [Required(ErrorMessage = "Date is required.")]
   6: public DateTime Date { get; set; }
   7: [Required(ErrorMessage = "A reason is required.")]
   8: public string Why { get; set; }

The YesNoControl attribute will be discussed later in this post.  The model needs at least two properties, the question control as a boolean and at least one other control that will be validated, but can display any additional number of controls.  In this example, there are two additional controls, one for the date the questions is answered and a reason.

   1: <div>
   2:     <%= Html.LabelFor(m => m.IsMVCBetterThanWebForms)%>
   3:     <span style="display:block;">
   4:         <%= Html.RadioButton("IsMVCBetterThanWebForms", "true", Model != null ? Model.IsMVCBetterThanWebForms : false, new { @onclick = "$('#IsMVCBetterThanWebForms_span').show()" })%><label for="Yes" style="width:20px;display:inline">Yes</label><br />
   5:         <span id="IsMVCBetterThanWebForms_span" style="display: <%= Model != null && Model.IsMVCBetterThanWebForms ? "normal" : "none" %>; width:800px; position:relative; left:25px">
   6:             Date:<%= Html.EditorFor(m => m.Date) %><%= Html.ValidationMessageFor(m => m.Date)%>
   7:             and Why: <%= Html.EditorFor(m => m.Why) %><%= Html.ValidationMessageFor(m => m.Why)%>
   8:         </span>
   9:     </span>
  10:     <%= Html.RadioButton("IsMVCBetterThanWebForms", "false", Model != null ? !Model.IsMVCBetterThanWebForms : false, new { @onclick = "$('#IsMVCBetterThanWebForms_span').hide()" })%><label for="No" style="width:20px;display:inline-block;">No</label><br />
  11:     <%= Html.ValidationMessageFor(m => m.IsMVCBetterThanWebForms)%>
  12: </div>

Then in your view you add markup that displays a radio button for the yes/no answer.  This markup adds the radio button that the user must select yes or no.  If the user selects yes, then the follow-up questions are display and require input before the form will post successfully.

So now we have a question control.

image

If the user doesn’t enter a value, the error is caught client-side and the form will not post.

image

If the user selects “Yes”, additional inputs are displayed.

image

And must be answered before proceeding as well.

image

This takes care of the client side validation, but since the server validates the model during binding, ModelState.IsValid will return false if the user answered “No” since Date and Why are empty.  This could be handled manually in the controller code, but the route we chose was to let  model binding handle it.

The next step is to create an attribute to use to decorate the model view:

   1: [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
   2:    public sealed class YesNoControlAttribute : Attribute
   3:    {
   4:        private static string defaultTemplateName;
   5:        public static string DefaultTemplateName
   6:        {
   7:            get
   8:            {
   9:                if (string.IsNullOrEmpty(defaultTemplateName))
  10:                {
  11:                    defaultTemplateName = "YesNoControl";
  12:                }
  13:
  14:                return defaultTemplateName;
  15:            }
  16:            set
  17:            {
  18:                defaultTemplateName = value;
  19:            }
  20:        }
  21:        public string TemplateName { get; private set; }
  22:        public string[] HiddenControls { get; private set; }
  23:        public IDictionary<string, object> HtmlAttributes { get; private set; }
  24:        public string ControlName { get; set; }
  25:
  26:        public YesNoControlAttribute(object hiddenControls, string controlName)
  27:            : this(DefaultTemplateName, hiddenControls, controlName, null)
  28:        {
  29:        }
  30:
  31:        public YesNoControlAttribute(object hiddenControls, string controlName, object htmlAttributes)
  32:            : this(DefaultTemplateName, hiddenControls, controlName, htmlAttributes)
  33:        {
  34:        }
  35:
  36:        public YesNoControlAttribute(string templateName, object hiddenControls, string controlName, object htmlAttributes)
  37:        {
  38:            if (string.IsNullOrEmpty(templateName))
  39:            {
  40:                throw new ArgumentException("Template name cannot be empty.");
  41:            }
  42:
  43:            if (string.IsNullOrEmpty(controlName))
  44:            {
  45:                throw new ArgumentException("Control field cannot be empty.");
  46:            }
  47:
  48:            if (((string[])hiddenControls).Count() < 1)
  49:            {
  50:                throw new ArgumentException("Hidden Controls must contain at least one control name.");
  51:            }
  52:
  53:            TemplateName = templateName;
  54:            ControlName = controlName;
  55:            HiddenControls = (string[])hiddenControls;
  56:            HtmlAttributes = new RouteValueDictionary(htmlAttributes);
  57:        }
  58:
  59:    }

This class inherits from the attribute and allows you to decorate a property and add the name of the controls that will be displayed and validated as a required field if the use answers as yes.

Then create a custom model binder to handle the binding of your question model.  If you are not familiar with custom model binding there are many sources that have covered that topic.

   1: public class QuestionDataModelBinder : IModelBinder
   2:     {
   3:         public new BindResult BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
   4:         {
   5:             var b = new BindResult(base.BindModel(controllerContext, bindingContext), null);
   6:             var pdm = b.Value as AllMyQuestionsModel;
   7:
   8:             if(pdm == null) return b;
   9:
  10:             var props = pdm.GetType().GetProperties();
  11:
  12:             // this checks if any of the properties have a custom attribute of "YesNoControlAttribute"
  13:             // if it does, it checks to see if it's false, and removes the errors of the controls specified
  14:             foreach (string ctlName in (from propertyInfo in props
  15:                                         let isYes = propertyInfo.GetCustomAttributes(typeof (YesNoControlAttribute), false).Any()
  16:                                         where isYes
  17:                                         let res = bindingContext.ValueProvider.GetValue(propertyInfo.Name)
  18:                                         where res != null && bool.FalseString.Equals(res.AttemptedValue, StringComparison.CurrentCultureIgnoreCase)
  19:                                         select propertyInfo).SelectMany(propertyInfo => Enumerable.SelectMany<string[], string>((from attrib in propertyInfo.GetCustomAttributes(typeof (YesNoControlAttribute), false)
  20:                                                                                                                                  select ((YesNoControlAttribute) attrib).HiddenControls), ctls => ctls)))
  21:             {
  22:                 RemoveErrors(bindingContext, ctlName);
  23:             }
  24:             return b;
  25:         }
  26:     }

This class checks to see if any properties on the model it’s binding have a “YesNoControl” attribute.  If the attempted value is false, it removes the model state errors that are on any of the controls specified in the attribute.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

WPF WTF – Data Binding Happens When, Now?

Posted September 24th, 2010 in Uncategorized by Matt

Data binding in WPF still seems to be a bit of a black art. In a recent project, I ran into an issue where data binding was happening considerably later than expected.

Here’s the scenario: we are presenting the user with a modal dialog where they can, among other things, choose a specific font for use in a specific area of the application from a restricted list of specified fonts. The modal dialog shouldn’t be concerned with retrieving the font list because, in our particular MVP Pattern, that’s not its job.

We’re storing the font information in a very simple class.

[Serializable] public class FontInformation { public string FontName { get; set; } public int FontSize { get; set; } }

“But Matt! FontFamily is available in System.Drawing….” Yes, Carl, I know. (Apologies if your name is not Carl.) We’re planning on serializing this information for later storage in user preferences, and we’d like to avoid building in unnecessary dependencies where possible.

Here’s our first stab at the properties in the modal dialog, and how it’s implemented in the XAML.

protected internal IEnumerable<FontInformation> AvailableFonts { get { return lstFont.DataContext as IEnumerable<FontInformation>; } set { lstFont.DataContext = value; } } public FontInformation SelectedFont { get { return lstFont.SelectedItem as FontInformation; } set { lstFont.SelectedItem = value; } }

<ComboBox Name="lstFont" ItemsSource="{Binding}"> <ComboBox.ItemTemplate> <DataTemplate> <!--display the font name, written in the selected font, size, and style.--> <TextBlock Text="{Binding Path=FontName}" FontFamily="{Binding Path=FontName}" FontSize="{Binding Path=FontSize}"/> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox>

The combo box draws its list of available fonts from the property setter and displays each font drawn in its own…uh…font. This implementation allows the calling code to be completely agnostic of how the View is displaying allowed fonts and setting the selected font. Here’s where the problem reared its head, in the calling code that readies the modal dialog.

MessageOptionsForm msgOptionsForm = new MessageOptionsForm(); msgOptionsForm.AvailableFonts = this.OptionsController.AvailableMessageFonts; msgOptionsForm.SelectedFont = this.FlipbookOptions.MessageFontInformation;

I naively thought that, after setting DataContext on the combo box, that the child items would be available for selection. However, when we try to set the SelectedFont property before the control loads, data binding has not occurred yet, and the setter for SelectedFont does a whole bunch of nothing. (Hey, at least it doesn’t blow up.)

Now you have two options.

  1. Track the SelectedFont with a private FontInformation instance and set it when the window loads. This creates a point of confusion for the programmer who follows me since setting the value of that private instance will do, again, a whole bunch of nothing.
  2. Get crafty.

Here’s the modified implementation.

public FontInformation SelectedFont { get { return lstFont.SelectedItem as FontInformation; } set { if (lstFont.IsLoaded) { lstFont.SelectedItem = value; } else { //setter might get triggered before options have finished loading. lstFont.Loaded += delegate { lstFont.SelectedItem = value; }; } } }

The IsLoaded property tells us whether a framework element has been loaded for presentation (and thus is available for data binding). Here we are attaching an anonymous delegate to the Loaded event to select the correct option.

This implementation solves another potential problem with the first stab: if the calling code sets SelectedFont before setting AvailableFonts, nothing will happen. This is bad, and it violates the general principle that you should allow properties to be set in any order.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Dependency Injected Action Filters in ASP.NET MVC2

Posted May 6th, 2010 in Software Development by ryan

On one of our current projects utilizing all the latest Microsoft has to offer (MVC2, EF4, Unity, .NET 4) we found ourselves creating a number of Action Filters for encapsulating often used behavior, such as Auditing, Authorization, and temp data management. Action filters are an incredibly powerful tool in MVC, capable of manipulating any piece of the request/response and making that behavior easy to reuse. The problem with Action Filters, on the surface, is that there is no immediately apparent method of injecting dependencies into those filters – they’re just attributes on a method in your controller, or on the class of the controller itself, such as below:

[Authorized]
public class WidgetController : MyControllerBase
{
 [Audit("Doing something")]
 public ActionResult DoSomething()
 {
 ...
 }
}

In the case where your attribute has dependencies that should be resolved by your DI container, you may find yourself manually resolving those dependencies every time, which can get tedious and error prone. The answer to this lies in the Controller, but first we need a little background on how the Action Filters are actually executed.

When the MVC routing system finds the Controller for the current request, it uses an instance of that controller create to an ActionInvoker, which will be used in executing the action(s) on the controller. This ControllerActionInvoker is responsible for finding the appropriate action given the route on that controller, as well as invoking the action AND the actions filters. Since the ControllerActionInvoker is responsible for actually creating instances of the Filters, it’s the ideal location to put code responsible for building up the dependencies of any Filters on your action methods. With a minimal amount of code, we should be able to usurp the ActionFilter creation process and inject our dependencies before the filter executes.

First, we’ll need a DI wrapper. The one below is a snippet from mine which acts as a shell around Unity:

public static class ServiceResolver
{
        public static T InjectDependencies(T instance)
        {
            return (T)_container.BuildUp(instance.GetType(), instance);
        }
 ...
}

Now, the custom action invoker, which for these purposes only needs to override GetFilters(…), since this is the method responsible for getting the filters on a given Action:

public class MyActionInvoker : ControllerActionInvoker
{
        protected override FilterInfo GetFilters(ControllerContext controllerContext, 
            ActionDescriptor actionDescriptor)
        {
            var filters = base.GetFilters(controllerContext, actionDescriptor);
 
            filters.ActionFilters.ForEach(
               f => ServiceResolver.InjectDependencies(f));
            filters.AuthorizationFilters.ForEach(
               f => ServiceResolver.InjectDependencies(f));
            filters.ExceptionFilters.ForEach(
               f => ServiceResolver.InjectDependencies(f));
            filters.ResultFilters.ForEach(
               f => ServiceResolver.InjectDependencies(f));
            return filters;
        }
}

Note that we iterate over all the different filter collections that are returned as a result of the call to base.GetFilters(…). This ensures that any filters we create for any part of the action process will have dependencies resolved. Now you need to make sure your custom ActionInvoker is used any time MVC is trying to invoke an action on your controllers, so you’ll need a common base Controller class that all of your controllers will inherit from.

public abstract class MyControllerBase : Controller
{
        protected override IActionInvoker CreateActionInvoker()
        {
            return new MyActionInvoker();
        }
}

Now any ActionFilters which have property-based dependencies will be automatically fulfilled by the new ActionInvoker, such as the AuditAttribute show below:

public class AuditAttribute : System.Web.Mvc.ActionFilterAttribute
{
        [Dependency]
        public IUserRepository UserRepository { get; set; }
        [Dependency]
        public ILogger Logger { get; set; }
...
}
Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)