Friday, January 10, 2014

Extending an MVVM KendoUI widget to support custom event bindings

In my previous post, I put together a simple Kendo widget that is MVVM compatible within the KendoUI framework. In this post, I will add custom event bindings to the widget to allow the MVVM bindings to establish event bindings to dependent methods within your viewmodel. This will allow the widget to trigger custom events when the user clicks on the icon in our custom text box. Starting with the previous widget, we now need some DOM elements for the user to interact with. I had found a posting that explained a way to make simple KendoUI widget that was not MVVM aware that added a magnifying glass icon to a standard textbox. This seemed good for this example. It uses and existing Kendo style for the magnifying glass.

        _create: function () {
            // cache a reference to this
            var that = this;

            // setup the icon
            var template = kendo.template(that._templates.icon);
            that.icon = $(template(that.options));

            // setup the textbox
            template = kendo.template(that._templates.textbox);
            that.textbox = $(template(that.options));
            
            // append all elements to the DOM
            that.element.attr("name", that.options.name);
            that.element.addClass("k-input");
            that.element.css("width", "100%");
            that.element.wrap(that.textbox);
            
            that.element.after(that.icon);
        },
        //HTML for the templates that comprise the widget
        _templates: {
            textbox: "<span style='width: #: width #px;' class='k-widget k-datepicker k-header tb'><span class='k-picker-wrap k-state-default'></span></span>",
            icon: "<span unselectable='on' class='k-select' role='button'><span unselectable='on' class='k-icon #: iconclass #'>select</span></span>"        },
The _create method adds additional dom elements as well as some kendo styles to create the effect. Width is used from the options collection and the icon class also comes from options, so we can override it if we choose to. Now that we have something to click on ,we need to add a line to _create to wire up a click event on the icon.
  that.icon.on("click", $.proxy(that._buttonclick, that));
A simple jquery click event is added via a proxy. From the previous example, we use a proxy to ensure that the scope of the event fired contains the widget when fired. We pass the widget in as scope for the proxy. The handler is tied to a new internal function in our widget, _buttonclick.
        _buttonclick: function (element) {
            var that = this;
            that.trigger("buttonclick", { element: element });
            return that;
        },
The handler for the widgets icon click event fires the custom event BUTTONCLICK to alert any listeners that the event has occured. The widget will be the scope and the element will be the icon DOM element. Now we have to declare the event in our events collection so the MVVM framework knows that the binding is available.
events: ["change", "buttonclick"],
By exporting the event via the events collection, the MVVM framework is aware that our widget can fire an event called 'buttonclick'. We can consume the event in MVVM bindings with the same binding syntax as other kendo widgets.
<input data-role="buttontextbox" data-bind="value: simpleValue, events: { buttonclick: onSomeButtonClick }" />

The buttonclick event binding will call into the dependent method specified as onSomeButtonClick. Our widget can now export custom events from events that are internal to the widget itself.
A functional fiddle with all the code is at:

http://jsfiddle.net/cn172/s7RF3/

Create a simple KendoUI MVVM widget

KendoUI is a nice framework for building HTML based applications.  One aspect of KendoUI that is not clearly documented is the creation of custom widgets.

There is an article at the kendoui web site that covers creation of a widget that uses a datasource to manage an internal list and in that article it shows how to connect the widget to their MVVM framework.

http://docs.kendoui.com/howto/create-custom-kendo-widget

However, this article and it's related blog posts are too complicated, working with widgets that are bound to lists of items.  A simple, straightforward example that simply binds to a single value in our view model (like a numeric textbox for instance) is not provided.

To begin, let's layout the requirements for this new, fictional widget.  It must have a text box that is MVVM bound.  We should be able to use a markup such as:
<input data-role="simplewidget" data-bind="value: simpleValue" />
To accomplish this, we need to create a kendo widget by extending the kendo widget framework. The first section of the article linked above details this well. I'll repeat the full boilerplate code here.
(function($) {
   ui = kendo.ui,
   Widget = ui.Widget

   var MyWidget = Widget.extend({

   init: function(element, options) {

   // base call to widget initialization
   Widget.fn.init.call(this, element, options);

   },

   options: {    
        // the name is what it will appear as off 
        // the kendo namespace(i.e. kendo.ui.MyWidget). 
        // The jQuery plugin would be jQuery.fn.kendoMyWidget.
        name: "MyWidget",
       // other options go here
       ....
   }
});
ui.plugin(MyWidget);

})(jQuery);
So far, this is quite straightforward. Using Widget.extend, we extend the Widget function and add init and options. The kendo framework will call init and examine the collection of options. Now we want to make the widget MVVM aware with a property from the viewmodel update the UI with the value provided.  In order for MVVM to support a binding of 'value' we have to implement a value method.
  //MVVM framework calls 'value' when the viewmodel 'value' binding changes
  value: function(value) {
      var that = this;

      if (value === undefined) {
          return that._value;
      }
      that._update(value);
      that._old = that._value;
  },
  //Update the internals of 'value'
  _update: function (value) {
      var that = this;
      that._value = value;
      that.element.val(value);
  }
