Kendo UI Core and DropDownListFor

Kendo UI Core supports data attribute initialization of its widgets. This initialization approach is largely created for it’s MVVM capabilities, but also can be used for server-side approaches too, which in turn can be used with ASP.NET MVC HTML helpers. The setup may be a little different than you are used to.

Please note: Although Telerik has MVC wrappers already created and ready for you to develop with, these come with the licensed version of the product and are not available through the Kendo UI Core license.

To begin, let’s look at how we’d setup the dropdownlist as an HTML widget without and use of the server.

<select id="reasonID" data-role="dropdownlist" data-option-label="-Select Reason-" data-value="">
  <option selected="selected" value="">-Select Reason-
  <option value="1">Entered in Error
  <option value="2">Removed
</select>

In our example, a select element with a pre-defined list of options is wrapped with the kendo dropdownlist widget. It’s initialized via the data-role attribute, indicating it’s a dropdownlist widget. Next, it defines options that the widget supports. Most of the attributes on the widget that you would configure through the JavaScript API can be defined here, but the syntax differs sometimes (for instance, the optionLabel property you would use in JS initialization is data-option-label in data attribute initialization). If you run into an issue, I was able to find what I needed online so far.

Telerik has some documentation on data attribute initialization here.

The dropdownlist widget can use a textbox as the source, and can also wire data up using JSON via local JavaScript API of via AJAX if you like. I’ve stuck with a select because I’m using the MVC DropDownListFor widget, and to get this widget to render the correct content that I needed, I had to use the following configuration:

@Html.DropDownListFor(
      i => i.ReasonTypeID,      
      Model.ReasonTypes, 
      new
      {
           data_role="dropdownlist", 
           data_option_label="-Select Reason-", 
           data_value=(Model.Receiving.ShrinkTransactionTypeID.HasValue ? Model.Receiving.ShrinkTransactionTypeID.Value.ToString() : ""), 
           style="width:100%;" })

Most of this is standard. The third parameter of DropDownListFor provides HTML attributes to the rendered select option. Here we define the role data attribute used for initialization. The next attribute defines the option label, and the data_value attribute defines the selected value, which is interesting. We already define what’s selected via the lambda expression pointing to our model. However, that’s used to render the selected attribute. What I found is that to cover all selection scenarios (including the default “Select Something” item) is to add the value attribute too, which the widget uses to perform the selection. The code above manually checks for null and converts to an empty string if no value present.

In case you didn’t notice, note how the HTML attribute use data_role, particularly the underscore. The convention that MVC uses is underscore (supported by the language), which is converted to a dash during the rendering process.

Dynamic Script Registering Component in ASP.NET MVC

One of the performance enhancements recommended in tools like YSlow and others is to put your JavaScript script files at the bottom of the page. The great difficulty in a web forms or MVC web application with doing that is scripts at the bottom of the page are typically added in the master page. Any pages or views can make use of a special section just for scripts, but partial views or user controls can’t take advantage of that.

I’m about to illustrate a solution that will do just that. It’s setup for MVC, but could be easily adapted for web forms by making the helpers as controls. You have to understand that MVC is a top down structure. So as views or partials render, they render their contents in place. The common approach is to have a section for scripts:

site.master:


  // master page common scripts


@* for any custom scripts in the view *@
@RenderSection("scripts", false)

The view can add a @section scripts { } to take advantage of this, but the partial view cannot. Additionally, everything is rendered in top down format; if a partial view at the top of your page has a script like:


$(function() { alert("In the partial view"); });

The problem with this script is that the final rendered view (when scripts are defined at the bottom) will look like:


$(function() { alert("In the partial view"); });


.
.
.
view content
. . // master page common scripts // view scripts

Since it’s top down, it’s also dependent on order, so scripts defined have no dependency (lacking a dependency feature like angular or script JS).

