Custom dropdown/auto-complete with AngularJS (Version 2)

It’s been over a year now since I released the version 1 of what I called the Custom Select directive (since it was based on the functionality of the AngularJS select directive).

Unfortunately, the designers of AngularJS decided to change the way the select directive works on version 1.4, thus breaking some of the features of this directive. So I decided to redesign it and use a different (and actually simpler) approach. So what used to be:


<div custom-select ng-model="fruit" ng-options="f for f in fruits">
</div>

is now:


<div custom-select="f for f in fruits | filter: $searchTerm" ng-model="fruit">
</div>

where $searchTerm is a parameter provided by the directive, that corresponds to the text in the search box.

Now the directive delegates the job of filtering to the programmer, letting you use any of the built-in AngularJS filters, or plugging in your own:





<div custom-select="p as p.name for p in findPeople($searchTerm)" ng-model="person">
</div>




And filter synchronously:

$scope.findPeople = function (term) {
    // Suppose we have a people array
    var found = [];
    for (var i = 0; i < people.length; i++) {
        if (/* search all properties you like */) {
            found.push(people[i]);
        }
    }
    return found;
};

Or asynchronously:

$scope.findPeople = function (term) {
    var url = 'http://mysite.com/search?q=' + encodeURIComponent(term);
    return $http.get(url); // This server call must return an array of objects
};

You can check out the new code from the GitHub repository. If you still want to use the previous version, you can find it here.

Happy coding!

Angular.NET – Helpers for ASP .NET MVC 4

ASP .NET MVC is a great web-server framework and, in my opinion, a HUGE improvement over regular ASP .NET WebForms. Among many features, it has routing, helper methods to generate views, declarative model validation (data annotations), automatic model binding for different media types (with model validation), support for dependency injection, etc.

On the other hand, AngularJS is a great client-side framework that helps you to create professional applications using JavaScript. It’s loaded with features such as client-side routing, directives for custom behavior like model binding (ngModel) and model validation, filters, message dispatcher, dependency injection, etc.

Currently, creating HTML forms with model bindings and the respective validations and error messages for each field in the form can be a tedious, error-prone task. Suppose we have the following model class:

using System;
using System.ComponentModel.DataAnnotations;

public class Person
{
    public int Id { get; set; }

    [Required]
    [StringLength(25)]
    [Display(Name = "First Name")]
    public string FirstName { get; set; }

    [Required]
    [StringLength(25)]
    [Display(Name = "Last Name")]
    public string LastName { get; set; }
}

Let’s look at an example of how you would create a simple but fully functional form (with validations) in AngularJS for this model (for more information, see the form and ngModel directives):

<form autocomplete="off" class="form-horizontal ng-cloak" id="personalForm" method="POST" name="personalForm" ng-submit="save(personalForm)" novalidate>
    <div class="control-group" ng-class="{ error: personalForm.FirstName.$invalid && personalForm.FirstName.$dirty }">
        <label class="control-label" for="FirstName">First Name</label>
        <div class="controls">
            <input autofocus id="FirstName" name="FirstName" ng-maxlength="25" ng-model="FirstName" required type="text" />
            <span class="help-inline" ng-show="personalForm.FirstName.$error.required && personalForm.FirstName.$dirty">The First Name field is required.</span>
            <span class="help-inline" ng-show="personalForm.FirstName.$error.maxlength && personalForm.FirstName.$dirty">The field First Name must be a string with a maximum length of 25.</span>
        </div>
    </div>
    <div class="control-group" ng-class="{ error: personalForm.LastName.$invalid && personalForm.LastName.$dirty }">
        <label class="control-label" for="LastName">Last Name(s)</label>
        <div class="controls">
            <input id="LastName" name="LastName" ng-maxlength="25" ng-model="LastName" required type="text" />
            <span class="help-inline" ng-show="personalForm.LastName.$error.required && personalForm.LastName.$dirty">The Last Name(s) field is required.</span>
            <span class="help-inline" ng-show="personalForm.LastName.$error.maxlength && personalForm.LastName.$dirty">The field Last Name(s) must be a string with a maximum length of 25.</span>
        </div>
    </div>
    <div class="control-group">
        <div class="controls">
            <button class="btn btn-primary" type="submit">Save</button>
            <button class="btn" type="button" ng-click="cancel()">Cancel</button>
        </div>
    </div>
