Category Archives: MVC

Database driven Asp.net MVC Model Binding, Validation, and Metadata

One of classic MVC paradigms is that you can bind class models to a view, and with attribute based annotations, you can have synchronized server and client side validations on them. This concept is absolutely brilliant! Code once and you don’t have to worry about duplicating your server side logic in the untrustworthy browser.

This is all fine and dandy if your validation logic and your models don’t change often. Consider the scenario that you are developing an application that will likely change over time. Or perhaps, you need to develop your app such that the client has put it in the requirements that they need to have control over the content long after you have completed the app. If they need to control the content and the form fields (inputs), those inputs will still need to be validated.

Enter database driven model validation, binding and metadata.

I have successfully developed implementations of the following, which accomplish exactly what I need:

ModelBinder
ModelValidationProvider
ModelMetadataProvider

My implementations heavily leverage the power of the extensible MVC DataAnnotations providers which read the attribute based metadata that you can decorate your classes with.

The code that I have written is currently in a state that is tightly bound to the database schema of the project I am currently working on. My plan is to extract the juice from the project so that the code is reusable to all.

I’m sorry to say that at this point, I have no code examples, but they will surely follow!

Await, Async, Mvc and Impersonation

I’ve been using AsyncControllers in Asp.net mvc for quite a while now.   I’ve also been using the Tasks Parallel Library sparingly.  Only recently have I used them together, with and without the new .Net 4.5 async and await keywords.  Throw unmanaged impersonation into the mix and you’re in for a smorgasbord of technologies that don’t necessarily play well together.

I want to tell you a story, but I must first set the stage for you.

  • I was developing an internal web app for my company TempWorks Software.
  • I Wanted to make use of concurrency wherever possible.
  • The data layer needed several different elevated credentials in varying contexts, other than that of the AppPoolIdentity.

Our last release to production web product, WebCenter 6 used AsyncControllers, taking advantage of the AsyncManager, rather than Task’s with continuation. If you are unfamiliar with either, have a look at this concise outline of the evolution of Mvc asynchronous controllers here. This time, I chose to use the more straightforward, Task with Task.ContinueWith.

The first problem I encountered was trying to make my impersonation context flow through my tasks and continuations. Imagine something like the following inside one of my Actions (the important thing to note is how I am doing impersonation).

FeatureEditorViewModel viewModel;

using (ElevatedUser.Impersonate())
{
    var features = LicensingService
        .GetFeatures(false);

    viewModel = new FeatureEditorViewModel(features, versionID, productID);
}

return View(viewModel);

The IDisposable ElevatedUser object you see above is a derivative of the code in the following article: Windows Impersonation Using C#. The important part about this is that it is IDisposable in my class, and that it is calling unmananged code via DllImport to do impersonation.

Interestingly enough, I never noticed any problem with this until I deployed to production servers. The reason was, that because I was using IIS Express, my AppPoolIdentity was in fact MY user account, and I happened to have permissions on the object I was accessing. When I deployed to production, the AppPoolIdentity was no longer me, it was the App Pool user account, thus making all data calls under the wrong context.

I scoured the net in search of answers, and discovered that I had a few options.

1. Change the aspnet.config file (there are 2 of them if you have an x64 machine), setting the value “legacyImpersonationPolicy” to enabled=false, and “alwaysFlowImpersonationPolicy” to enabled=true
2. Do the same as above except in the context of the app pool only (I discovered later on that this does not work)
3. Capture the impersonation context outside of my thread, and then re-impersonate inside of my thread

I chose option 3 because I wanted to adhere to the least privilege principal. I wanted keep elevated credentials to the absolute minimum so as not to expose any overlooked security holes in my application.

I came up with my own TPL extension method class that I could use in place of the default TPL methods.

using System;
using System.Linq;
using System.Security.Principal;
using System.Threading.Tasks;

public static class TaskFactoryExtensions
{