The following solution was meant to give more control over placement of defined scripts. Scripts are defined in a wrapper, and queued up for later rendering. The solution I’m providing is simple, but easily enhanced to add dependencies in scripts, custom ordering, and more features.

To give an idea of what we need to do, the system will achieve something like the following:

view.cshtml:

@Html.AddScript("ViewInit", () => @$(function() { .. }));

partial view:

@Helper Script()
{
   
     ..
   
}

@Html.AddScript("PartialInit", (m) => Script());

master:

@Html.PlaceScripts()

The idea is to add scripts via a method, which queues them up to be rendered, and writes them out at the point the PlaceScripts method is called. Note that for partial views, I’m using a little trick I noted earlier, whereby using a helper is the only way to circumvent exceptions that occur when using the action-based approach.

AddScript essentially adds the definitions to the HttpContext.Items collection, a common trick for storing singleton-like data elements that are available across the application. Since HttpContext.Items is available to add and then render scripts, it’s a great place to share content. The AddScript method shoves in data:

public void AddScript(HtmlHelper html, string key, Action fn)
{
    var http = html.ViewContext.HttpContext;
	var list = http.Items["_Scripts"] as Dictionary;
	
	if (list == null)
		list = new Dictionary();
	
	list[key] = fn;
	
	http.Items["_Scripts"] = list;
}

This method checks to see if we have a dictionary in the items collection; if not, it creates it, pushes in our item, and updates the collection. Similar, our other method, which takes a helper result, uses another overload to store the string result for easy rendering:

public void AddScript(this HtmlHelper html, string key, HelperResult fn)
{
	this.AddScript(html, key, fn(html.ViewData.Model).ToHtmlString());
}

public void AddScript(this HtmlHelper html, string key, string script)
{
    var http = html.ViewContext.HttpContext;
	var list = http.Items["_Scripts"] as Dictionary;
	
	if (list == null)
		list = new Dictionary();
	
	list[key] = script;
	
	http.Items["_Scripts"] = list;
}

We could easily add dependencies and ordering requirements to this solution if we needed; for now, let’s finish this out by showing how to grab the contents and render them:

public void PlaceScripts(this HtmlHelper html)
{
var http = html.ViewContext.HttpContext;
var list = http.Items[“_Scripts”] as Dictionary;

if (list == null)
return;

using writer = new HtmlTextWriter(html.ViewContext.Writer)
{
foreach (var entry in list)
{
if (typeof(entry.Value) is string) {
writer.WriteLine(entry.Value);
}
else {
//This is an action; the action will be
//rendered in the current output stream, and
//do not need to be directly written
entry.Value(html.ViewData.Model);
}
}
}

}

This would need greatly enhanced for dependencies and sorting; right now, we take the list in order and render it out. For HTML results or just plain string definitions, it gets rendered to the current response stream. Actions get processed the same way, but MVC handles that internally, rather than your code.

And voila, we are done; now we can define scripts in the view and partial views and expect them to be rendered where we want them placed, and have a component that can be easily enhanced to do much more.

Rendering Markup Anywhere in MVC