This method will be called by MVVM with the current viewmodel value supplied.  It will also be called anytime the bound propery changes. We'll need to keep track of that, so we keep it in a local variable called _value, as well as creating a copy of it in a local variable called _old. We will want to know the original value for change tracking purposes later. If we simply add the above two functions to our widget boiler plate, we will see MVVM calling the value function anytime the viewmodel value we bound to changes. We also set the element value with a call to element.val(value) to get the UI displaying the viewmodel value.

Our widget is updated with the data from the view model with this one simple function.  Next we will want to support notifying the MVVM framework when our user updates the value using the UI.  First we need to alert the MVVM framework that we are going to be firing an event that can be bound to. This is done by declaring an events property.
events: ["change"]
This line tells MVVM that a CHANGE event is available from this widget. Now that MVVM is aware that we might trigger an event called 'change' we need to detect the UI updates in our input box and when the user changes the value of our input we need to notify MVVM.  To detect changes by the user, let's bind a blur event to our  textbox.

   //Create a blur event handler.
   element = that.element.on(".kendoButtonTextBox", $.proxy(that._blur, that));
A key component here is the user of $.proxy to ensure that the scope of the call to "that._blur" is set to the widget's scope. Without resetting the scope the event handler function will not have the widget's scope and won't be able to access any of the properties or methods on the widget.

Now an implementation for the _blur function must be provided.
  //blur event handler - primary UI change detection entry point
  _blur: function () {           
      var that = this;            
      that._change(that.element.val());
  },
  //Update the internals of 'value'       
  _change: function (value) {
      var that = this;
      //Determine if the value is different than it was before
      if (that._old != value) {
          //It is different, update the value
          that._update(value);
          //Capture the new value for future change detection
          that._old = value;
          // trigger the external change
          that.trigger("change");
      }
  }
In this code, the _blur event handler function is calling the _change event trigger function. This function uses the _update function to update the internal value, and triggers the change event from the provided scope. The MVVM framework is listening for this change and has subscribed our viewmodel to listen for the change event.

In this simple example, we created a textbox that binds to a single viewmodel property.  In my next example, I'll expand on this widget to allow the widget to create and trigger custom events that can also be MVVM bound.  The full source code for a working, simple MVVM widget is at:

http://jsfiddle.net/cn172/XE2Qg/

Wednesday, January 9, 2013

Setting Database Permissions with Server 2012 for IIS Apps

I found a great post detailing the methods to setup permissions to databases using the latest version of IIS, check it out: http://rarcher.azurewebsites.net/Post/PostContent/20

Wednesday, January 2, 2013

MVC.Net 4 WebAPI Server Side Model Validation

My latest work is implementing a site using MVC.Net and the WebAPI interface.  I wanted to use the data annotations in my UI models to support server side validation of incoming data passed in via JSON or XML with POST requests to my WebAPI methods.  I found a lot of confusion when I was researching the proper method of implementing a custom filter for WebAPI to implement this type of validation.

To clear things up, it is important to realize that data annotations in your model are validated using unique namespaces for MVC controllers vs. Webapi controllers.  The syntax and naming conventions within these namespaces are very similar.  MVC controllers utilize use System.Web.MVC while WebAPI uses System.Web.Http.