    public static Task StartNewImpersonated(this TaskFactory taskFactory, Action action)
    {
        var identity = WindowsIdentity.GetCurrent();
        return taskFactory.StartNew(() =>
        {
            using (identity.Impersonate()) 
            {
                action();
            }
        });
    }

    public static Task<TResult> StartNewImpersonated<TResult>(this TaskFactory taskFactory, Func<TResult> function)
    {
        var identity = WindowsIdentity.GetCurrent();
        return taskFactory.StartNew<TResult>(() =>
        {
            using (identity.Impersonate())
            {
                return function();
            }
        });
    }

    public static Task ContinueWithImpersonated<TResult>(this Task<TResult> task, Action<Task<TResult>> continuationAction)
    {
        var identity = WindowsIdentity.GetCurrent();

        return task.ContinueWith((antecedent) =>
        {
            using (identity.Impersonate())
            {
                continuationAction(antecedent);
            }
        });
    }

    public static Task<TNewResult> ContinueWithImpersonated<TResult, TNewResult>(this Task<TResult> task, Func<Task<TResult>, TNewResult> continuationFunction)
    {
        var identity = WindowsIdentity.GetCurrent();

        return task.ContinueWith<TNewResult>((antecedent) =>
        {
            using (identity.Impersonate())
            {
                return continuationFunction(antecedent);
            }
        });
    }

    public static Task ContinueWhenAllImpersonated(this TaskFactory taskFactory, Task[] tasks, Action<Task[]> continuationAction)
    {
        var identity = WindowsIdentity.GetCurrent();

        return taskFactory.ContinueWhenAll(tasks, (antecedent) =>
        {
            using (identity.Impersonate())
            {
                continuationAction(antecedent);
            }
        });
    }

    public static Task<TResult> ContinueWhenAllImpersonated<TResult>(this TaskFactory taskFactory, Task[] tasks, Func<Task[], TResult> continuationFunction)
    {
        var identity = WindowsIdentity.GetCurrent();

        return taskFactory.ContinueWhenAll<TResult>(tasks, (antecedent) =>
        {
            using (identity.Impersonate())
            {
                return continuationFunction(antecedent);
            }
        });
    }

    public static void ForAllImpersonated<TSource>(this ParallelQuery<TSource> source, Action<TSource> action)
    {

        var identity = WindowsIdentity.GetCurrent();

        source.ForAll(new Action<TSource>((tsource) =>
        {
            using (identity.Impersonate())
            {
                action(tsource);
            }
        }));
        
    }

}

This worked great aside from the fact that everytime I needed to use a varied overload in the TPL, I needed to code a new extension method in my class.

Enter .Net 4.5… Async, await.

Before converting my app to 4.5 and the “new way” of doing things, I ingested as many Kindle books as I could find on the topic. Here is my short list:

So here I was at a cross-roads. I now had enough knowledge to start using the async and await keywords in place of “continuations” using ContinueWith and various Wait techniques. At this point however, I theorized that if I was to substitute usage of ContinueWith (or in fact, my very own ContinueWithImpersonated as noted above) with await, that the impersonation context would be lost.

I converted a couple of methods to async/await and threw in a couple of debug breakpoints. To much chagrin, I was right, the impersonation context was lost AFTER my await keyword.

Back to the drawing board! My options were few, and I still didn’t want to turn on the aspnet.config options that I mentioned earlier.

I then diagrammed my architecture:

* Controller
* Actions -> call services via Tasks (impersonate here)
* Services -> call repositories via Tasks
* Repositories

It became very apparent that because I couldn’t persist my impersonation context through tasks and continuation, that I had to move where I was doing my impersonation.

My arch then looked like this:

* Controller
* Actions -> call services via Tasks
* Services -> call repositories via Tasks
* Repositories (impersonate here)

So, now I would have to rewrite how I was calling my database, so that impersonation was done there.