</form>

Now, that was only a form with two fields (I know, I have a several rules and validation messages, but it’s a real-world case). This works like a charm but, as you can see, it requires a great deal of maintenance effort. You need to add all the validation directives, the appropriate help messages and the rules for when to display/hide them. You will need to be careful to keep you form validations in sync with your server side models if any of the following occur:

  • The names of your model properties are modified.
  • The validations for a specific property are added/removed.
  • The values for such validations are changed (for example, the max value for a number or the max length for a string field)

That’s a lot work for me. Since I’m too lazy for all that, I thought there must be something that could save me some time when coding and maintaining my code. It turns out there is a great ASP .NET MVC feature that could come to the rescue: HTML helper extension methods. So, inspired by a solution that I used for Knockout some time ago (Knockout MVC) and by ASP .NET MVC’s jQuery unobtrusive validation, I created a small library for AngularJS that integrated both features (binding and validation generation).

Using this library, the same view can be created in Razor as follows:

@using AxSoft.Angular.Net

@model AxSoft.Model.Person
@using (var form = Html.BeginAngularForm("personForm", "save", "person", new { @class = "form-horizontal ng-cloak" }))
{
    <div class="control-group" @form.NgClassError(m => m.FirstName)>
        @form.Label(m => m.FirstName)
        <div class="controls">
            @form.TextBox(m => m.FirstName, new { autofocus = "" })
            @form.ValidationsFor(m => m.FirstName, true)
        </div>
    </div>
    <div class="control-group" @form.NgClassError(m => m.LastName)>
        @form.Label(m => m.LastName)
        <div class="controls">
            @form.TextBox(m => m.LastName)
            @form.ValidationsFor(m => m.LastName, true)
        </div>
    </div>
    
    <div class="control-group">
        <div class="controls">
            <button class="btn btn-primary" type="submit">Save</button>
            <button class="btn" type="button" ng-click="cancel()">Cancel</button>
        </div>
    </div>
}

A few things to note:

  • You need to import the AxSoft.Angular.Net (or add it to the namespaces node of you web.config file under the Views folder).
  • You have to declare the model type for the extension methods to work properly. Note that this declaration only acts as an indication of the type of model you want to get the properties from, but you don’t need to pass an actual model instance to the view.
  • You can create a form almost exactly as you would using the Html.BeginForm method, supplying the following values:
    • A form name: this will be used for the validation message conditions; also, AngularJS will create a property on your controller’s scope with the same name as the form.
    • The name of the method to be invoked when the form is submitted (optional); this is used to output the ng-submit directive in the form ng-submit="nameOfMethod(nameOfForm)". The form instance is passed to the method so that you can check the validity of the form through form.$valid. The default value is "save"
    • The name of the scope property that will hold the model object (optional).
    • An object or dictionary instance containing custom HTML attributes to be set on the form (optional).

The invocation of Html.BeginAngularForm will return a generic AngularForm object which you can use to create your form controls and bindings.

You can create controls for specific model properties using the methods TextBox, Hidden, TextArea, Password, RadioButton, CheckBox, and Dropdown. These methods will output the corresponding ngModel directive as well as all the registered validations found in the ValidationAttribute‘s of the property.

The method ValidationsFor will generate span elements for each registered validation for the property. Each element will have a CSS class with the value you specify in the AngularConfiguration.HelpCssClass property (the default is "help-inline").

The method Label is similar to Html.LabelFor, with the only advantage of creating a for attribute that will match the id attribute of the control generated for the same property.

Lastly, the method NgClassError will output an ng-class directive that will activate the error CSS class of the element when any of the validations for that property fail to pass. The name of this class will be given by the value of the AngularConfiguration.ErrorCssClass property (the defautl is "error").

Interested? Grab the code from Github and play with it. Any feedback is welcome.