I had a hard time coming up with the title, because as you know, markup is pretty dynamic in MVC. However, I came across an interesting limitation when it came to rendering markup. I’m not talking about rendering partial view content using Html.Partial, or using a helper method. I’m actually talking about rendering markup segments, which I’ll demonstrate with a VB.NET example (sorry, I’ve been stuck in the VB world for some time, it’s become more natural than C#):

@* SomeView.vbhtml *@
@Code
Html.ScriptDefine(
   @
      alert("ME");
   )
End Code

Html.ScriptDefine is not something Microsoft created, but a custom extension I created. This was a helper method to register script segments. It is not a method defined globally or in a view, but a helper that’s code, which can be easily reused across projects, which is why I tried to utilize this technique. Somewhere in the master page, a process read all of these scripts and rendered them in the master page. This was excellent; I could define these script blocks anywhere in the view, and they would all get rendered in one place.

My helper looked like the following:

Public Sub ScriptDefine(Of TModel)(html As HtmlHelper, key as String, fn as Action(Of TModel))
    Dim script = fn(html.ViewData.Model)
    'Store reference to model and script somewhere, 
    'which the master page retrieves all of the scripts and renders
End Sub

It worked, except in one scenario: Partial Views, which is a key reason why I wanted it. See, I often found myself using scripts in a partial view. I tried using an optimization technique where scripts run at the end of the page; the only problem was a partial view that used a script had it’s <script /&rt; block defined wherever the partial was, which was usually above the end of the view. The issue with partial views has to do with the rendering process, and although I wasn’t quite sure how to figure out why, I found a better solution anyway: HelperResult.

By defining the script in a helper (a small caveat) and then storing the helper result, this solved the problem much more easily. I was able to define an extension like the following:

Public Sub ScriptDefineHelper(Of TModel)(html As HtmlHelper, key As String, fn As Func(Of TModel, HelperResult))
   Dim helperResult = fn(html.ViewData.Model) 'Returns the content as IHtmlString
   Dim list = CType(html.ViewContext.HttpContext.Items("_Scripts_"), List(Of String))

   if (list Is Nothing) Then
      list = new List(Of String)
   End If

   list.Add(helperResult.ToHtmlString()) 'Store the scripts as a string, which is easy to render later

   html.ViewContext.HttpContext.Items("_Scripts_") = list
End Sub

Now wherever we use our helper, we can use it like:

@Code
  'Use in view or partial view
  Html.ScriptDefineHelper(Function(i) Scripts())
End Code

@Helper Scripts()
   
      alert("Hello");
   
End Helper

And we can render out all the scripts with the following code (we can also use a helper method for this):

Dim items = CType(html.ViewContext.HttpContext.Items("_Scripts_"), List(Of String))
For Each item in items
  @Html.Raw(item)
Next

The real question is why do all of this, when all of the scripts could be in the page? Well, there are good reasons for doing this. First and foremost, keeping the scripts used in a partial view are best defined in the partial view. Out of sight is out of mind, especially for JavaScript. By using this technique, scripts can be defined, and rendered at the designed area, more effectively. That is the primary benefit; outside of that, there aren’t a lot of benefits.

Adding ASP.NET MVC Anti-Forgery Tokens To All Post Requests Easily

One of the newer attacks against web applications is the cross-site request forgery attack. It’s an attack against modern applications that store a cookie to represent the currently logged in user. The problem has been explained in other web sites. I’d highly recommend checking out Phil Haack’s blog post on the subject.

One of the techniques to prevent this attack is to add an anti-forgery token using the @Html.AntiForgeryToken extension method. On the controller side, the action method defines the [ValidateAntiForgeryToken] attribute. Behind the scenes, the hidden input field for the anti-forgery token is validated by the MVC framework to ensure it’s correct. This has also been explained well; see Steve Sanderson’s post on the subject. While there is discussion as to whether this approach is needed just for the logging in an anonymous posts, or all posts in general, as been up for debate. But the point of CSRF is to attack authenticated users.

I’m not real fond of repetitive coding, especially when the framework is flexible enough to avoid it. Below is my solution to to create a flexible solution to validate all post operations. The first task is to create an attribute for validating the token. After using .NET Reflector by Red Gate to examine the existing ValidateAntiForgeryTokenAttribute class, the token is simply an authorization attribute that validates the request using a helper utility to validate it. See the example below.

public class GlobalAntiForgeryTokenAttribute
  : FilterAttribute, IAuthorizationFilter
{
  public sub OnAuthorization(filterContext As AuthorizationContext)
  {
	if (filterContext.HttpContext.Request.HttpMethod.ToUpper() == "POST")
	{
	  AntiForgery.Validate();
    }	
  }
}

Make sure to add this to the GlobalFilters.Filters collection:

GlobalFilters.Filters.add(new GlobalAntiForgeryTokenAttribute);

On authorization of the request, if the operation is a POST request, we call the Validate() method on the AntiForgery helper to actually perform the validation. All of our post operations are now checked for forgery; however, this will fail because we haven’t added our token globally. To do that, we have to create a custom form extension method like the following:

public static void FormExtensions
{
   public static MvcForm BeginDataForm(this HtmlHelper html, string action, string controller, ...)
   {
     var form = html.BeginForm(action, controller, ...);
	 //At this point, the form markup is rendered in BeginForm
	 // we can render the token
	
	 //With every form, we render a token, since this
	 //assumes all forms are posts
	 html.ViewContext.Writer.Write(html.AntiForgeryToken().ToHtmlString());
	
	return form;
   }
}

If we use our custom helper for all of our forms, then all of our custom forms will have rendered an anti-forgery token. Therefore we don’t have to worry about creating it ourselves, saving time and reducing code.

VB.NET Inline Functions in ASP.NET MVC and Razor

I’ve seen various debate about whether inline markup expressions work in VB, and I want to tell you that they do. Here is how I did it. Define a method like the following, which will be an HTML helper extension. Please see my introductory post on how to do that:


<Extension>
Public Sub Inline(Of TModel)(html As HtmlHelper(Of TModel), template As Action(OF TModel))

In a view, you can define an implementation of that method like the following:


@Code

Html.Inline(Sub(m)
@<span>This is my template</span>
End Sub)

End Code

This approach has worked for me, as long as any helper using the template is inside an @Code block, and the Sub(m) declaration is a multi-line sub, not an inline statement.

Custom ASP.NET MVC Helper Extensions

As you probably are aware of, ASP.NET MVC was a divergence from the approach developers took to developing ASP.NET web forms applications. For web forms developers, any level of customizations occurred by creating custom ASP.NET server controls, inheriting from a particular base class and adding some functionality, something like:

public class SuperLabel : Label
{
   // Enhanced functionality
}

There are many benefits to doing this; you can initialize the control’s properties for your web application, or encapsulate repeatable code into a common class that’s reused throughout the application. For instance, if we know that we will always render our form labels in a specific manner, I could create a custom control to do this following:

public class FormLabel : WebControl
{

   protected override void Render(HtmlTextWriter writer)
    {
         writer.Write("<div>" + this.Text + "</div>");
    }

}

And that way, every label is wrapped in a div with a FormLabel class. This is a simple example of standarizing your control’s output and thus your client’s markup, but you get the idea. This is also possible in ASP.NET MVC, with the help of your own helper methods.

Note that there are two kinds of helper methods in MVC: ones who return an MvcHtmlString object and render the text inline, and ones that render inside the method and are defined as @Html.DoSomething(); (with a semi-colon at the end; in VB this method can be called in a @Code block). I’m going to talk about helpers that return an MvcHtmlString in this blog post. As a simple example of a helper we may want to standardize on, we can, for instance, wrap a DIV with a special class around the Html.EditorFor helper as in the following example:

public static class HtmlHelperExtensions
{

  public static MvcHtmlString CustomEditorFor(this HtmlHelper html, Expression<Func> expr)
  {
     return new MvcHtmlString("<div>" + html.EditorFor(expr) + "</div>");
  }

}

As you can see, we have a custom editor with a wrapper DIV around it now, which we can put in our UI by doing:

@Html.CustomEditorFor(i => i.ModelProperty)

The TModel and TProp generic references above are inferred from the current view’s model, and the property expressed in the lambda expression. If you look in other MVC helpers, they are all defined with these two generic references. The HtmlHelper class has a lot of useful features; first it has access to all the extension methods as you would use them in the UI (most defined in the System.Web.Mvc.Html namespace, but there are additional namespaces too). It also has a reference to the ViewContext and to the current model for the given view, via the HtmlHelper.ViewData.Model property (remember HtmlHelper is specific to the model, therefore it maintains an explicit, strongly-typed reference to said model).

I’ve only scratched the surface, but you can see a lot of options are available to you. For instance, if you use Twitter bootstrap, maybe you want your editor helper to look like:

 public static MvcHtmlString CustomEditorFor(this HtmlHelper html, Expression<Func> expr)
  {

     return new MvcHtmlString(
  @"<div class=\"control-group\">" + 
    html.LabelFor(
        expr, 
        new { @class = "col-md-2 control-label" }
     ).ToHtmlString() +
   @"</div>
     <div class=\"col-md-10\">" + 
    html.EditorFor(expr) + 
    "</div>");

  }

And thus, this saves you from writing a lot of HTML. In the future, I may write on some of the extensions I’ve used for twitter bootstrap to save time. I hope this is a good overview of how you can customize HTML helpers in ASP.NET MVC, which I am using this technique in a current ASP.NET MVC 5 application.

Using JQuery FullCalendar with ASP.NET MVC and Entity Framework

I had a need to use a calendar component in my application. Calendars are hard to come by, that also act as a scheduling component. In comes JQuery FullCalendar, a plugin that renders a calendar with event components.

To set this up

1. Create an Entity Framework model with all of the AdventureWorks entities.  Choose whatever template you like. Leave the context name as the default “AdventureWorksEntities”.

2. Create a new MVC project. Add a new controller named OrderHistoryController. The OrderHistoryController that I used is defined as the following:

public class OrderHistoryController : Controller
{
//
// GET: /OrderHistory/
public ActionResult Index()
{
return View();
}

[HttpPost]
public ActionResult List(long start, long end)
{
var epoch = new DateTime(1970, 1, 1);
var startDate = epoch.AddMilliseconds(start);
var endDate = epoch.AddMilliseconds(end);

var ctx = new AdventureWorksEntities();
var data = ctx.SalesOrderHeaders
.Where(i => startDate <= i.OrderDate && i.OrderDate <= endDate)
.GroupBy(i => i.OrderDate)
.Select(i => new { OrderDate = i.Key, Sales = i.FirstOrDefault()}).Take(20).ToList();

return Json(data.Select(i => new
{
title = (i.Sales.Customer != null) ? i.Sales.Customer.AccountNumber : “Untitled”,
start = i.OrderDate.ToShortDateString(),
allDay = true
}));
}

}

The Index action serves up the view.  Once the view is loaded, an AJAX request is made back to the server, looking for any orders.  Using LINQ, we load up some of those records.  I used a GroupBy statement so that I could get one record back per date for a given month, as a way to test with a single record per day.

JSON is the preferred mechanism to return to the client.  We’ll need to massage the data a little bit in order to work with the full calendar.   For instance, we’ll have to convert the date appropriately.  For simplicity, I used ToShortDateString to get the date and parse it in JavaScript.  However, it would have been more appropriate to convert the date to Epoch time (time since 1/1/197o).

3.  Download JQuery FullCalendar from the following URL: http://arshaw.com/fullcalendar/download/.  Copy the JS and CSS files to your project, in the Content and Scripts folder (or whatever folder structure you are using).  The files includes are:

  • fullcalendar.css – the core CSS file
  • fullcalendar.print.css – the CSS stylesheet for printing a calendar
  • fullcalendar.js – the core JS file
  • fullcalendar.min.js – the minified JS file
  • gcal.js – Google calendar integration

4.  Add scripts to your page

Rather than adding all the scripts to every page, I added the scripts to the OrderHistory view.  To do this, I started by creating a bundle.  Open up Bundle.config and add the following:

bundles.Add(new ScriptBundle(“~/bundles/calendar”).Include(

#if DEBUG

“~/Scripts/fullcalendar.js”

#else

“~/Scripts/fullcalendar.min.js”

#endif

));bundles.Add(new StyleBundle(“~/Content/calendar”).Include(

“~/Content/fullcalendar.css”,

“~/Content/fullcalendar.print.css”

));

We use these bundles within the view. To setup the calendar, all that we need to do is add a DIV to a page with an ID, like <div id=”container”></div>. The FullCalendar plugin simply attaches to

$(“#calendar”).fullCalendar({
    header: {
        left: ‘prev,next today’,
        center: ‘title’,
        right: ‘month,agendaWeek,agendaDay’
    },
    editable: true,
    eventClick: function(i, evt, view) {
               
    },
    events: function (start, end, callback) {
        $.ajax({
            type: “post”,
            url: ‘@Url.Action(“List”, “OrderHistory”)?start=’ + start.getTime().toString() + “&end=” + end.getTime().toString(),
            success: function (d) {
                var list = [];
                for (var i = 0, len = d.length; i < len; i++) {
                    var item = d[i];
                    item.start = new Date(item.start);

                    list.push(item);
                }

                callback(list);
            },
            error: function (e) {
                debugger;
            }
        });
    }

});