To enable server side validation for MVC.Net WebAPI, you will need the following code:

   1:  using System.Collections.Generic;
   2:  using System.Net;
   3:  using System.Web.Http.Filters;
   4:  using System.Web.Http.Controllers;
   5:  using Newtonsoft.Json;
   6:  using System.Net.Http;
   7:   
   8:  namespace SampleMVC
   9:  {
  10:      public class ValidationActionFilter : ActionFilterAttribute
  11:      {
  12:   
  13:          /// <summary>
  14:          /// System.Web.Http.Filters implementation for model validation (WebAPI)
  15:          /// </summary>
  16:          /// <param name="actionContext"></param>
  17:          public override void OnActionExecuting(HttpActionContext actionContext)
  18:          {
  19:              base.OnActionExecuting(actionContext);
  20:   
  21:              var modelState = actionContext.ModelState;
  22:              if (!modelState.IsValid)
  23:              {
  24:                  List<string> errors = new List<string>();
  25:                  foreach (var value in modelState)
  26:                  {
  27:                      errors.Add(value.Value.Errors[0].ErrorMessage);
  28:                  }
  29:                  var response = new System.Net.Http.HttpResponseMessage(HttpStatusCode.BadRequest);
  30:                  response.Content = new StringContent(JsonConvert.SerializeObject(errors));
  31:   
  32:                  actionContext.Response = response;
  33:              }
  34:          }
  35:      }
  36:  }

This code executes for each action, reads the model state from the action context and prepares a list of validation errors to return in JSON format to the client.  An http status of BadRequest is returned along with the body containing the error details in JSON.  While this may not be the particular action you wish to take when an error is found and it may not be very RESTful, it shows an example of what could be done and how to read through the validation errors list.

To make this code execute you'll need to add these lines to your FilterConfig.cs file, don't forget to add a namespace reference for System.Web.Http.Filters:

   1:  public static void RegisterHttpFilters(HttpFilterCollection filters)
   2:  {
   3:       filters.Add(new ValidationActionFilter());
   4:  }

Be sure to add a registration in your Global.asax.cs file, the MVC controller filters are registered there, but not the webapi filters.

FilterConfig.RegisterHttpFilters(GlobalConfiguration.Configuration.Filters);

If you wish to add validation to a standard MVC.Net controller, the code is as follows.

   1:  using System.Web;
   2:  using System.Web.Mvc;
   3:   
   4:  namespace SampleMVC
   5:  {
   6:      public class ValidationActionFilterMvc : ActionFilterAttribute
   7:      {
   8:          /* MVC Controller implementation of model validation
   9:           * Uses System.Web.Mvc
  10:           * Lists of ActionResult Implementations found at:
  11:           * http://brendan.enrick.com/post/types-of-aspnet-mvc-3-action-results.aspx
  12:           * */
  13:          public override void OnActionExecuting(ActionExecutingContext filterContext)
  14:          {
  15:              base.OnActionExecuting(filterContext);
  16:              var modelState = filterContext.Controller.ViewData.ModelState;
  17:              if (!modelState.IsValid)
  18:              {
  19:                  var result = new HttpStatusCodeResult(HttpStatusCode.BadRequest, "ModelError");
  20:                  filterContext.Result = result;
  21:              }
  22:          }
  23:      }
  24:  }

The proper entry in your FilterConfig.cs for this validation filter is, of course this requires a namespace reference to System.Web.MVC:

   1:  public static void RegisterGlobalFilters(GlobalFilterCollection filters)
   2:  {
   3:      filters.Add(new HandleErrorAttribute());
   4:  }

The MVC validation code executes for each action the same as the webapi controller, but in this case MVC.Net provides a built in mechanism for returning http status codes.  I found a post linked to in the code that has a list of the implementations provided by Microsoft for the ActionResult class that allows you to return these status codes to the controller.  Of course you could iterate the validation errors just the same as was done in the WebAPI example if you chose to. Note the different usings here that are referencing the proper namespaces for this implementation versus the usings in the WebAPI sample.  The similar names in different namespaces are the source of confusion around these implementations.

Friday, December 7, 2012

How to get to the start button in Windows Server 2012

How do you access the 'start button' in windows server 2012?

Good luck!

This photo has the hover spots clearly marked with bright red to make it easier.   In order to get to the 'start screen' you have to hover in one of these areas.

What?  You missed it?  Can't find it?  They are only a couple of pixels wide!  I circled them with  yellow quarter circles, the actual hover areas are still in red:


I'm an avid microsoft user, and a fan of many of their products.  However, this is just about the dumbest thing I have run across yet, and it crosses a line to absolute stupidity.  This is a SERVER OS!  I access it from virtual consoles across networks!  It probably isn't even a real machine, but is a virtualized host in a datacenter somewhere.  You might say, you can press the 'start button' on your keyboard right?  NOT on a virtual host, the start button works on your local PC only.  It isn't that big of a deal you might say, just hover on those spots, now that you know where they are, right?  Again, this is a VIRTUAL MACHINE which means it is accessed through a virtual screen on my desktop.  It doesn't have edges that your mouse stops at.  You have to very carefully line up the mouse with the exact 2 pixel wide spots and play with it until you get it right.  What is wrong with MS?  Does anyone in Redmond actually use this?  Once you finally get the start 'screen' up, the fun really begins, because everything has been moved and hidden and you get to start over with finding anything.  Note that the locations haven't been IMPROVED, they have just been MOVED for the sake of moving them.  Once you find the ones you need, you better pin them to your start bar, or you'll get to do this rediculous operation day in and day out.  Microsoft: Why the start button HATE?  What did the start button ever do to you?  You still put the stupid TRASH CAN on the main screen, and I don't even want it!

Microsoft should take a lesson from the auto industry:  DONT MOVE CRITICAL CONTROLS.  Imagine if they did this with cars, and they just randomly moved the turn signals, headlights, gas pedal and brakes around.  Each car you got into would have them in different places.  When you took it in for service, they'd re-arrange them just 'because' and if you didn't like it, it would be your own fault.

Tuesday, August 28, 2012

Break anywhere in Javascript from Firebug

Developing client side code can be challenging, often you need to be able to break at very specific place in the code to debug an issue, check a variable value or troubleshoot a non operational point.

Firebug has a very useful feature, 'Break on Next' which can be used to break on the next line of javascript that executes.  However, most pages have mouseover effects, click events and other things that may fire before you can ever get to the thing that you want to break on.  What if you want to break on a sub menu that can only be reached by clicking on it's parent? 

Firebug 1.10a8 introdcued a short cut key to enable 'Break on Next'. This allows you to get your mouse lined up on the exact position in your app that you want to break on, hit CTRL-ALT-B on your keyboard and then click.  This allows you to get past all the mouseover, onclick and other issues and break on exactly the click you want to break on.

Monday, August 27, 2012

Using an F5 iRule to solve cross domain ajax calls instead of CORS or JSONP

As a web developer at some point you will likely face a requirement to make cross-domain calls from a client side web page.  To prevent data from being loaded from multiple sites and presented as all belonging to the same site, browsers have a form of security built in that prevents scripts from being able to load data from other sites.

I recently worked with a situation that required deployment of a new RESTful web service layer that worked in concert with an existing ASP.Net application.  A process of refactoring required the projects to be treated separately and to be deployed on different URLs.  Both URLs were owned by the same organization and browser version compatibility requirements were well defined.  The browser support requirement included IE7 and newer, Firefox, Chrome and Safari.

Due to browser support issues, it was not ideal to use either CORS or JSONP to meet the requirements as both have various issues with certain browsers.  After reviewing the F5 documentation a solution was created using an iRule on the switch to represent the RESTful web site as a 'virtual folder' under the main web site.  This hides the real location of the REST service layer from the client and the client browser is not aware of the switch happening behind the scenes.  The client sees the RESTful service site on the same URL as the ASP.net site and nothing special is needed to make ajax calls.


when HTTP_REQUEST {
  if { [HTTP::uri] starts_with "/restservice" } {
    if {([string tolower [HTTP::host]] contains "aspapp.example.com")}{
      HTTP::header replace "Host" "restsvc.example.com"
 HTTP::uri [substr [HTTP::uri] 12 ]
    }
  }
}

This iRule traps on URI's that begin with /restservice.  If found it verifies that the host is the ASP.net application URL, and replaces it with the restservice URL replacing the Host from it's original URL (restsvc.example.com). The final command modifies the URI to remove the virtual folder from the call to create the new, proper URL that can be interpreted by the server.

The iRule allows pages at: aspappdomain.example.com to make ajax calls to the rest service at aspappdomain.example.com/restservice even though that URL doesn't actually exist anywhere, except in this iRule.

The key to making this work is that both sites must be serviced on the same IP address and be using host header names to serve the proper content.  If the sites are on different IPs the iRule will have no effect.

These few lines of code saved a lot of work on the client side and ensured support accross all browsers quickly and easily.