I am using a variation of Oh So Simple SQL, so I created some extension method overloads to handle this.

    public static class RepositoryExtensions
    {
        // public List<O> FetchAll<O>();
        public static List<O> FetchAll<O>(this QueryBuilder<StoredProcedure> baseQuery, IElevatedUser elevatedUser)
        {
            using (elevatedUser.Impersonate())
            {
                return baseQuery.FetchAll<O>();
            }
        }
        public static List<O> FetchAll<O>(this QueryBuilder<Query> baseQuery, IElevatedUser elevatedUser)
        {
            using (elevatedUser.Impersonate())
            {
                return baseQuery.FetchAll<O>();
            }
        }

        //public O Fetch<O>();
        public static O Fetch<O>(this QueryBuilder<StoredProcedure> baseQuery, IElevatedUser elevatedUser)
        {
            using (elevatedUser.Impersonate())
            {
                return baseQuery.Fetch<O>();
            }
        }
        public static O Fetch<O>(this QueryBuilder<Query> baseQuery, IElevatedUser elevatedUser)
        {
            using (elevatedUser.Impersonate())
            {
                return baseQuery.Fetch<O>();
            }
        }

        //public void Execute();
        public static void Execute(this QueryBuilder<StoredProcedure> baseQuery, IElevatedUser elevatedUser)
        {
            using (elevatedUser.Impersonate())
            {
                baseQuery.Execute();
            }
        }
        public static void Execute(this QueryBuilder<Query> baseQuery, IElevatedUser elevatedUser)
        {
            using (elevatedUser.Impersonate())
            {
                baseQuery.Execute();
            }
        }

    }

My IElevatedUser object looks like this:

    public interface IElevatedUser : IDisposable
    {

        IElevatedUser Impersonate();
        IElevatedUser Impersonate(string account, string password);

        string Account
        {
            get;
            set;
        }

        string Password
        {
            get;
            set;
        }

    }

The moral of the story is 2-fold.

1. Impersonation doesn’t flow through the TPL automatically
2. Make sure you are doing impersonation at the right place

I’ve also compiled the impersonation classes as a gist available here.

Twin Cities Code Camp 2012 – Day 1

This post will be a compilation of my notes from Twin Cities Code Camp 2012.

Understanding WebAPI in ASP.NET MVC 4 – Matt Milner – Rapson 56

What is web api?

  • API for HTTP Services – client and server components
  • WCF vs MVC – why do we need this api?
  • WCF – some people just want HTTP, REST services is complicated. Global error handling is almost impossible. Goal was to make WCF extremely flexible. Transport neutral just like SOAP. Because WCF was trying to cover ALL transports and protocols, HTTP became buried.

MVC was primarily built to pass back a View – typically HTML. JSON/JSONP were after thoughts. This is not a perfect model for RESTful services.

HTTP is a protocol in and of itself. Don’t need another protocol (e.g. SOAP). The protocol has been optimized over the years.

HTTP is widely accessible and MUCH easier to reach ALL devices.

Web API MVC Integration

  • MVC is for web applications
  • Web API is for web APIs
  • what they have in common is usually the model or domain

Cool new features: media type formatters for resource type handling. validation at the handler level which supports cancelation and pass-through instead of lowest level – the action. Better json support with the new System.Json library. Self-hosted testing built upon a partial wcf service stack. Support for OData URI queries. Simply return IQueryable. CONS: partial support for OData – only $page, $filter, and $sort – not $select. Doesn’t seem like the will be adding support for this. There is talk about adding built in support for Expression for DTO transformation on the server side.

There is also talk about combining the ServiceResolver configuration (configuration.ServiceResolver.SetResolver) to support both MVC and WebAPI in the same call. For example, right now you configure your MVC service resolving and a separate configuration for WebAPI service resolving. Simplification of this is on the table. Hopefully by the time the release comes around, we see a unified method.

TAKEAWAY MESSAGE: FORGET COMPLICATED SOAP PROTOCOL which is the standard for RIA Services and WCF. Simplify your api with REST. Forget about the mvc paradigm of method based access to your resources. You now access your resources via GET, POST, PUT, DELETE. You access a resource from a Controller. One controller per type of resource. Web API has content negotiation. It returns the data in the format that your request based on the Accept header. If I want JSON, I get JSON. You could expand upon this to return resources in whatever format you need; image, doc, resume, and more. The same for xml. Etc… Input validation is handled by the model binding mechanisms of MVC which builds a model state object.