The plugin supports a variety of members defined in the documentation that can be specified at initialization time. The key is the events property, which defines the source of the events. The source can be a static list, a pointer to a page or web service, or even a function callback. The latter option gives you the most flexibility, and I’ve demonstrated it’s usage in this example. The callback gets a start and end parameter. These parameters are dates, converted to epoch time (in milliseconds) as they are sent to the server. JQuery is used to make the call to the server, and as the results come back, the process does some massaging first. For instance, a date is coming back to the client in string form, and converts the date back to a date form.

Once our final list is complete, and to load them into the calendar, they are passed to the callback. The plugin handles all of the loading of data into the calendar. Remember from the MVC controller, it returned a title, start (date), and an allDay indicator. Using this data is what the FullCalendar plugin uses as the data source. More parameters

Knockout with MVC Sample

I have an application where there exists the ability to request invitation to a group, similar to the process of joining a private linked in group.  One of my MVC views displays all such requests, and allows the user to process them.  The way this page works is the following: the view loads with no data.  The view begins to build the view model and bind it without any request data.  A JQuery AJAX request fetches the request data from the server, and loads the requests after-the-fact, once the AJAX request completes.  The process used an action method to stream JSON to the client, and returns the following content:

public ActionResult Invitations(string username)

{
.
.
//load data from server

return Json(new
{
Invitations = from i in requests
select new
{
i.Key,
i.GroupName,
i.UserName,
i.Note
}
});
}