In a future tutorial: how to extend the validation mechanism with custom validation attributes and directives. Stay tuned.

Using XSLT as email template engine in C#

Email has been (and will be for some time) one of the main means to communicate with your customers and perform various core business and security tasks (such as confirming a newly created accounts, helping a user reset their lost password, notify updates and required actions, etc.). These emails usually consist of static sections and some dynamic parts that are specific to the user receiving the email.

Sometimes, a simple string replacement approach works to achieve such goal (that’s what I used to do before). But if you need something more elegant and powerful than that, a good option would be using XSLT. I am no XSLT expert and I won’t talk about it in this post, but I encourage you to learn about it if you don’t already know. In order to follow the principle of separation of concerns and improve testability, the solution is separated into four components with their corresponding interface (contract):

  • A XSLT template compiler (ITemplateCompiler). A simple wrapper that uses cached XslCompiledTransform‘s.
  • An email sender (IEmailSender). Another wrapper, in this case, around the SmtpClient. This is abstracted away in order to mock the actual sending of the email when testing (dump the result to console or to a text file, etc.).
  • A custom XML serializer (IXmlSerializer). Why not use the built in XML serializer? Simple: it doesn’t work with anonymous objects. Sometimes we want to pass our variables without having to explicitly create a class for it. In case you do want to use the regular serializer, you can always create a wrapper that implements IXmlSerializer.
  • A template email sender (ITemplateEmailSender). Integrates all the above mentioned services.

The XSLT compiler

Not much to say about it. It will accept an input XML stream (this would be your variables object serialized as XML), an XSLT file path (or stream), and an output stream to dump the resulting transformation. If you use the overload that accepts the XSLT file path, the XslCompiledTransform object will be cached.

The email sender

Again, as simple as it sounds. Just to decouple the actual sending of the email. In the example, I dump the result to an HTML file called output.html.

The XML Serializer

For the custom XML serializer, I borrowed Martin Normark‘s solution, but made some modifications to it, mainly allowing for the serialization of any kind enumerable, not only arrays.

Basically, it will turn any object into XML following these rules:

  1. If no root element name is provided, “object” will be used.
  2. All properties will be serialized as XML nodes with the same name as the property.
  3. For collection properties, the main node will be named after the property, and the child nodes will have the same name with the suffix “Item” appended.

The template email sender

This is the one that puts all together, and has dependencies to everything else. It only has a Send method (and its async counterpart). You’ll notice that it does not accept a from parameter. That’s because you usually handle that in the SMTP configuration part of your project’s web.config or app.config. If you need it, just go ahead and add it.

Additionally, this service has a LayoutFilePath property. Inspired by ASP .NET’s layout (or master) pages, only much simpler, this allows to have a base, static HTML content file where you can put the frame and layout that is common to all the emails that you will send. If this property is null, then the output will be only what results from the XSLT transformation. The only requirement for your layout file is that you need to include the following wherever you want the content placed:

<!-- Content -->

For example:

<html>
<head>
</head>
<body>
<div style="height: 10px; font-size: 10px; line-height: 10px;">&nbsp;</div>
<table width="602" border="0" cellspacing="0" cellpadding="0" align="center">
<tbody>
<tr>
<td>
<!-- Content --></td>
</tr>
</tbody>
</table>
<div style="height: 10px; font-size: 10px; line-height: 10px;">&nbsp;</div>
</body>
</html>

Putting it all together

var templateDirectory = Path.Combine(Environment.CurrentDirectory, "Templates");
var layoutFile = Path.Combine(templateDirectory, "layout.html");
var xsltFilePath = Path.Combine(templateDirectory, "ActivateAccount.xslt");
var variables = new
{
FirstName = "Axel",
LastName = "Zarate",
Username = "azarate",
Logo = "http://www.logotree.com/images/single-logo-design/logo-design-sample-14.jpg",
ActivationLink = "http://localhost/Account/Activate/azarate"
};

var templateEmailSender = new TemplateEmailSender(emailSender, templateCompiler, xmlSerializer)
{
LayoutFilePath = layoutFile
};