Note: WebAPI is NOT a replacement for WCF. If you still need to support multiple endpoints in different protocols (for example pure TCP), then WCF is still the best option out there. If you want a simplified API that will be accessible for the widest audience, consider WebAPI.

NOTE TO SELF: check out $.validator.unobtrusive.revalidate(form, validationResult) – validationResult is the json object; { “Speaker”: “Speaker is required” } – where in this example Speaker is the name attribute of the form input element – this takes a json object and interprets it using jquery.validation unobtrusive. Is this a NEW method?

Async Today and Tomorrow – Joe Mayo – Rapson 54

Talk about the Async CTP. How we use async programming today and how we will use it in the future. The Async CTP hides the complexity of async programming. It leverages the TPL (Tasks Parallel Library).

Why do we need async for UI responsiveness? Ex. click on a button in a Windows Form. The program does some long running operation. The user doesn’t know what is happening until all of a sudden, the UI shows something. NOT A GOOD USER EXPERIENCE.

TPL at it’s core revolves around the Task class. It has a fluent api. Uses continuation methods (similar to callbacks).

  • Language Integration – Changes to C# and VB in .NET. Async – the await and async Context Keywords.
  • Every platform – Desktop, Web, and Device
  • leverage Opportunities – Clarity, lifetime, progress, UI, and exceptions

void functions – regular event handlers
functions that return typeof Task<T>– represents the ongoing operation – get exceptions off of that task. The Task wraps the <T> – it holds information about what happened when it returned the <T>.

Async CTP code looks like synchronous code except for the await and async keywords.

Previous convention was to write methods with the Async as the end of the method name. For example WriteAsync. The new paradigm is to write the method as WriteTaskAsync.

Everything after the await keyword is the continuation.

Multiple tasks in parallel… Task.WhenAll.  Or alternatively, Task.WhenAny.  NEAT!

Task based Async Patterns – continuation, cancellation, etc. Task.Wait(), AggregateException, ae.InnerExceptions, CancellationToken

Notes:  this is going to be a fun library to work with.  I can hardwly wait to get home and start coding!  That was not sarcasm but true enthusiasm.

Android Development for the .NET Developer

This is about native Android development, not developing using PhoneGap or MonoDevelop.

http://mike-marshall.net outlines the way to install the JDK, SDK, and everything you need to get an Android IDE up and running here.

  • android.app.Activity class
  • Combined with layouts (views), represents a single type of work that can be accomplished in your application
  • Reusable
    • Can be chained within your application to build a workflow
    • Can be published for use by other applications through :Intents” (more later)

Outlines how to create an Android Application Project within Eclipse.

The .net delegate event handler does not apply.

Working with resources can be annoying.

“Form” designer is very similar to XAML designer in visual studio.  Nothing is absolutely positioned unless you tell it to be as such.

What the heck is a ModelState error? Why do I care?

The following post is an email I sent out to my team reviewing why we care about ModelState in an Asp.NET MVC 3 project:

When you bind your views to a Model, you are basically telling MVC to keep track of all of the public properties in the class type that you bound the view to. When you send data to an mvc action via an HTTP request (POST, GET, PUT, DELETE, etc.), mvc uses a ModelBinder to take all the data you sent and shove it into the Model type that you specified as the parameters of the action. If there were any problems binding your data to the Model type specified, you get a model state error. Those errors are stored in the ModelState dictionary which is a key value pair collection where the key’s are all the propterty names of the binding type properties. If you encounter an error, the best practices scenario that MVC likes, is to return the invalid Model back to the View. When you do this, AND you have ClientValidationEnabled AND UnbotrusiveValidationEnabled AND you are using ValidationMessage or ValidationMessageFor, or ValidationSummary helpers on your form properites, wonderful things happen on the View; the error message of the Model State error is shown.