On the client, we have a view defined as the following.  there is a lot of markup, but the process isn’t overly complex.  At the top, we have the template user interface defined.  Later on, we construct the view model, load it with empty data.  An AJAX request retrieves JSON data and loads the invitations into the view.  Each invitation displays the core information, along with a button that permits and acceptance or rejection of the invitation.

<div class=“P”>

<div databind=“if:hasInvitations”>
<div id=“InvitationsList” databind=“template: { name: ‘InvitationsTemplate’, data: invitationsList }”></div>
</div>

<div databind=“if:hasNoInvitations”>
Loading
</div>

<div databind=“if:emptyInvitations”>
No invitations have been submitted yet.
</div>

</div><script type=“text/html” id=“InvitationsTemplate”>

<section databind=“foreach:Invitations”>
<h3 databind=“html:UserName”></h3>

<div class=“P”>
For Group <span databind=“text:GroupName” />
</div>

<div class=“P”>
The user attached the following note:
<div databind=“html:Note”></div>
</div>

<div class=“P”>

<div>
Please approve or reject the user using the buttons below.
</div>

<div>
<form class=“InlineForm” action=‘@Url.Action(“Approve”, “Groups”)’ method=“post”>
<input type=“submit” value=“Approve” />
</form>

<form class=“InlineForm” action=‘@Url.Action(“Reject”, “Groups”)’ method=“post”>
<input type=“submit” value=“Reject” />
</form>
</div>