templateEmailSender.Send(xsltFilePath, variables, "axel.zarate@mail.com", "This is a template test");

Advice: To maximize email viewing compatibility across different clients, use regular tables for layout and old HTML attributes for appearance (width, bgcolor, etc.).

Check out the source code and sample.

AngularJS Tree View Control

Did I mention that I love AngularJS? Oh, yes I did, on my previous post. Well, in case you didn’t believe me, this time I would like to share yet another small solution with AngularJS. By the way, I forgot to mention that I also use the awesome Twitter Bootstrap CSS framework, along with the also awesome Font Awesome font icons.

I made this simple tree view directive to simulate a file explorer. There was some more functionality specific to the project but I removed it for this demo. I intend to work a little bit more to make it into a more generic, configurable solution (suggestions accepted). In order to use it, you just need to add the necessary JavaScript and CSS files and drop the following HTML code in your page:

<div tree-view="structure" tree-view-options="options"></div>

Where structure is the JSON model containing the folders and files, and options is the tree view configuration (optional). If you don’t provide any, the default configuration is used.

The configuration options object currently accepts the following values:

Param Type Default Details
foldersProperty String "folders" Name of the property that contains the folders array in your model.
filesProperty String "files" Name of the property that contains the files array in your model.
displayProperty String "name" Name of the property that contains the name to be display both for files and folders.
collapsible Boolean true Whether or not the nodes are collapsible. If false, the nodes will always be expanded.
onNodeSelect function (Object, Array) undefined A callback function that is executed whenever a folder/file is selected. The first argument passed to the function is the actual node from the model, and the second argument is a dynamically generated array of all the ancestor nodes. This is useful to display breadcrums for the selected path.

The following is an example model and configuration that can be supplied to the tree view:

$scope.structure = { folders: [
    { name: 'Folder 1', files: [{ name: 'File 1.jpg' }, { name: 'File 2.png' }], folders: [
        { name: 'Subfolder 1', files: [{ name: 'Subfile 1' }] },
        { name: 'Subfolder 2' },
        { name: 'Subfolder 3' }
    ]},
    { name: 'Folder 2' }
]};

$scope.options = {
    onNodeSelect: function (node, breadcrums) {
        $scope.breadcrums = breadcrums;
    }
};

The result should be similar to this:

Untitled

The directive is recursive, so it should be able to handle any number of hierarchy levels (in theory). Source code in GitHub.

Update (8/28/2014): Added option mapIcon, which expects a function that takes a file node as the argument and must return a custom icon class (String). Sample usage included.

Custom dropdown/auto-complete with AngularJS

Update (2015-09-17): Check out new Version 2 of this control.

I’ll admit it, I’m a big fan of AngularJS; it’s a great framework. If you consider yourself a serious front-end developer, you should really know about AngularJS. In our day to day work, we frequently find challenging requirements and problems that need to be solved efficiently and, why not, elegantly. And frameworks such as AngularJS help us achieve just that, and even turn our solutions into generic pieces of work that we can put in our tool box and use here and there across different projects. This time I will talk briefly about one such case. Hopefully it can be of use to someone else, too.

The problem

We all need to use an auto-complete box once in a while. There are many good solutions out there that are easy to use. But… they are usually limited to working with strings. On the other hand, regular select elements are great when you want to display names but use Id’s (or some sort of unique value) for your model and your business rules. But… they are pretty inflexible and “boring”. So, I needed and auto-complete box that worked also well with complex objects, and could integrate seamlessly with AngularJS.

The solution

Create an AngularJS directive from scratch. At least that was the only option I saw. And it didn’t turn out too bad after all. So here it is, Custom Select (sorry for the totally uncreative name).


<div custom-select ng-model="fruit" ng-options="f for f in fruits">
</div>

You may have noticed that the attributes look very similar to those of a regular AngularJS select directive (except for the additional custom-select attribute). Assuming you setup the appropriate values in your scope, you’ll get something like this.

Untitled

If you want to use JSON objects and have a display property and another property that gets saved to your model, you could use something like this:


<div custom-select ng-model="state" ng-options="s.id as s.name for s in states">
</div>

The end result would look very similar, but will work slightly different.

As a bonus, you could use a custom template for your dropdown items. Here’s an example:


<div custom-select ng-model="person" ng-options="t as t.name for t in people">

<div class="pull-left" style="width: 40px">
        <img ng-src="{{ t.picture }}" style="width: 30px" />
    </div>


<div class="pull-left">
        <strong>{{ t.name }}</strong>
        <span>{{ t.phone }}</span>
    </div>


<div class="clearfix"></div>

</div>

And the end result:
Untitled

If you liked it, you can grab the source code and the examples from Github.

Dependency injection in ASP .NET MVC with Autofac

Dependency injection (DI) is one form of inversion of control, which is a technique used to reduce coupling between components by replacing hard-coded dependencies with abstractions (usually interfaces) that are passed (injected) to the consuming component.

DI offers a number of benefits and encourages good practices that result in other benefits, such as:

  • Modularity: dependency injection practices favor a more modular application design.
  • Simplified Unit testing
  • Dynamic behavior: allows the changing of concrete implementations of services at runtime or compile time.
  • Scalability
  • Decoupling
  • Service life-cycle management: service containers can take care of the creation, sharing, and disposal of object instances when needed (i.e., we don’t need to call IDisposable.Dispose ourselves).

There are many CI containers out there, but today I will talk about one that I like in particular because it’s simple, flexible and light: Autofac. More specifically, I will show you how you can use it in your ASP .NET MVC projects.

We’ll start by creating an MVC project in Visual Studio (in this case, MVC 4). Choose the template that best suits your needs; in this example I chose the Basic template and I called it AutofacExample. Open the Package Manager Console and execute the following command to install Autofac for MVC 4:

Install-Package Autofac.Mvc4

(You can use the Manage NuGet Packages option, and then search for Autofac MVC4, if you’re more comfortable with the UI version.)

Suppose we already have a few business entities, including Customer. Let’s start by defining some simple services (interfaces and implementation).

using System.Collections.Generic;
using AutofacExample.Models;
 
namespace AutofacExample.Services
{
	public interface IRepository<T> where T : class
	{
		IEnumerable<T> All();
 
		T Get(int id);
 
		void Update(T entity);
 
		void Delete(int id);
	}
 
	public interface ICustomerRepository : IRepository<Customer>
	{
		IEnumerable<Receipt> GetReceipts(int customerId);
	}
 
	public class CustomerRepository : ICustomerRepository
	{
		public IEnumerable<Customer> All()
		{
			// Code goes here
		}
 
		public Customer Get(int id)
		{
			// Code goes here
		}
 
		public void Update(Customer entity)
		{
			// Some code
		}
 
		public void Delete(int id)
		{
			// Code goes here
		}
 
		public IEnumerable<Receipt> GetReceipts(int customerId)
		{
			// Code goes here
		}
	}
}

Next, in our MvcApplication class (in the Global.asax.cs file), we create a RegisterServices method, which we’ll invoke in Application_Start:

private static void RegisterServices()
{
	var builder = new ContainerBuilder();
	var assembly = Assembly.GetExecutingAssembly();

	// Tell autofac to scan the assembly and register all subclasses of System.Web.Mvc.Controller 
	builder.RegisterControllers(assembly);

	// Register repository, and expose it only through the ICustomerRepository interface
	builder.RegisterType<CustomerRepository>()
		.As<ICustomerRepository>().InstancePerHttpRequest();
 
	// Build the container and set it as the default dependency resolver
	var container = builder.Build();
	var resolver = new AutofacDependencyResolver(container);
	DependencyResolver.SetResolver(resolver);
}

(You will need to add using statements for Autofac and Autofac.Integration.Mvc.)

Notice we declared our repository’s lifetime as per HTTP request. This means that the container will dereference the instance after the request has completed so that it can be garbage-collected. If the service implements the IDisposable interface, the Dispose method will be invoked before the instance is released.