I want to point out another scenario which Rob [Gedelian] has taken advantage of. The preceding scenario involves ModelState binding errors, which only happen before the body of your Action code is executed. But what happens if you encounter an error, or an unexpected (but handled) situation in your action code. You can manually add a model state error to the collection. If you add the ModelState error using a key that is already on your form, you will be displaying back the error NEXT TO the invalid form property back on your view.

        [HttpPost]
        public void CreateDocumentAsync(EmployeeDocumentViewModel viewModel)
        {
            Request.Headers["X-Requested-With"] = "XMLHttpRequest"; // spoof ajax request headers in case of an error - we don't want to render the layout

            if (ModelState.IsValid && !FileUtils.IsValidDocument(viewModel.File.ContentType))
            {
                ModelState.AddModelError("File", "Invalid file type.  Please upload a document.");
            }

            if (ModelState.IsValid)
            {
                new EmployeeCreateDocumentService(AsyncManager, viewModel);
            }
            else
            {
                viewModel.New = true;
                viewModel.Error = true;
                this.AsyncManager.Parameters["viewModel"] = viewModel;
            }
        }

The “File” parameter is the key, which maps back to the view:

        @Html.EditorFor(e => e.File)
…
        <li class='validationSummary'>
            @Html.ValidationSummary()
        </li>

The way Rob chose to display the errors was using an Html.ValidationSummary helper, but he could just as easily used the following:

        @Html.EditorFor(e => e.File)
        @Html.ValidationMessageFor(e => e.File)

As an aside, the reason Rob was able to use Html.EditorFor is because I created an MVC Editor template for the type HttpPostedFileBase:

@model HttpPostedFileBase
 
@{
    var attrs = Html.Attributes();
    attrs = Html.AddMaxLengthAndRequiredToAttributes();
    attrs["class"] = "text-box single-line" + (attrs.ContainsKey("class") ? " " + attrs["class"] : string.Empty);
    attrs["type"] = attrs.ContainsKey("type") ? attrs["type"] : "file";
}
@Html.FileBox("", attrs)

Inline Editing paradigm using a jQuery Inline Editor plugin

As our WebCenter 6 project is nearing release, we’re constantly trying to make our code more DRY.  The basic premise of this post is this: how do we duplicate the showing and hiding of elements needed for inline form field editing without re-inventing the wheel.

What is this inline editing that I’m speaking of?  Well, consider this content:

Customer details pane from WebCenter 6

Customer details pane from WebCenter 6

Rather than creating a whole new page, to edit the Username and other information, why not just pop an edit link next to the Username and allow editing right there on the page?  This eliminates the need for creating a second page, popup, or what have you.  When the edit link is clicked, the display of the username turns into an editor.  An associated cancel link and Save button would also appear.

username edit link

username edit link

editor, save, and cancel link

editor, save, and cancel link

I can accomplish this pretty easily with some nifty jQuery code using hide, show, toggle, etc., but what I really want to do is write this code once and be able to re-use it for other forms that would use the exact same functionality.

Enter the jQuery plugin.

Our wonderfully talented UX developer, Pete Klein suggested we wire this up with data attributes.  Without delving into the details of writing a jQuery plugin, or really optimizing the code, here it is:

/*!
 * jQuery Inline Editor
 * Copyright 2011, Andrew Cohen https://omegaluz.wordpress.com
 */