</div>

</section>

</script>

<script type=“text/javascript”>

function viewModel() {
var self = this;

self.invitationsList = ko.observable(null);

self.emptyInvitations = ko.computed(function () {
var i = self.invitationsList();

   return (i != null && i.Invitations.length == 0);

});

self.hasInvitations = ko.computed(function () {
var i = self.invitationsList();

    return (i != null && i.Invitations.length > 0);

});

self.hasNoInvitations = ko.computed(function () {
    return self.invitationsList() == null;
});

}

var model = new viewModel();
ko.applyBindings(model);

$.ajax({

type: “post”,
url: ‘@Url.Action(“Invitations”, “Groups”)’,
data: { UserName: ‘@ViewBag.UserName’ },
context: model,
success: function (d) {
this.invitationsList(d);
}

});

</script>

Notice the computed properties; at first, the list of invitations is null, meaning we haven’t gotten any invitations at all.  If I would have bound a null observable to the view, Knockout JS throws an exception in relation to this.  We can’t bind a null observable that isn’t prevented first with some if logic.  If we do have data, one of two view appears.  Either the view renders the invitations posted, or if an empty list, we see an empty message to inform the user the system has no invitations.

This is a piece of functionality I actually have in operation, and I hope this may be of benefit to you to see how an entire view may be implemented in Knockout.