Finally, we can add a CustomerController (or use the default HomeController) to consume our newly created CustomerRepository, through its interface. The controller will declare a constructor dependency to ICustomerRepository and Autofac will take care of resolving and instantiating the dependencies and the controller itself.

using AutofacExample.Services;
using System.Web.Mvc;
 
namespace AutofacExample.Controllers
{
	public class CustomerController : Controller
	{
		private readonly ICustomerRepository _customerRepository;
 
		public CustomerController(ICustomerRepository customerRepository)
		{
			_customerRepository = customerRepository;
		}
 
		public ActionResult Index(int id)
		{
			var customer = _customerRepository.Get(id);
			return View(customer);
		}
	}
}

This is a ridiculously simple example, but in a real life application, dependencies would be nested in many levels. For example, our CustomerRepository could have a dependency to a DataService, which in turn may declare dependencies to other services. Autofac will kindly take care of all that mess and deliver what we ask for (as long as all objects involved are properly registered and configured).

Usually, an application may use many services and registering them one by one would be tedious and error prone. But if we use some naming standards for our services we can use assembly scanning and register many at once. For example:

var assembly = Assembly.GetExecutingAssembly();
// Assuming all repository names end with Repository
builder.RegisterAssemblyTypes(assembly)
	.Where(t => t.Name.EndsWith("Repository"))
	.AsImplementedInterfaces();

If you need more control over how a specific service is instantiated, you can specify it:

// Use the connection string named DefaultConnection
builder.Register(d => new Database("DefaultConnection"))
	.As<IDatabase>().InstancePerHttpRequest();

There are many more tips and tricks when using Autofac as your dependency injection container in ASP .NET MVC. Stay tuned.

Model validation filter in ASP .NET Web API

Most Web applications need to be able to accept and save data, and any serious application must perform all sorts of validations before taking information and attempt to store it. Luckily for us (.Net developers at least), the days of manual, imperative validation are gone for good.

Thanks to Data Annotations, model validation and error messages have become easy and consistent. We can pick from the built in validation attributes in the System.ComponentModel.DataAnnotations namespace (such as RequiredAttribute, StringLengthAttribute, CompareAttribute) or roll our own, and then declare our intention to validate our objects properties by decorating them with the corresponding attributes. This validation mechanism is plugged right into the core of ASP NET MVC and Web API, so we can check right away if a model entity passed to a controller action is valid or not:

// MyModel.cs file
using System.ComponentModel.DataAnnotations;

public class MyModel
{
	[Required(ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "MyModel_Name")]
	public string Name { get; set; }

	[EmailAddress]
	public string Email { get; set; }
}

// MyController.cs file
using System.Web.Http;

public class MyController : ApiController
{
	public HttpResponseMessage Post(MyModel model)
	{
		if (ModelState.IsValid)
		{
			// Work with the object
			_repository.Save(model);
			return new HttpResponseMessage(HttpStatusCode.OK);
		}
		else
		{
			var errors = ModelState.Values.SelectMany(v => v.Errors.Select(e => e.ErrorMessage)).ToArray();
			return Request.CreateResponse(HttpStatusCode.BadRequest, new { errors });
		}
	}
}

Easy, huh? But, if you are as lazy (or practical) as me, and don’t want to keep checking your model validity in every action, you can centralize that logic in only one place and then apply it wherever you like. Just create an ActionFilterAttribute:

using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;

public class ModelValidationFilterAttribute : ActionFilterAttribute
{
	public override void OnActionExecuting(HttpActionContext actionContext)
	{
		if (!actionContext.ModelState.IsValid)
		{
			var errors = actionContext.ModelState.Values.SelectMany(v => v.Errors.Select(e => e.ErrorMessage)).ToArray();
			actionContext.Response =
				actionContext.Request.CreateResponse(HttpStatusCode.BadRequest, new { errors });
		}
	}
}

And on your controllers:

public class MyController : ApiController
{
	[ModelValidationFilter]
	public HttpResponseMessage Post(MyModel model)
	{
		// No need to check for validity (if model is not valid, the method will not be called)
		_repository.Save(model);
	}
}