(function ($) {
    /// <param name="$" type="jQuery">Description</param>

    $.fn.inlineeditor = function (options) {

        var $this = this;

        var settings = $.extend({
            display: this.find('[data-inlineeditor-display]'),
            edit: this.find('[data-inlineeditor-edit]'),
            editlink: this.find('[data-inlineeditor-editlink]'),
            cancellink: this.find('[data-inlineeditor-cancellink]'),
            form: this.find('form[data-val=true]')
        }, options);

        settings = $.extend(settings, this.data('settings')); // apply the settings that are stored in the data['settings'] object
        this.data('settings', settings); // store the current settings in the settings data object
        this.attr('data-inlineeditor', 'true');
        settings.edit.hide();
        settings.cancellink.hide();

        settings.editlink.on('click', function (e) {
            /// <param name="e" type="jQuery.Event">jQuery Event Object</param>
            var target = e.target;
            var $target = $(target);
            var currentTarget = e.currentTarget;
            var $currentTarget = $(currentTarget);

            e.preventDefault();

            settings.display.hide();
            settings.editlink.hide();

            settings.edit.show();
            settings.cancellink.show();
        });
        settings.cancellink.on('click', function (e) {
            /// <param name="e" type="jQuery.Event">jQuery Event Object</param>
            var target = e.target;
            var $target = $(target);
            var currentTarget = e.currentTarget;
            var $currentTarget = $(currentTarget);

            e.preventDefault();

            settings.edit.hide();
            settings.cancellink.hide();

            var $form = $this.find('form');
            if ($form.length > 0) {
                var validator = $form.data('validator');
                if (validator) {
                    validator.resetForm();
                }
            }

            settings.display.show();
            settings.editlink.show();
        });
        /*// is the below code more efficient?
        this.on('click', settings.editlink.selector, function (e) {
        /// <param name="e" type="jQuery.Event">jQuery Event Object</param>
        e.preventDefault();
        settings.display.hide();
        settings.editlink.hide();
        settings.edit.show();
        settings.cancellink.show();
        });
        this.on('click', settings.cancellink.selector, function (e) {
        /// <param name="e" type="jQuery.Event">jQuery Event Object</param>
        e.preventDefault();
        settings.edit.hide();
        settings.cancellink.hide();
        settings.display.show();
        settings.editlink.show();
        });
        */

    };

} (window.jQuery));

Interesting to note, I’m making use of the new jQuery.on function instead of using click, bind, or live.