MVC 4 Mobile Display Modes

A lot of talk has been happening over the new MVC 4 display modes feature.  If you don’t know what it is, the display modes feature controls the display to the current user, switching which view is being displayed by the user by running a specific condition.  What this means is I can setup a condition to target the iPad, and then display an iPad-specific view to the user, instead of the standard view.  The convention for a display mode is: viewname.<placeholder>.cshtml (assuming we’re using Razor), where placeholder is an alias passed to the constructor of the display mode.  Below is a sample display mode class that I adapted and modified from a sample on the web and is available here:

  1. public class MobileDisplayMode : DefaultDisplayMode
  2. {
  3.     private static string[]_useragenStringPartialIdentifiers = new string[]
  4.     {
  5.         “Android”,
  6.         “Mobile”,
  7.         “Opera Mobi”,
  8.         “iPhone”,
  9.         .,
  10.         .
  11.     };
  12.     public MobileDisplayMode()
  13.         : base(“Mobile”)
  14.     {
  15.         ContextCondition = (context => context.Request.IsDetectedMobileBrowser() ||
  16.             IsMobile(context.GetOverriddenUserAgent()));
  17.     }
  18.     public static bool IsMobile(string useragentString)
  19.     {
  20.         return _useragenStringPartialIdentifiers.Cast<string>()
  21.                     .Any(val => useragentString.IndexOf(val, StringComparison.InvariantCultureIgnoreCase) >= 0);
  22.     }
  23. }

Every time a request is made to the server, the display mode condition is checked to determine if the scenario is appropriate for an alternative display.  If the user agent matches a mobile device, MVC serves up the view with .Mobile.cshtml or .Mobile.aspx in it’s name, if one can be found.  If no view exists with that name, then the default is returned.

I did run into one problem; MVC was ignoring my requests.  In inspection of the display modes collection, I noticed the ASP.NET MVC framework already had a mobile display mode implementation present.  I had to remove that one and add a new one, as I did below in the Global.asax page.  Interestingly enough, by researching this I did find that it uses the DefaultDisplayMode class to provide the mobile view, meaning the same class is used by ASP.NET MVC to detect standard and mobile requests.

  1. DisplayModeProvider.Instance.Modes.RemoveAt(0);
  2. DisplayModeProvider.Instance.Modes.Insert(0, new Mvc.MobileDisplayMode());

Note that display modes can be for anything; we could have a display mode that matches the iPhone user agent, and displays an iPhone-specific view.  Or a display mode could be not device-specific, but based on other information about the current request.  The possibilities are limitless.

One might ask why customize the display mode at all?  I personally ran into an issue using the opera mobile emulator; the emulator was not supported in the default implementation.  Adding a condition to check for the “Opera Mobi” user agent resolved that problem.