This code assumes the following:

  • Plugin and all associated functionality are instantiated like so: $(‘#sampleeditor’).inlineeditor();
  • There is an encapsulating element from which all other elements are nested.
  • Within the root there exists ‘[data-inlineeditor-display]’, ‘[data-inlineeditor-editlink]’, ‘[data-inlineeditor-edit]’, ‘[data-inlineeditor-cancellink]’.
  • ‘[data-inlineeditor-display]’ is an element that contains the original text
  • ‘[data-inlineeditor-editlink]’ is a link that when clicked hides the display and shows the editor
  • ‘[data-inlineeditor-edit]’ is a form input that serves to edit the content
  • ‘[data-inlineeditor-cancellink]’ cancels out of the editor, reset’s the form, hides the editor and shows the display again

My mvc 3 razor/html markup looks like so:

        <li><span class='key lfloat'><strong>Username:</strong></span>
            <span class='value lfloat' id="usernameeditor">
                <span data-inlineeditor-display>@Model.User.UserName</span>
                <a data-inlineeditor-editlink href="#">Edit</a>
                <span data-inlineeditor-edit id='usernameEdit'>
                    @{
                        Html.RenderPartial("RenameUserControl", Model.UserRenameViewModel);
                    }
                </span>
                <a data-inlineeditor-cancellink href="#">Cancel</a>
            </span>
            <script type="text/javascript">
                $(function () {
                    $('#usernameeditor').inlineeditor();
                });
            </script>
            <div class='clear'>
            </div>
        </li>

The content of the RenameUserControl:

@model UserRenameViewModel

@using (Ajax.BeginForm("RenameUser",
    "Home",
    null,
    new AjaxOptions
    {
        HttpMethod = "POST",
        UpdateTargetId = "usernameEdit"
    },
    new { id = "renameUserForm" }))
{
        @Html.HiddenFor(model => model.UserID)
        @Html.HiddenFor(model => model.UserName)
        <span class="editor-field">
            @Html.EditorFor(model => model.NewUserName)
            @Html.ValidationMessageFor(model => model.NewUserName)
        </span>

        @Html.ValidationSummary(true)

        <input type="submit" value="Save" />
}

<script type="text/javascript">
    $(function () {
        $.validator.unobtrusive.parse('#renameUserForm');
    });
</script>

Interesting to note, we’re using MVC 3’s built in unobtrusive ajax with data annotations to accomplish the actual form submission.  Again, I didn’t have to write any javascript to wire that up.

I can now re-use this plugin wherever we’re doing inline editing on our site.  I’ll still need to hook into my client side and server side validation when I’m clicking the save button.  I’ll probably wire up an onsuccess event to check whether there are any validation errors and then if not, fire some kind of hide event, rather than the plugin’s cancel code.

** I have updated the source for this. You can find it here.

An exploration of HTML5 Editor Templates with MVC

It occurred to me that we should be using the input type = email in our WebCenter 6 project.  I thought editor templates would be the right way to do this.

If you download the rtm sources for asp.net who will find the MVC 3 Futures source.  This has 2 interesting folders, DisplayTemplates and EditorTemplates inside a folder called DefaultTemplates.  Whenever you use Html.DisplayFor or Html.EditorFor, these templates are used.   You don’t have to download these templates for editor for or default for to work, the code for these is actually packed inside a resource file inside the mvc assembly.  You also might want to check out the source for these.

Default Templates Folder

I wanted to check to see if there was a template for an EmailAddress.  Interestingly, I found a Display template, but not an Editor template.

Display Templates

The display template for email looks like this:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<a href="mailto:<%= Html.AttributeEncode(Model) %>"><%= Html.Encode(ViewData.TemplateInfo.FormattedModelValue) %></a>

You can see that all it does is add a mailto link.

I started first by creating an EditorTemplates folder inside of our root Views/Shared folder.  Then I created a partial view control named EmailAddress.  I names it email address because editor and display templates are used according to the following rules:

http://scottonwriting.net/sowblog/archive/2011/11/22/using-templates-to-display-boolean-values-as-yes-no-options.aspx?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+ScottOnWriting+%28Scott+on+Writing%29

Specifically, the Html.DisplayFor and Html.EditorFor methods consult the following metadata in this order:

  1. The UIHint attribute – specifies the name of the template to use.
  2. The DataType attribute
  3. The data type

The data type is set from the DataAnnotations attribute:

        [DataType(DataType.EmailAddress)]

The partial view will be exactly the same as the editor template for a string except that the type will be changed.

Here is the string control:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>

<%= Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class = "text-box single-line" }) %>

But my email address control is going to do this with razor:

@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class = "text-box single-line", type = "email" }) %>

Here is what validation looks like before I saved this template:

WebCenter 6 Your Profile Validation

Here is what it looks like afterwards.  I have to first change the code from;

                @Html.TextBoxFor(m => m.EmailAddress)

To

                @Html.EditorFor(m => m.EmailAddress)

Now I get this using FireFox.  The RED outline occurs because now I am using an editor template, which puts the correct validation classes:

Shared.css line 3392

.input-validation-error {
    background-color: #FFEEEE;
    border: 1px solid #FF0000;
}

WebCenter 6 Your Profile Validation 2

Interestingly enough, this is still not using HTML 5 validation.  The reason being there is a novalidate attribute on the form:

<form method="post" id="email-form" data-ajax-update="#change-form-email" data-ajax-success="Profile.changeSuccess" data-ajax-mode="replace" data-ajax-method="POST" data-ajax-begin="Modal.Loader.showTop" data-ajax="true" action="/Default/Account/ChangeEmail" style="display: block;" novalidate="novalidate">    <br>
    <div>
        <fieldset>
            <label class="editor-label" for="EmailAddress">New Email Address:</label>
            <div class="editor-field">
                <input type="email" value="" name="EmailAddress" id="EmailAddress" data-val-required="The Email Address field is required." data-val-email="The Email Address field is not a valid e-mail address." data-val="true" class="text-box single-line input-validation-error">
                <span data-valmsg-replace="true" data-valmsg-for="EmailAddress" class="field-validation-error"><span for="EmailAddress" generated="true" class="">The Email Address field is not a valid e-mail address.</span></span>
            </div>

            <div class="form-controls">
                <input type="submit" value="Change Email">
                <input type="button" class="change-cancel" value="Cancel">
            </div>
        </fieldset>
    </div>
</form>

This novalidate attribute is added by jquery.validate line 32:

// Add novalidate tag if HTML5.
this.attr('novalidate', 'novalidate');

According to w3schools:

novalidate novalidate Specifies that the form should not be validated when submitted

If I remove the novalidate attribute using firebug and then try to submit the form:

WebCenter 6 Your Profile Validation 3

The problem that I want you all to think about or research is:

How do we turn jquery validate on or off conditionally based on whether or not html 5 validation will work?  Modernizr gives you test’s for each individual input type, but how do you turn validation ON programatically when html 5 validation has been disabled using the novalidate attribute.  Try it out.

Furthering this, I then realized that there is a Nuget package that adds all of the HTML 5 editor templates.  It actually uses the exact same code that I came up with.  I’m going to add it to our project and see what happens.

https://github.com/srkirkland/Html5MvcTemplates

Html5MvcTemplates

There are also a ton of open source projects out there for Html 5 and mvc 3.  I wouldn’t be surprised if they are going to be built in to Mvc 4.  There is also the HTML 5 mvc 3 helpers which I’m guessing add this kind of code for non editor templates and display templates, using plain old Html.TextBox like syntax:

http://mvchtml5.codeplex.com/

https://github.com/Gutek/MVC-3-Html5EditorFor

Unobtrusive Validation with MVC 3 and Html.BeginForm

Yesterday a colleague of mine and I were trying to find out why client side unobtrusive validation attributes were being generated everywhere EXCEPT one specific page on our upcoming release of WebCenter 6.  Client side validation attributes in MVC 3 are html 5 data-val-*attributes.   They enable you to tie your validation to Data Annotation attributes on your models without having to write a line of javascript code.  This is sweet in my book because the JavaScript is completely decoupled from the actual C# code.

Here is what they look like:

<input type="text"
    name="UserName"
    data-val-required="The Username field is required."
    data-val="true"
    class="text-box single-line" />
  • data-val turns unobtrusive validation on for the input
  • data-val-required enables the required validation rule to kick in with the specified error message you see above

If you want to go into more detail, check out Brad Wilson’s in depth post about Unobtrusive Client Validation in ASP.NET MVC3.

The specific problem we were both encountering was that these attributes were simply not being output on our view when rendered in the browser.

I peeked into the source of System.Web.Mvc.dll and here is what I discovered.

  1. When you render an input using an HtmlHelper like @Html.EditorFor, @Html.TextBox etc., they are rendered with the InputExtensions.InputHelper method.
  2. InputHelper calls HtmlHelper.GetUnobtrusiveValidationAttributes to render the data-val attributes.
  3. GetUnobtrusiveValidationAttributes calls ViewContext.GetFormContextForClientValidation which checks to see if ClientValidation is enabled in the either your web.config or the scope of the view that you are rendering.
  4. GetFormContextForClientValidation will return the FormContext that was instantiated with @Html.BeginForm OR return null.
  5. If it returns null, no attributes are rendered, thus the need for Html.BeginForm.

So to re-cap.  I discovered the problem was that my colleague had NOT created his form using Html.BeginForm.  Instead, he had manually added a <form> tag, which in turn never created the ViewContext.FormContext object.

If you want to see for yourself, go download the latest MVC 3 sources from the ASP.Net site on CodePlex.

In my opinion, this is totally ridiculous.  And I guess the devs over at Microsoft agree because they are removing this requirement in MVC 4.

Here are Brad’s own words:

Important note: jQuery Validate requires your input elements to be inside of a <form> element in order to be validated. In addition, MVC 3 requires that you have called Html.BeginForm() to render this form, so that it can find its book-keeping object to help render the HTML attributes. Starting with MVC 4, we’ve eliminated the need for Html.BeginForm(), but the requirement for the HTML <form> element is still there.