Learning Kendo UI Web Development with MVC Book Published…!

Follow up on one of my previous blog post in regards to Kendo UI Web with MVC book project I had the opportunity to be involved with as a Technical Reviewer, the book is complete and has been published..! Kudos to John Adams (author) from RBA for all the late nights, weekends and hard work I know he put into the project.

For those of you looking for a good starting point, incorporating Kendo UI Web into your MVC project or solution the book has some good real world practical implementations with ASP.NET MVC.

Personally and professionally Kendo UI Web is my client side framework of choice. It’s one solution that offers it all, so that you don’t have into incorporate and include several different frameworks to gain some of the fundamental features of Kendo UI Web, especially when working with MVC.

My personal top favorite features of Kendo UI Web Framework

  • Widgets (client-side controls)
  • MVVM Framework (a must have for modern web apps)
  • Validation Framework
  • Templates
  • Built on top of jQuery
  • Custom UI/UX Themes
  • MVC 4 Sever Side Wrappers
  • SPA (Single Page App) Support (a must have for modern web apps)
  • Globalization
  • DataSource
  • List goes on…

http://www.amazon.com/dp/1849694346/?tag=packtpubli-20
http://www.packtpub.com/learning-kendo-ui-web-development/book
http://packtlib.packtpub.com/library/9781849694346

An easy-to-follow practical tutorial to add exciting features to your web pages without being a JavaScript expert with this book and ebook

Overview

Learn from clear and specific examples on how to utilize the full range of the Kendo UI tool set for the web
Add powerful tools to your website supported by a familiar and trusted name in innovative technology
Learn how to add amazing features with clear examples and make your website more interactive without being a JavaScript expert

In Detail

Creating useful and attractive web sites for today’s audiences requires more JavaScript programming than ever before. JavaScript, however, isn’t easy and staying up to date with recent trends makes it even harder. You need a way to integrate the latest technology into your web site without having to start from the beginning.

“Learning Kendo UI Web Development” shows you how to add the latest web features to your site without doing all of the work yourself. The experts at Telerik have created a fully supported code library that lets you focus on what makes your sites special while letting them focus on how that translates into cutting edge JavaScript code.

This book will take you on a survey through Kendo UI for the web from the basic widgets that wrap input fields to the full page scaffolding widgets for setting up your site.

Kendo UI for the web is a rich framework of JavaScript widgets and tools that will add immediate value to your web sites. Learn the full spectrum of what Kendo UI has to offer in specialized widgets that gather input from users by displaying calendars, sliders, or date pickers all the way up to widgets that structure your web pages through data-driven models in accordions, tabs, list views, and tree views.

“Learning Kendo UI Web Development” is the perfect companion for navigating the broad features offered by Telerik in JavaScript web development.

What you will learn from this book

  • Leverage data source objects and JavaScript templates with the TabStrip and Grid widgets
  • Guide users in date selection with the Calendar widget
  • Create fast and fluid word wheels with the AutoComplete widget and date selection with the Calendar widget
  • Take advantage of the powerful MVVM JavaScript architectural pattern
  • Take full HTML input from users with a graphical editor
  • Structure your site with the Menu and ListView widgets
  • Build interactive accordions with the PanelBar widget and a fun way to select numbers with the Slider widget
  • Organize your data with the Splitter and TreeView widgets and Customize pop-up windows and file uploads with the Window and Upload widgets

Approach

A practical tutorial with step-by-step example based approach.

Who this book is written for

This book is for web developers who want to take advantage of cutting edge JavaScript and HTML 5 web site features, but who don’t have the time or the knowledge to write all of that code by hand. The reader should be familiar with basic HTML 5 and JavaScript but does not need to be an expert.

Author:

John Adams currently works as an application development consultant in the Dallas/Fort Worth area for a fantastic company called RBA. He has been developing custom business applications with the Microsoft .NET platform for 6 years and has specialized in development with ASP.NET MVC. He loves writing code and creating solutions. Above all, he loves his wife and children and the lord Jesus Christ.

This book is dedicated to Michell, Samuel, and Sophie whose patience with my late nights made this project possible.

I would also like to thank RBA, especially my manager Will, who introduced me to the project and kicked everything off.

Finally, I would like to thank Kartikey Pandey, Anugya Khurana, Mayur Hule, Ricardo Covo, and Long Le for their oversight and editing skills. Their work has been exceptional and valuable throughout.

Reviewers:

Ricardo Covo has more than a decade of international experience in the Software Development field, with experience in Latin America, California, and Canada. He has a wealth of experience in delivering data-driven enterprise solutions across various industries.

With a Bachelor’s degree in Systems Engineering, complemented with a certification in Advanced Project Management, he has the right combination of technical and leadership skills to build development teams and set them up for efficient execution.

In 2007 he founded (and is the principal of) Web Nodes – Software Development (http://webnodes.ca); a custom software development company, with clients big and small in Canada, United States, and South America.

Prior to Web Nodes, Ricardo spent some years in the corporate world both in Canada and in the U.S., being part of companies such as Loblaws Inc., Trader Corporation, UNX (http://www.unix.com) and Auctiva (http://www.auctiva.com).

Ricardo’s passion for technology goes beyond work; he normally works on personal projects in an effort to always remain on top of the changes in technology. These projects include: http://ytnext.com, http://serversok.com, and http://toystrunk.com.

Long Le is a Principle .NET Architect and ALM Practitioner at CBRE. He also serves as consultant for Thinklabs and spends most of his time developing frameworks and application blocks, providing guidance for best practices and patterns, and standardizing the enterprise technology stack. He has been working with Microsoft technologies for over 10 years.

Le has focused on a wide spectrum of server-side and web technologies, such as ASP.NET Web Forms, ASP.NET MVC, Windows Workflow, LINQ and Entity Framework, DevExpress, and Kendo UI. In his spare time, he enjoys blogging (http://blog.longle.net) and playing Call of Duty on his XBOX. He’s recently became a proud father of his new born daughter Khloe Le. You can reach and follow him on Twitter @LeLong37.

Special thanks to my significant other Tina Le for all your love and support throughout this project and to my wonderful newborn daughter Khloe Le. I love you.

https://twitter.com/LeLong37/status/344402714240897024

Building an Extensible Fluent Validation Framework using Generic Funcs and Wiring it up to MVC 4 with ModelValidatorProvider and ModelValidator

Live demo http://longle.azurewebsites.net/customer, courtesy of Windows Azure free 10 Websites, will keep this out there for as long as it’s free 🙂

We will start off in a pre-baked solution from my last post http://blog.longle.net/2013/05/17/generically-implementing-the-unit-of-work-repository-pattern-with-entity-framework-in-mvc-simplifying-entity-graphs-part-2-mvc-4-di-ioc-with-mef-attributeless-conventions/ using Unity 3.0 as our DI framework of choice.

Before we starts let’s define some of key architecture & design principles we are attempting to achieve here.

  • Validation Framework can run in any .NET technology space e.g. WPF, MVC, ASP.NET WebForms, ASP.NET MVC, SilverLight, WF, Windows Services, WCF, etc..
  • Validation Framework is extensible, and easy to do so.
  • Validation Framework will support reusable validations so that we can reuse them across the enterprise.
  • Validation Framework will support ad-hoc validations, meaning validations, that potentially will only be used once, that are not common validations, and very specific to a given entity with a unique use case.
  • Validation Framework can easily be plugged in e.g such as the MVC 4 run-time, not requiring developer’s to do anything different than they are today to validate their models.

We have a lot to cover so let’s dive right into the Validation project and its’ code!

Validation.Validator.cs


namespace Validation
{
    public class Validator<TModel> : IValidator
    {
        private readonly List<ValidationResult> _validationResults;
        private readonly List<Validation<TModel>> _validations;

        public Validator()
        {
            _validations = new List<Validation<TModel>>();
            _validationResults = new List<ValidationResult>();
        }

        public List<ValidationResult> Validate(object model)
        {
            foreach (var validation in _validations)
            {
                validation.OnValidating();
                var validater = validation.GetValidater();

                if (!validater((TModel) model))
                    _validationResults.Add(validation.GetValidationResult());
            }

            return _validationResults;
        }

        public Validation<TModel> AddValidation(Validation<TModel> validationRule)
        {
            _validations.Add(validationRule);
            return validationRule;
        }
    }
}

This is probably one of the most important class of our Validation Framework, it primary responsibility are:

  • Iterating through all of our validations for a given entity
  • Storing the result for each of the validations

Validation.Validation.cs


    public class Validation<TModel>
    {
        private string _errorMessage;
        private string _propertyName;
        private Func<TModel, bool> _validater;
        private Expression<Func<TModel, object>> _property;

        public Expression<Func<TModel, object>> GetProperty()
        {
            return _property;
        }

        public Validation<TModel> SetProperty(Expression<Func<TModel, object>> property)
        {
            _property = property;
            return this;
        }

        public string GetPropertyName()
        {
            var memberExpression = GetProperty().Body as MemberExpression ?? ((UnaryExpression) GetProperty().Body).Operand as MemberExpression;

            if (memberExpression == null)
            {
                _propertyName = default(string);
                return _propertyName;
            }

            _propertyName = memberExpression.Member.Name;

            return _propertyName;
        }

        public Validation<TModel> SetErrorMessage(string errorMessage)
        {
            _errorMessage = errorMessage;
            return this;
        }

        public Validation<TModel> SetValidater(Func<TModel, bool> validater)
        {
            _validater = validater;
            return this;
        }

        public Func<TModel, bool> GetValidater()
        {
            return _validater;
        }

        public string GetErrorMessage()
        {
            return _errorMessage;
        }

        public ValidationResult GetValidationResult()
        {
            return new ValidationResult {ErrorMessage = GetErrorMessage(), PropertyName = GetPropertyName()};
        }

        public virtual void OnValidating()
        {
            if (string.IsNullOrEmpty(_errorMessage))
                _errorMessage = GetPropertyName() + " is not valid";
        }}

The Validation class is primarily responsible for:

  • Keeping track which property of the entity it’s its validation is for.
  • Setting the appropriate validation result and message.

Now really this is really all you need to start validating your entities/models. Although, there are some other classes that are in the Validation project, they are really not needed to start validating. They are there to help us later wire up our Validation Framework to MVC 4. With that being said let’s wire up our first validation, all you need to do is implement the the Validator class.

I’ve added a UnitTest project with two test class, one is simply a dummy model with fictitious property names, the property names are named after the type of validation we are performing on the property so that we can easily understand what type of validation is happening on each of them. The second class MyValidator is where are validations actually reside for validating MyModel.cs.

Notice all the validations are stored in the MyValidator.cs class and that our MyModel.cs knows nothing about any validation business. More importantly our validation is completely decoupled from our entities, giving us nice separation of concerns.

Validation.Tests.MyModel.cs

Note: Again, The property names here are named so that we can easily see what types of validations are happening for each of them. Obviously in the real world they would be named FirstName, LastName, Age, versus Compare1, Compare2, Regex, etc. :p


namespace Validation.Test
{
    public class MyModel
    {
        public string Compare1 { get; set; }
        public string Compare2 { get; set; }
        public string CreditCard { get; set; }
        public string Id { get; set; }
        public string Length { get; set; }
        public string Range { get; set; }
        public string Regex { get; set; }
        public string Required { get; set; }
        public string IpAddress { get; set; }
        public string Email { get; set; }
    }
}

Validation.Tests.MyValidator.cs
A simple test/sample validator implementation so that we can code up a quick unit test.


namespace Validation.Test
{
    public class MyValidator : Validator<MyModel>
    {
        public MyValidator()
        {
            this.ValidateCompare(m => m.Compare1, m => m.Compare2)
                .WithDataType(ValidationDataType.Integer)
                .WithOperator(ValidationOperator.GreaterThan);

            this.ValidateCreditCard(m => m.CreditCard);

            this.ValidateId(m => m.Id);

            this.ValidateLength(m => m.Length)
                .WithMax(5)
                .WithMin(1);

            this.ValidateRange(m => m.Range)
                .WithDataType(ValidationDataType.Integer)
                .WithMin(1)
                .WithMax(5);

            this.ValidateRegex(m => m.Regex)
                .SetPattern(@"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*")
                .SetErrorMessage("Email must be in valid format");

            this.ValidateRequired(m => m.Required);

            this.ValidateIpAddress(m => m.IpAddress);

            this.ValidateEmail(m => m.Email);

            this.AddValidation()
                .SetProperty(m => m.Email)
                .SetValidater(model => !string.IsNullOrEmpty(model.Email))
                .SetErrorMessage("Email is required");
        }
    }
}

Here we have some simple validation implemented and wired up for our MyModel.cs entity. Here we are using some of the out of the box validations I’ve coded up, and some ad-hoc validations we are able to add to our Validator that the Validation Framework provides e.g. validating and Id, length, range, using Regex, required, IP address, email, etc.. Obviously you can easily add your own reusable validation, and again add ad-hoc (lines 34-37) validations that will probably only be specific to a given entity.

Now let’s test our validation by coding up a quick unit test.

ValidationTests.UnitTest1.cs


namespace Validation.Test
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            var myModel = new MyModel();
            var myValidator = new MyValidator();
            var validationResults = myValidator.Validate(myModel);
            
            Assert.AreEqual(validationResults.Count, 4);
            Assert.AreEqual(validationResults[0].PropertyName, "Compare1" );
            Assert.AreEqual(validationResults[1].PropertyName, "Id");
            Assert.AreEqual(validationResults[2].PropertyName, "Required");
            Assert.AreEqual(validationResults[3].PropertyName, "Email");
        }
    }
}

If we run our unit test, we can see that MyModel.cs was nicely validated…!

6-3-2013 2-41-04 PM

Now, this is great, but how do we seamlessly wire this up to MVC 4..?! Good question, let’s get started. To wire up our new Validation Framework with the MVC 4 run-time there are a couple of things we need to do.

First is to implement the ModelValidatorProvider (http://msdn.microsoft.com/en-us/library/system.web.mvc.modelvalidatorprovider(v=vs.98).aspx), this will provide the MVC 4 runtime the necessary implementation to get a set of validations for a model.

Validation.CustomModelValidatorProvider.cs


namespace Validation
{
    public class CustomModelValidatorProvider : ModelValidatorProvider
    {
        public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
        {
            var isPropertyValidation = metadata.ContainerType != null && !String.IsNullOrEmpty(metadata.PropertyName);

            if (isPropertyValidation) yield break;

            var validatorFactory = new ValidatorFactory();
            var validator = validatorFactory.GetValidator(metadata.ModelType, metadata.Model);

            if (validator != null)
                yield return new CustomModelValidator(metadata, context, validator);
        }
    }
}

When implementing the ModeValidatorProvider we see that we do need a factory of some sort to new up an instance of the right Validator to validate our model. We accomplish this with the ValidatorFactory. This class is responsible for discovering the ValidatorAttribute that the MVC model should be decorated with has the Validator type to be activated to validate the model.

Validation.ValidatorFactory.cs


namespace Validation
{
    public class ValidatorFactory
    {
        public IValidator GetValidator(Type type, object model)
        {
            var validatorAttributes = type.GetCustomAttributes(typeof (ValidatorAttribute), true);

            if (validatorAttributes.Length > 0)
            {
                var validatorAttribute = (ValidatorAttribute) validatorAttributes[0];
                return Activator.CreateInstance(validatorAttribute.Validator) as IValidator;
            }   
            return null;
        }
    }
}

The ValidatorAttribute is pretty straight forward, it’s an attribute that accepts a type, which is the Validator type we need to activate to validate the model.

Validation.ValidatorAttribute.cs


namespace Validation
{
    [AttributeUsage(AttributeTargets.Class)]
    public class ValidatorAttribute : Attribute
    {
        private readonly Type _validator;

        public ValidatorAttribute(Type validator)
        {
            _validator = validator;
        }


        public Type Validator
        {
            get { return _validator; }
        }
    }
}

Let’s take a look at our Customer model that is decorated with the ValidatorAttribute so that our ValidatorFactory knows which Validator to activate for it, in our case CustomerValidator.cs.

Data.Models.Customer.cs


namespace Data.Models
{
    [Validator(typeof (CustomerValidator))]
    public class Customer : IObjectState
    {
        public Customer()
        {
            Orders = new List<Order>();
            CustomerDemographics = new List<CustomerDemographic>();
        }

        public string CustomerID { get; set; }
        public string CompanyName { get; set; }
        public string ContactName { get; set; }
        public string ContactTitle { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string Region { get; set; }
        public string PostalCode { get; set; }
        public string Country { get; set; }
        public string Phone { get; set; }
        public string Fax { get; set; }
        public virtual ICollection<Order> Orders { get; set; }
        public virtual ICollection<CustomerDemographic> CustomerDemographics { get; set; }
        public ObjectState State { get; set; }
    }
}

Second, we need to implement the ModelValidator (http://msdn.microsoft.com/en-us/library/system.web.mvc.modelvalidator(v=vs.108).aspx), this will provide the MVC 4 runtime to call into our Validation Framework and execute our Validator.Validate(object model) method and return a set of ValidationResults. Once our ValidationResult payload is returned we will then need to map it back to MVC’s ModelValidationResult so that it can display our validation messages correctly.

Validation.CustomModelValidator.cs


namespace Validation
{
    public class CustomModelValidator : ModelValidator
    {
        private readonly IValidator _validator;

        public CustomModelValidator(ModelMetadata metadata, ControllerContext controllerContext, IValidator validator)
            : base(metadata, controllerContext)
        {
            _validator = validator;
        }

        public override IEnumerable<ModelValidationResult> Validate(object container)
        {
            var validationResults = _validator.Validate(Metadata.Model);

            return validationResults
                .Select(validationResult => 
                    new ModelValidationResult
                        {
                            MemberName = validationResult.PropertyName, 
                            Message = validationResult.ErrorMessage
                        });
        }
    }
}

Finally we need to register our Validation.CustomModelValidatorProvider.cs implementation with the MVC runtime.

Web.Global.asax.cs


namespace Web
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            Bootstrapper.Initialise();

            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();

            // Add our custom ModelValiidatorProvider for MVC runtime
            ModelValidatorProviders.Providers.Add(new CustomModelValidatorProvider());
        }
    }
}

Now let’s start off by validating one of our existing entities Entites.Customer.cs. You can really place your validation objects anywhere you’d like, for simplicity sake I’ll go ahead and place them in the same project as our Entities under a folder named Validations.

Entities.Validators.CustomerValidator.cs


namespace Entities.Validations
{
    internal class CustomerValidator : Validator<Customer>
    {
        public CustomerValidator()
        {
            this.ValidateId(m => m.CustomerID);

            this.ValidateLength(m => m.CompanyName)
                .WithMax(5)
                .WithMin(1);

            this.ValidateRequired(m => m.ContactName);

            this.AddValidation()
                .SetProperty(m => m.City)
                .SetValidater(model => !string.IsNullOrEmpty(model.City))
                .SetErrorMessage("Customer city is required");
        }
    }
}

Now let’s edit our existing CustomController and add two more actions for editing our Customer entity.

Web.Controllers.CustomerController.cs


namespace Web.Controllers
{
    public class CustomerController : Controller
    {
        private readonly IUnitOfWork _unitOfWork;

        public CustomerController(IUnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
        }

        public ActionResult Index(int? page)
        {
            var pageNumber = page ?? 1;
            const int pageSize = 20;

            int totalCustomerCount;

            var customers =
                _unitOfWork.Repository<Customer>()
                    .Query()
                    .Include(i => i.Orders)
                    .OrderBy(q => q
                        .OrderBy(c => c.ContactName)
                        .ThenBy(c => c.CompanyName))
                    .Filter(q => q.ContactName != null)
                    .GetPage(pageNumber, pageSize, out totalCustomerCount);

            ViewBag.Customers = new StaticPagedList<Customer>(
                customers, pageNumber, pageSize, totalCustomerCount);

            return View();
        }

        [HttpGet]
        public ActionResult Edit(string id)
        {
            var customer = _unitOfWork.Repository<Customer>().FindById(id);
            return View(customer);
        }

        [HttpPost]
        public ActionResult Edit(Customer customer)
        {
            if (ModelState.IsValid)
                RedirectToAction("Edit");
            
            _unitOfWork.Repository<Customer>().Update(customer);
            _unitOfWork.Save();

            return View(customer);
        }
    }
}

Notice how we are calling the MVC ModelState.IsValid, and when we debugging this, we see that the MVC run-time will invoke our custom Validation Framework.

6-3-2013 3-30-50 PM

Our error message from Entities.Validation.CustomerValidator.cs.

6-3-2013 3-31-57 PM

All of the out of the box Validators that are included in the example download, follow the described pattern listed below, this is also how you would extend or add your own reusable validations to the framework.

  1. Extend the Validator, by writing an Extension method
  2. Instantiating a fluent helper class for the validation
  3. Setting the property to be validated
  4. Setting the validation logic
  5. Adding the the validation to stack of validations to the Validator instance

Let’s take a quick look at one of the out of the box validations e.g. ValidateLength.

Validation.Validators.ValidateLengthExtension.cs


namespace Validation.Validators
{
    public static class ValidateLengthExtension
    {
        public static ValidateLengthFluentHelper<TModel> ValidateLength<TModel>(this Validator<TModel> validator, Expression<Func<TModel, object>> property)
        {
            var fluentHelper = new ValidateLengthFluentHelper<TModel>();

            fluentHelper.SetProperty(property);
            fluentHelper.SetValidater(model =>
                {
                    var value = property.GetPropertyValue(model) as string;

                    return string.IsNullOrEmpty(value) || value.Length >= fluentHelper.GetMin() && value.Length <= fluentHelper.GetMax();
                });

            validator.AddValidation(fluentHelper);

            return fluentHelper;
        }
    }
}

To provide a nice and easy to use fluent API experience, let’s take a look at the fluent helper class for this validation.

Validation.Validators.ValidateLengthFluentHelper.cs


namespace Validation.Validators
{
    public class ValidateLengthFluentHelper<TModel> : Validation<TModel>
    {
        private int _max;
        private int _min;

        public override void OnValidating()
        {
            if (String.IsNullOrEmpty(GetErrorMessage()))
                SetErrorMessage(GetPropertyName() + " must be between " + _min + " and " + _max + " characters long.");
        }

        public int GetMin()
        {
            return _min;
        }

        public int GetMax()
        {
            return _max;
        }

        public new ValidateLengthFluentHelper<TModel> SetProperty(Expression<Func<TModel, object>> propertySelector)
        {
            base.SetProperty(propertySelector);
            return this;
        }

        public ValidateLengthFluentHelper<TModel> WithMin(int min)
        {
            _min = min;
            return this;
        }

        public ValidateLengthFluentHelper<TModel> WithMax(int max)
        {
            _max = max;
            return this;
        }
    }
}

To use this is fairly straight forward and simple..!

ValidationTest.MyValidator.cs


            this.ValidateLength(m => m.Length)
                .WithMax(5)
                .WithMin(1);


Support for Ad-Hoc Validations with Generic Funcs using AddValidation() Fluent Method

Finally, let’s quickly go over adding ad-hoc validations by adding in-line Lambda’s or Generic Funcs, all you hvae to do is call AddValidation() and using the fluent API, and make sure your generic func accepts a TModel (could be of any object type) and returns a Boolean. In the sample code below we are doing a simple ad-hoc validation for the property Email, validating if there’s a value or not and returning an validation message.

ValidationTest.MyValidator.cs


            this.AddValidation()
                .SetProperty(m => m.Email)
                .SetValidater(model => !string.IsNullOrEmpty(model.Email))
                .SetErrorMessage("Email is required");


There you have it, a Validation Framework registered and wired up to the MVC 4 run-time.

Happy Coding..! 🙂

Download sample application.

https://skydrive.live.com/redir?resid=949A1C97C2A17906!5153&authkey=!AKbcAGKuETlcm6M

Generically Implementing the Unit of Work & Repository Pattern with Entity Framework in MVC & Simplifying Entity Graphs

Update: 02/24/2014 – v3.2 released, improved API and reusable queries with the variation of the Query Object Pattern. Breaking change: Framework now ships returning all things TEntity or IEnumberable for compartmentalization, you will need to change the Repository.cs (see below, what methods signatures to change) if IQueryable is preferred over IEnumerable, IEnumerable is preferred as a best practice (http://genericunitofworkandrepositories.codeplex.com/documentation).

Update [01/06/2014] Quick start online video: http://blog.longle.net/2014/01/06/unit-of-work-unity-3-quick-start-video/

1-3-2014 5-43-38 PM

Update [11/18/2013]: Added mocked DbContext and DbSet and example Unit Tests using the mocks, download: https://genericunitofworkandrepositories.codeplex.com

This will be part two of a six part series of blog posts.

  1. Modern Web Application Layered High Level Architecture with SPA, MVC, Web API, EF, Kendo UI, OData
  2. Generically Implementing the Unit of Work & Repository Pattern with Entity Framework in MVC & Simplifying Entity Graphs
  3. MVC 4, Kendo UI, SPA with Layout, View, Router & MVVM
  4. MVC 4, Web API, OData, EF, Kendo UI, Grid, Datasource (CRUD) with MVVM
  5. MVC 4, Web API, OData, EF, Kendo UI, Binding a Form to Datasource (CRUD) with MVVM
  6. Upgrading to Async with Entity Framework, MVC, OData AsyncEntitySetController, Kendo UI, Glimpse & Generic Unit of Work Repository Framework v2.0

Update: 09/18/2013 – Sample application and source code has been uploaded to CodePlex: https://genericunitofworkandrepositories.codeplex.com, updated project to VS2013, Twitter Bootstrap, MVC 5, EF6, Kendo UI Bootstrap theme, project redeployed to Windows Azure Website.

Update: 07/30/2013 – To see this implementation with DI & IoC with EntLib Unity v3.0, see post: Bounded DbContext with Generic Unit of Work, Generic Repositories, Entity Framework 6 & EntLib Unity 3.0 in MVC 4.

Update: 06/21/2013 – Bug fix: Issue with deleting objects by Id in Repository.Delete(object Id). Updated blog post, and sample solution and added live demo link.

Live demo: http://longle.azurewebsites.net

First off let’s elegantly setup our solution, and prep it for real world development. We have our solution broken up into four different projects, now let’s talk about the “why?”.

5-8-2013 9-08-17 PM

Data Project (Data Access Layer)

This is where all of our ORM tooling related objects reside. In our case the EF (Entity Framework 6.0 Alpha 3) DataContext, Mappings, Migrations, etc. This give is nice separation, control and isolation of where any persistence related objects live. If ever, one day we need to change the tool of choice, or even upgrade, there’s only one layer or project to do this in, the Data project.

5-8-2013 10-08-26 PM

Entities Project (Domain Layer)
The Entities project is where all of our POCO (Plan Old C# Objects) objects will live. POCO’s should be very ignorant objects that pretty much have nothing in them but the structure of your data. With that being said, typically anything outside our Repository layer e.g. presentation layer (MVC), services layer (will cover in next post) should be completely ignorant to any persistence tool or technology e.g. NHibernate, eXpressPersistent, OpenAccess, EF (our case), etc.

5-8-2013 10-09-31 PM

Repository (Layer)
This is where our UoW (Unit of Work) pattern will be implemented as well as our Repository implementation. Our UoW implementation will handle most of our usual CRUD activities.

Two important objectives we will try to with our UoW pattern implementation are:

  1. Abstract away the ORM tool, in our case EF.
  2. Ensuring that all interactions with the database are happening under one DbContext instance per page request.

Obviously there are many other benefits, such giving us the ability to implement different variations of our UoW, potentially wire up to different types of repositories. For purposes of this article, we’ll stake focus on our two primary objectives, and I’ll cover the other benefits in later posts.

Web Project (Presentation Layer)
This is our presentation layer, for the purposes of the blog, we will use MVC (ASP.NET MVC 4). Again, this project should not have any dependent code on EF assembly, therefore that should not be any references to the EF assembly, it should only reference our Repository project for data access.

Refactoring the NorthwindContext for an Abstracted and Cleaner Implementation

Now that we’ve gone over the solution and it’s projects, let’s do a little bit of refactoring and cleaning up with our EF code.

Data.NorthwindDataContext.cs

Before:


    public class NorthwindContext : DbContext
    {
        static NorthwindContext()
        {
            Database.SetInitializer<NorthwindContext>(null);
        }

        public NorthwindContext()
            : base("Name=NorthwindContext")
        {
        }

        public DbSet Category Categories { get; set; }
        public DbSet CustomerDemographic CustomerDemographics { get; set; }
        public DbSet Customer Customers { get; set; }
        public DbSet Employee Employees { get; set; }
        public DbSet OrderDetail Order_Details { get; set; }
        public DbSet Order Orders { get; set; }
        public DbSet Product Products { get; set; }
        public DbSet Region Regions { get; set; }
        public DbSet Shipper Shippers { get; set; }
        public DbSet Supplier Suppliers { get; set; }
        public DbSet Territory Territories { get; set; }
        public DbSet Invoice Invoices { get; set; }


        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new CategoryMap());
            modelBuilder.Configurations.Add(new CustomerDemographicMap());
            modelBuilder.Configurations.Add(new CustomerMap());
            modelBuilder.Configurations.Add(new EmployeeMap());
            modelBuilder.Configurations.Add(new Order_DetailMap());
            modelBuilder.Configurations.Add(new OrderMap());
            modelBuilder.Configurations.Add(new ProductMap());
            modelBuilder.Configurations.Add(new RegionMap());
            modelBuilder.Configurations.Add(new ShipperMap());
            modelBuilder.Configurations.Add(new SupplierMap());
            modelBuilder.Configurations.Add(new TerritoryMap());
            modelBuilder.Configurations.Add(new InvoiceMap());
        }
    }

After:

     public class NorthwindContext : DbContext, IDbContext
    {
        static NorthwindContext()
        {
            Database.SetInitializer<NorthwindContext>(null);
        }

        public NorthwindContext()
            : base("Name=NorthwindContext")
        {
        }

        public new IDbSet<T> Set<T>() where T : class
        {
            return base.Set<T>();
        }

        public override int SaveChanges()
        {
            this.ApplyStateChanges();
            return base.SaveChanges();
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new CategoryMap());
            modelBuilder.Configurations.Add(new CustomerDemographicMap());
            modelBuilder.Configurations.Add(new CustomerMap());
            modelBuilder.Configurations.Add(new EmployeeMap());
            modelBuilder.Configurations.Add(new Order_DetailMap());
            modelBuilder.Configurations.Add(new OrderMap());
            modelBuilder.Configurations.Add(new ProductMap());
            modelBuilder.Configurations.Add(new RegionMap());
            modelBuilder.Configurations.Add(new ShipperMap());
            modelBuilder.Configurations.Add(new SupplierMap());
            modelBuilder.Configurations.Add(new TerritoryMap());
            modelBuilder.Configurations.Add(new InvoiceMap());
        }
    }

We can see that our DbContext is now much cleaner, and that it implements IDbContext. IDbContext will be the abstraction we will be working with when interacting with it’s concrete implementation, NorthwindContext.

Best Practice, Coding Against Abstractions or Interfaces

Abstractions serve as a nice flexibility point later, allowing us to implement different variations of the abstraction (interface). This will be very useful later when we implement DI (Dependency Injection and IoC (Inverse of Control) patterns. Coding to an abstraction will also help us easily create unit test, allowing us to inject faked or mocked instances as well. If your a bit unclear on how this helps set stage for DI, IoC and Unit Testing, no worries, I’ll cover these topics in the next post.

Data.IDbContext.cs


namespace Data
{
    public interface IDbContext
    {
        IDbSet<T> Set<T>() where T : class;
        int SaveChanges();
        DbEntityEntry Entry(object o);
        void Dispose();
    }
}

Now, let’s take take a look at what’s all in our Repository project, where our generic extensible repositories will reside.

5-10-2013 7-02-10 PM

IUnitOfWork This is simply the contract or abstraction that we will be working with, when interacting with it’s concrete implementation which will be UnitOfWork object.

Repository.IUnitOfwork.cs



namespace Repository
{
    public interface IUnitOfWork
    {
        void Dispose();
        void Save();
        void Dispose(bool disposing);
        IRepository<T> Repository<T>() where T : class;
    }
}

Concrete Implementation of IUnitOfWork.cs


namespace Repository
{
    public class UnitOfWork : IUnitOfWork
    {
        private readonly IDbContext _context;

        private bool _disposed;
        private Hashtable _repositories;

        public UnitOfWork(IDbContext context)
        {
            _context = context;
        }

        public UnitOfWork()
        {
            _context = new NorthwindContext();
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        public void Save()
        {
            _context.SaveChanges();
        }

        public virtual void Dispose(bool disposing)
        {
            if (!_disposed)
                if (disposing)
                    _context.Dispose();

            _disposed = true;
        }

        public IRepository<T> Repository<T>() where T : class
        {
            if (_repositories == null)
                _repositories = new Hashtable();

            var type = typeof (T).Name;

            if (!_repositories.ContainsKey(type))
            {
                var repositoryType = typeof (Repository<>);

                var repositoryInstance = 
                    Activator.CreateInstance(repositoryType
                            .MakeGenericType(typeof (T)), _context);
                
                _repositories.Add(type, repositoryInstance);
            }

            return (IRepository<T>) _repositories[type];
        }
    }
}

Let’s take a look at our IRepository Repository() method here in our UnitOfWork implementation. Here we are storing all the activated instances of repositories for each and every requests. One there is a request for a given repository we will first check to see if our Hashtable (container to hold all of our activated repository instances) has been created, if not, will go ahead and create our container. Next, we’ll scan our container to see if the requested repository instance has already been created, if it has, then will return it, if it hasn’t, we will activate the requested repository instance, store it in our container, and then return it. If it helps, you can think of this as lazy loading our repository instances, meaning we are only creating repository instances on demand, this allows us to only create the repository instances needed for a given web request. Last but not least, notice here how we are following best practices mentioned earlier, we are not return the concrete implementation for the Repository, but the abstraction, IRepository.

Repository.IRepository.cs


namespace Repository
{
    public interface IRepository<TEntity> where TEntity : class
    {
        TEntity FindById(object id);
        void InsertGraph(TEntity entity);
        void Update(TEntity entity);
        void Delete(object id);
        void Delete(TEntity entity);
        void Insert(TEntity entity);
        RepositoryQuery<TEntity> Query();
    }
}


Repository.Repository.cs


    public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
    {
        internal IDbContext Context;
        internal IDbSet<TEntity> DbSet;

        public Repository(IDbContext context)
        {
            Context = context;
            DbSet = context.Set<TEntity>();
        }

        public virtual TEntity FindById(object id)
        {
            return DbSet.Find(id);
        }

        public virtual void InsertGraph(TEntity entity)
        {
            DbSet.Add(entity);
        }

        public virtual void Update(TEntity entity)
        {
            DbSet.Attach(entity);
        }

        public virtual void Delete(object id)
        {
            var entity = DbSet.Find(id);
            var objectState = entity as IObjectState;
            if (objectState != null) 
                objectState.State = ObjectState.Deleted;
            Delete(entity);
        }

        public virtual void Delete(TEntity entity)
        {
            DbSet.Attach(entity);
            DbSet.Remove(entity);
        }

        public virtual void Insert(TEntity entity)
        {
            DbSet.Attach(entity);
        }

        public virtual RepositoryQuery<TEntity> Query()
        {
            var repositoryGetFluentHelper =
                new RepositoryQuery<TEntity>(this);

            return repositoryGetFluentHelper;
        }

        internal IQueryable<TEntity> Get(
            Expression<Func<TEntity, bool>> filter = null,
            Func<IQueryable<TEntity>,
                IOrderedQueryable<TEntity>> orderBy = null,
            List<Expression<Func<TEntity, object>>>
                includeProperties = null,
            int? page = null,
            int? pageSize = null)
        {
            IQueryable<TEntity> query = DbSet;
            
            if (includeProperties != null)
                includeProperties.ForEach(i => { query = query.Include(i); });

            if (filter != null)
                query = query.Where(filter);

            if (orderBy != null)
                query = orderBy(query);

            if (page != null && pageSize != null)
                query = query
                    .Skip((page.Value - 1)*pageSize.Value)
                    .Take(pageSize.Value);

            return query;
        }
    }

Our generic implementation for Repository allows us to have have all our basic heavy lifting of a Repository out of the box for any one of our Entities. All we have to do is request for the Repository of interest by passing in the Entity e.g.

UnitOfWork.Repository<Customer>

will give us the Customer Repository with all our out of the box plumbing available.

Let’s take a quick look at our Get method in the Repository implementation.


        internal IEnumerable<TEntity> Get(
            Expression<Func<TEntity, bool>> filter = null,
            Func<IQueryable<TEntity>,
                IOrderedQueryable<TEntity>> orderBy = null,
            List<Expression<Func<TEntity, object>>>
                includeProperties = null,
            int? page = null,
            int? pageSize = null)
        {
            IQueryable<TEntity> query = DbSet;
            
            if (includeProperties != null)
                includeProperties.ForEach(i => query.Include(i));

            if (filter != null)
                query = query.Where(filter);

            if (orderBy != null)
                query = orderBy(query);

            if (page != null && pageSize != null)
                query = query
                    .Skip((page.Value - 1)*pageSize.Value)
                    .Take(pageSize.Value);


            return query.ToList();
        }

The Get method here, handles fetching data. It handles querying the data supporting a filtering, ordering, paging, and eager loading of child types, so that we can make one round trip and eager load the entity graph.

We notice here that the method is marked “internal”, this is because we only want the Get method here to be accessible to objects with the same assembly, Repository.dll. We will expose the Get method via the Query method and return the RepositoryQuery object to provide a fluent “ish” api, so that’s its a bit more easy and intuitive for our developers when querying with our Repository layer. Note, only methods in our RepositoryQuery will actually invoke the internal Get method, again, which is why we went ahead and marked the Get method internal.

Repository.RepositoryQuery.cs (our fluent api helper class)


    public sealed class RepositoryQuery<TEntity> where TEntity : class
    {
        private readonly List<Expression<Func<TEntity, object>>> 
            _includeProperties;

        private readonly Repository<TEntity> _repository;
        private Expression<Func<TEntity, bool>> _filter;
        private Func<IQueryable<TEntity>, 
            IOrderedQueryable<TEntity>> _orderByQuerable;
        private int? _page;
        private int? _pageSize;

        public RepositoryQuery(Repository<TEntity> repository)
        {
            _repository = repository;
            _includeProperties = 
                new List<Expression<Func<TEntity, object>>>();
        }

        public RepositoryQuery<TEntity> Filter(
            Expression<Func<TEntity, bool>> filter)
        {
            _filter = filter;
            return this;
        }

        public RepositoryQuery<TEntity> OrderBy(
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy)
        {
            _orderByQuerable = orderBy;
            return this;
        }

        public RepositoryQuery<TEntity> Include(
            Expression<Func<TEntity, object>> expression)
        {
            _includeProperties.Add(expression);
            return this;
        }

        public IEnumerable<TEntity> GetPage(
            int page, int pageSize, out int totalCount)
        {
            _page = page;
            _pageSize = pageSize;
            totalCount = _repository.Get(_filter).Count();

            return _repository.Get(
                _filter, 
                _orderByQuerable, _includeProperties, _page, _pageSize);
        }

        public IEnumerable<TEntity> Get()
        {
            return _repository.Get(
                _filter, 
                _orderByQuerable, _includeProperties, _page, _pageSize);
        }
    }

Addressing IRepository<TEntity> Extensibility

Well, what happens if we need extra methods a specific Repository? Meaning, how do we address “extensiblility” in our Repository? No problem, we have a couple of options here, we can simply inherit a Repository and add your own methods to it, or what I prefer, create extension methods e.g. extending IRepository (with some pseudo code for validating an address with UPS).

Repository.CustomerRepository.cs

    /// <summary>
    /// Extending the IRepository<Customer>
    /// </summary>
    public static class CustomerRepository
    {
        public static decimal GetCustomerOrderTotalByYear(
            this IRepository<Customer> customerRepository, 
            int customerId, int year)
        {
            return customerRepository
                .FindById(customerId)
                .Orders.SelectMany(o => o.OrderDetails)
                .Select(o => o.Quantity*o.UnitPrice).Sum();
        }

    /// <summary>
    /// TODO:
    /// This should really live in the Services project (Business Layer), 
    /// however, we'll leave it here for now as an example, and migrate
    /// this in the next post.
    /// </summary>
        public static void AddCustomerWithAddressValidation(
            this IRepository<Customer> customerRepository, Customer customer)
        {
            USPSManager m = new USPSManager("YOUR_USER_ID", true);
            Address a = new Address();
            a.Address1 = customer.Address;
            a.City = customer.City;

            Address validatedAddress = m.ValidateAddress(a);

            if (validatedAddress != null)
            customerRepository.InsertGraph(customer);
        }
    }

Great, now that we have our project nicely structured with the our generic implementation of the Unit of Work and Repository Pattern, let’s see how we can leverage this by wiring up a simple controller to show a list of customers.

To help us with this go ahead and NuGet the PagedList for MVC so we easily create a view with a paged grid.

5-10-2013 6-22-37 PM

Let’s create a CustomerController Index Action load a paged list of customers to hydrate a grid.


    public class CustomerController : Controller
    {
        public ActionResult Index(int? page)
        {
            var pageNumber = page ?? 1;
            const int pageSize = 20;

            var unitOfWork = new UnitOfWork();

            int totalCustomerCount;

            var customers =
                unitOfWork.Repository<Customer>()
                    .Query()
                    .Include(i => i.CustomerDemographics)
                    .OrderBy(q => q
                        .OrderBy(c => c.ContactName)
                        .ThenBy(c => c.CompanyName))
                    .Filter(q => q.ContactName != null)
                    .GetPage(pageNumber, pageSize, out totalCustomerCount);

            ViewBag.Customers = new StaticPagedList<Customer>(
                customers, pageNumber, pageSize, totalCustomerCount);

            unitOfWork.Save();

            return View();
        }
    }

Next, let’s wire up the Index.cshtml view for our CustomerController Index Action.


@{
    ViewBag.Title = "Customers";
}

@using PagedList.Mvc;
@using PagedList;

<h2>Customers</h2>

<link href="/Content/PagedList.css" rel="stylesheet" type="text/css" />

<h2>List of Customers</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table style="width: 100%; padding: 10px;">
    <tr style="background-color: lightgray; padding: 10px;">
        <th>#</th>
        <th>Company
        </th>
        <th>Name
        </th>
        <th>Title
        </th>
        <th>Order Date
        </th>
    </tr>

    @foreach (var item in ViewBag.Customers)
    {
        <tr>
            <td>
                @Html.ActionLink(
                    "Edit", "Edit", new { id = item.CustomerID }) |

                @Html.ActionLink(
                    "Details", "Details", new { id = item.CustomerID }) |

                @Html.ActionLink(
                    "Delete", "Delete", new { id = item.CustomerID })
            </td>
            <td>
                @item.CompanyName
            </td>
            <td>
                @item.ContactName
            </td>
            <td>
                @item.ContactTitle
            </td>
            <td>
                @if (item.Orders.Count > 1)
                {
                    @item.Orders[1].OrderDate.ToShortDateString()
                }
            </td>
        </tr>
    }


    <tr>
        <td colspan="9">
            @Html.PagedListPager(
                (IPagedList)ViewBag.Customers, page => 
                    Url.Action("Index", new { page }))
        </td>
    </tr>

</table>


Go ahead and run our project to see our paged customers grid.

5-10-2013 6-46-30 PM

Abstracting the Complexity when Dealing with Entity Graphs

Another item I wanted to go over was insert and updating graphs with our Repository pattern. There are four use cases for inserting graphs, they are as follows.

5-10-2013 7-34-28 PM

To abstract the complexity and EF experience required, and how the DbContext manages graphs e.g to know to set the root entity state and how it affects other entities in the graph (e.g. updating the root entity in the graph, and existing entities in the graph are to be updated or deleted) we added a interface IOjectState that all of our entities will implement.

Entities.IObjectState.cs


namespace Data
{
    public interface IObjectState
    {
        ObjectState State { get; set; }
    }
}

Entities.ObjectState.cs (enum)


namespace Data
{
    public enum ObjectState
    {
        Unchanged,
        Added,
        Modified,
        Deleted
    }
}

These two classes will allow our development team to explicitly set the state of each of the entities in the graph when inserting or updating a graph. To make use of the classes we’ll need to extend the DbContext with a few methods, we’ll do this by creating extension methods.

Data.DbContextExtension.cs


    public static class DbContextExtension
    {
        public static void ApplyStateChanges(this DbContext dbContext)
        {
            foreach (var dbEntityEntry in dbContext.ChangeTracker.Entries())
            {
                var entityState = dbEntityEntry.Entity as IObjectState;
                if (entityState == null)
                    throw new InvalidCastException(
                        "All entites must implement " +
                        "the IObjectState interface, this interface " +
                        "must be implemented so each entites state" +
                        "can explicitely determined when updating graphs.");

                dbEntityEntry.State = ConvertState(entityState.State);
            }
        }

        private static EntityState ConvertState(ObjectState state)
        {
            switch (state)
            {
                case ObjectState.Added:
                    return EntityState.Added;
                case ObjectState.Modified:
                    return EntityState.Modified;
                case ObjectState.Deleted:
                    return EntityState.Deleted;
                default:
                    return EntityState.Unchanged;
            }
        }
    }

Now we will override the SaveChanges in our NorthwindContext to invoke the ApplyStateChanges method to synchronize our ObjectSate with EF’s EntityState, so that the context will know how to deal with each and every entity when dealing with entity graphs.

Data.NorthwindContext.SaveChanges()


        public override int SaveChanges()
        {
            this.ApplyStateChanges();
            return base.SaveChanges();
        }


Now when inserting, updating you can explicitly set the entities state, especially useful when dealing with graphs. This abstracts the skill-set of a developer using our Repository of having to know the what, when and how to set the state of entities in the graph in order for the context to update the graph and persist the graph correctly. Let’s take a look at an example of updating an existing Order and adding an OrderDetail item with an entity graph. Both these actions, are will be executed on the same graph, however notice that the action is different for both of the entity’s, one is updating and the other is adding, however we will only be invoking one method (IRepository.Update(TEntity entity) from our IRepository in one transaction.

So we’ll demonstrate and prove out updating an entity graph with our UnitOfWork implementation in these steps.

Code Snippet from LinqPad, notice how we are explicitly setting each of the entities state in the entity graph.


var unitOfWork = new UnitOfWork(this);

var orderId = 10253;

unitOfWork
	.Repository<Order>()
	.Query()
	.Include(t => t.Customer)
	.Filter(t=> t.OrderID == orderId)
	.Get().Dump();

var order = unitOfWork
	.Repository<Order>()
	.FindById(orderId);

unitOfWork
	.Repository<OrderDetail>()
	.Query()
	.Filter(t => t.OrderID == orderId)
	.Get().Dump();

order.ShipName = "Long Le";
order.State = ObjectState.Modified;

order.OrderDetails.Add(
	new OrderDetail{
		ProductID = 2,
		UnitPrice = 10,
		Quantity = 2,
		Discount = 1,
		State = ObjectState.Added
	}
);


unitOfWork.Repository<Order>()
	.Update(order);

unitOfWork.Save();

new UnitOfWork(this)
	.Repository<Order>()
	.Query()
	.Include(t => t.Customer)
	.Filter(t => t.OrderID == orderId)
	.Get().Dump();
	
new UnitOfWork(this)
	.Repository<OrderDetail>()
	.Query()
	.Filter(t => t.OrderID == orderId)
	.Get().Dump();
		

Entity Graph Update Scenario

  1. Query the Order table, make note of the ShipName value.
  2. Query the OrderDetail table, make not there are only three (3) items, that belong to the same Order.
  3. Update the ShipName value in the Order.
  4. Add an OrderDetail to the Order.

5-11-2013 4-13-23 PM

(click image to enlarge)

Presto, we were able to successfully update an existing Order and add a new OrderDetail via an entity graph with one transaction using one method. Now, we can absolutely do this using EF out of the box, however, our goal here is was to abstract the complexity and skill set required from a developer in regards to EF specially how do deal with the DbContext in order to make this happen as well as obviously still support working with graphs through our IRepository implementation.

There you have it, and extensible genericized implementation of the UoW and Repository pattern with EF in MVC. In the next blog post, we’ll add DI & IoC to this solution and introduce the Services layer, this layer will house all of our business logic and rules. We will also implement the Services layer in a way, where we don’t violate our Unit of Work pattern, meaning all the work done in our Repository and Services are executed under one single instance the DbContext per page request.

Happy Coding..! 🙂

Download sample: https://genericunitofworkandrepositories.codeplex.com

Developing with Twilio Cloud Communication using MVC 4, WebApi and UriPathExtensionMapping Configurations

Twilio has some pretty good documentation on developing with MVC using your traditional Controllers, Actions, and Views leveraging their REST Api’s. However this post will be for those that would like to develop around Twilio this using MVC’s new WebApi.

There are typically no Views being used when working with Twilio’s Platform (unless you are placing in-line code in your View’s markup), it’s largely a lot of REST like request’s that Twilio makes to your application and your application is responding with XML payloads, so that Twilio can injest your Xml payload and figure out what the next step is, whether it be a voice and/or SMS request.

So let’s get into it, the first thing we do is to get our MVC 4 app infrastructure ready.

In Global.asax.cs, let’s add some Uri path extensions, meaning our WebApi methods will know what type of content/type to deliver back from a request by the extension of the Url. For example if we have a inbound request for a collection of some sort mapped to http://localhost/api/MyController/MyPost.xml, the MVC runtime will know to return my collection in Xml vs. Json (MediaTypeFormatterExtensions.AddUriPathExtensionMapping).


    public class WebApiApplication : HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            MefConfig.RegisterMef();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            FilterConfig.RegisterHttpFilters(GlobalConfiguration.Configuration.Filters);
            MapperConfig.RegisterMappings();

            GlobalConfiguration
                .Configuration
                .Formatters
                .XmlFormatter
                .AddUriPathExtensionMapping("xml", "text/xml");

            GlobalConfiguration
                .Configuration
                .Formatters
                .XmlFormatter
                .AddUriPathExtensionMapping("json", "application/json");
        }
    }

Note: Technically, we only need the UriPathExtensionMapping for Xml, however just in case we ever decided to still want to serve up Json payloads from our WebApi methods we will go ahead and add one for Json as well. That way our Api methods can return either Xml or Json just by changing the extension on the url.

For example:

Update and/or add a WebApi route (in this case I’ll just replace the one that’s there since I don’t need the default route at all) so that we can support our added UriPathExtensionMappings we added earlier (.xml, .json).

Location: YourMvc4Project/App_Start/WebApiConfig.cs


    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: "Api with action and extension ",
                routeTemplate: "api/{controller}/{action}.{ext}/{id}",
                defaults: new {
                    id = RouteParameter.Optional, 
                    ext = RouteParameter.Optional}
                );

            //config.Routes.MapHttpRoute(
            //    name: "DefaultApi",
            //    routeTemplate: "api/{controller}/{id}",
            //    defaults: new {id = RouteParameter.Optional}
            //    );
        }
    }


Now we can build a fictitious example of a Weather WebApi controller for Twilio to make requests to.

  • GatherZipCode method, will prompt a a voice caller for what zip code the caller is interested for weather information.
  • RetrieveWeather method, will actually read and speak the weather condition to the voice caller, obviously this is a an example and you would probably need to hit a real weather service such as Accuweather for real world purposes.
  • I prefer implementing it this way, because at the end of the day you end up with just small methods that handle responses to Twilio requests, and we get to use the TwilioResponse object to give us some assistance in what we are trying to send back to Twilio. With this being said we don’t have to worry about stringing together Xml string(s) in our code, the TwilioReponse object has a handy property named Element (twilioResponse.Element) that handles nice serialization for us, and provding a representation of of the object in Xml that is Twilio ready for us to send back.

     
    
        public class WeatherController : ApiController
        {
            public HttpResponseMessage GatherZipCode(TwilioRequest twilioRequest)
            {
                var twilioResponse = new TwilioResponse();
    
                twilioResponse.BeginGather(
                    new 
                    {
                        action = "http://myapp.com/api/Weather/RetrieveWeather.xml", 
                        finishOnKey = "#"
                    });
    
                twilioResponse.Say(
                    "Please enter the zip code of the area you would like the weather in.", 
                    new {voice = "woman"});
    
                twilioResponse.EndGather();
    
                return Request.CreateResponse(HttpStatusCode.OK, twilioResponse.Element);
            }
    
            public HttpResponseMessage RetrieveWeather(TwilioRequest twilioRequest)
            {
                var zipcode = twilioRequest.Digits;
    
                var zipWeather = new Dictionary<string, string>
                    {
                        {"75042", "sunny"},
                        {"75043", "rainy"},
                        {"75044", "windy"},
                        {"75045", "thunder storms"}
                    };
    
                var twilioResponse = new TwilioResponse();
    
                twilioResponse.Say(
                    string.Format(
                        "The weather conditions in your zip code is {0}", 
                        zipWeather[zipcode]), new {voice = "woman"});
    
                return Request.CreateResponse(HttpStatusCode.OK, twilioResponse.Element);
            }
        }
    

    Great, now how can we do some level of testing with our Twilio ready WebApi’s locally? Meaning let’s do some level of testing before we involve actual people and their actual phones and/or Skype accounts.

    You will need to download the Curl utility (http://curl.haxx.se/download.html).

    Run your application, and issue a couple of command to invoke your new WebApi methods and make sure they are returning the correct Xml payloads to Twilio, you can cross reference your Xml payloads with Twilio TwiML Referenence (http://www.twilio.com/docs/api/twiml).

    Go ahead and spin up command prompt and navigate to the Curl command line utility, now let’s run a couple of commands to inspect the Xml payloads we are expecting to return to Twilio.

    curl http://localhost:64190/api/weather/gatherzipcode.xml -X POST

    Now when we execute this command we get:

    
    <Response><Gather action="http://myapp.com/api/Weather/RetrieveWeather.xml" finishOnKey="#"><Say voice="woman">Please en
    ter the zip code of the area you would like the weather in.</Say></Gather></Response>
    
    

    Now we can cross reference and compare it with when reviewing the “Say” verb from Twilio TwiML docs on how to use the “Say” verb (http://www.twilio.com/docs/api/twiml/say) to get some level of comfort that we are returning the right Xml payloads from our WebApi methods before actually getting people and phones in the picture.

    The next step, if your developing locally, and if you are developing on a workstation that is not publicy exposed to the internet, an option for you could be leveraging Windows Azure Service Bus for it’s relaying features. The Windows Azure Service Bus relaying pattern is pretty much the same pattern used for services that are in cloud that need to work with services that are on-premise that are deep inside a company’s infrastructure behind their firewall.

    You can visit Devin’s blog http://www.twilio.com/blog/2012/06/relaying-twilio-requests-using-windows-azure.html to set up relaying with Windows Azure Service Bus for Twilio development.

Multi-Step (Two-Factor) ASP.NET MVC 4 Registration with SMS using Twilio Cloud Communication and SimpleMembershipProvider for Increased User Validity

Some sites such as live.com, gmail.com will require a multi-step registration and/or forgot password workflows to validate you say you are. Having an opportunity working with the Twilio Cloud Communication Platform, exposed how easily this can be done with their Api’s.

So for this post, I wanted to illustrate the steps in getting your MVC 4 application wired up with multi-step registration process with SMS code verification leveraging Twilio. We will start from my last blog post with Seed Users and Roles with MVC 4, SimpleMembershipProvider, SimpleRoleProvider, EntityFramework 5 CodeFirst, and Custom User Properties.

Since we already gathered the user’s mobile number during registration, let’s go ahead and add a property/field “IsSmsVerified” and run EntityFramework’s migration command update-database -verbose (so we can see what commands are being issued to our database for the migration.

NuGet and install the Twilio.Mvc package.

Update our UserProfile entity with IsSmsVerified and SmsVerificationCode properties.


    [Table("UserProfile")]
    public class UserProfile
    {
        public UserProfile()
        {
            IsSmsVerified = false;
        }

        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int UserId { get; set; }
        public string UserName { get; set; }
        public string Mobile { get; set; }
        [DefaultValue(false)]
        public bool IsSmsVerified { get; set; }
        public string SmsVerificationCode { get; set; }
    }

Update our Seed method so that we are not inserting nulls for the provisioned users.


#region

using System.Data.Entity.Migrations;
using System.Linq;
using System.Web.Security;
using MVC4SimpleMembershipCodeFirstSeedingEF5.Models;
using WebMatrix.WebData;

#endregion

namespace MVC4SimpleMembershipCodeFirstSeedingEF5.Migrations
{
    internal sealed class Configuration : DbMigrationsConfiguration<UsersContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = true;
        }

        protected override void Seed(UsersContext context)
        {
            WebSecurity.InitializeDatabaseConnection(
                "DefaultConnection",
                "UserProfile",
                "UserId",
                "UserName", autoCreateTables: true);

            if (!Roles.RoleExists("Administrator"))
                Roles.CreateRole("Administrator");

            if (!WebSecurity.UserExists("lelong37"))
                WebSecurity.CreateUserAndAccount(
                    "lelong37",
                    "password",
                    new {Mobile = "+19725000374", IsSmsVerified = false});

            if (!Roles.GetRolesForUser("lelong37").Contains("Administrator"))
                Roles.AddUsersToRoles(new[] {"lelong37"}, new[] {"Administrator"});
        }
    }
}

Run: update-database -verbose from the Package Manager Console

Now the fun begins, let’s update our AccountController.

  • Update the Register(RegisterModel model) Action and introduce the second step registration process of entering an SMS verfication code that we send the user using Twilio’s REST Api Client.

    Note: We are just scratching the tip of the ice berg in terms of what the Twilio Cloud Communication offers, you can visit their docs site for more info.

  • Add SmsVerification() Action, so that the user can enter the SMS verification code.
  • Add SmsVerication(SmsVerificationModel smsVerificationModel) Action, so that we can validate the user, the user’s mobile number, and SMS verification code.
  • Add GenerateSimpleSmsVerificationCode() method, a simple static helper method to generate a six character SMS verification code.

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult Register(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                try
                {
                    var smsVerificationCode =
                        GenerateSimpleSmsVerificationCode();

                    WebSecurity.CreateUserAndAccount(
                        model.UserName,
                        model.Password,
                        new
                            {
                                model.Mobile,
                                IsSmsVerified = false,
                                SmsVerificationCode = smsVerificationCode
                            },
                        false);

                    var twilioRestClient = new TwilioRestClient(
                        ConfigurationManager.AppSettings.Get("Twilio:AccoundSid"),
                        ConfigurationManager.AppSettings.Get("Twilio:AuthToken"));

                    twilioRestClient.SendSmsMessage(
                        "+19722001298",
                        model.Mobile,
                        string.Format(
                            "Your ASP.NET MVC 4 with Twilio " +
                            "registration verification code is: {0}",
                            smsVerificationCode)
                        );

                    Session["registrationModel"] = model;

                    return RedirectToAction("SmsVerification", "Account");
                }
                catch (MembershipCreateUserException e)
                {
                    ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        [AllowAnonymous]
        public ActionResult SmsVerification()
        {
            return View(new SmsVerificationModel
                {
                    Username =
                        ((RegisterModel) Session["registrationModel"])
                            .UserName
                });
        }

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult SmsVerification(SmsVerificationModel smsVerificationModel)
        {
            if (ModelState.IsValid)
            {
                var userContext = new UsersContext();

                var userProfile = userContext.UserProfiles
                    .Single(u => u.UserName == smsVerificationModel.Username);

                var registerModel = ((RegisterModel) Session["registrationModel"]);

                if (userProfile.SmsVerificationCode == smsVerificationModel.SmsVerificationCode)
                {
                    WebSecurity.Login(userProfile.UserName, registerModel.Password);
                    return RedirectToAction("Index", "Home");
                }
            }

            ModelState.AddModelError("", "The SMS verfication code was incorrect.");
            return RedirectToAction("SmsVerification", "Account");
        }

        private static string GenerateSimpleSmsVerificationCode()
        {
            const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            var random = new Random();
            return new string(
                Enumerable.Repeat(chars, 6)
                    .Select(s => s[random.Next(s.Length)])
                    .ToArray());
        }

We could combine the two actions SmsVerication() and SmsVerication(SmsVerificationModel smsVerificationModel) into one, by checking the request verb for GET or Post, however for separation of concerns we will keep them “nice” and “separate”.

Let’s add some AppSettings entries to store our Twilio Rest Api credentials.


  <appSettings>
    <add key="webpages:Version" value="2.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="PreserveLoginUrl" value="true" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
    <add key="Twilio:AccoundSid" value="youtwilioaccountid" />
    <add key="Twilio:AuthToken" value="yourtwilioauthtoken" />
  </appSettings>

Note: Your Twilio credentials for using their REST Api can be found on your dashboard after registering.

Create a SmsVerification ViewModel.


using System.ComponentModel.DataAnnotations;

using System.ComponentModel.DataAnnotations;

namespace MVC4SimpleMembershipCodeFirstSeedingEF5.Models
{
    public class SmsVerificationModel
    {
        [Display(Name = "Username")]
        public string Username { get; set; }

        [Required]
        [Display(Name = "SMS Verification Code")]
        public string SmsVerificationCode { get; set; }
    }
}

Let’s create the SmsVerification View where a user can input the SMS verification code that we sent to the user bound to the ViewModel we just created.

@model MVC4SimpleMembershipCodeFirstSeedingEF5.Models.SmsVerificationModel
@{
    //ViewBag.Title = "SMS Verification with MVC 4 & Twilio";
    ViewBag.Title = "SmsVerification";
}

<hgroup class="title">
    <h1>@ViewBag.Title.<br/></h1>
    <h3>Please enter your SMS verification code to complete registration.</h3>
</hgroup>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary()

    @Html.HiddenFor(m => m.Username)

    <fieldset>
        <legend>SMS Verifcation Form</legend>
        <ol>
            <li>
                @Html.LabelFor(m => m.Username)
                @Html.DisplayTextFor(m => m.Username) 
                <br/><br/>
            </li>
            <li>
                @Html.LabelFor(m => m.SmsVerificationCode)
                @Html.TextBoxFor(m => m.SmsVerificationCode)
            </li>
        </ol>
        <input type="submit" value="SmsVerification" />
    </fieldset>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Step 1 of the registration process, run the application and register.

For a quick sanity check let’s just make sure our SimpleMembershipProvider is persisting the extra properties we added earlier e.g. SmsVerificationCode, IsSmsVerified.


SELECT TOP 1000 [UserId]
      ,[UserName]
      ,[Mobile]
      ,[IsSmsVerified]
      ,[SmsVerificationCode]
  FROM [aspnet-MVC4SimpleMembershipCodeFirstSeedingEF5].[dbo].[UserProfile]

Good, we can see here that Mobile, IsSmsVerified and SmsVerificationCode is being saved when we invoked the WebSecurity.CreateUserAndAccount method earlier from our Registration Action.


                    WebSecurity.CreateUserAndAccount(
                        model.UserName,
                        model.Password,
                        new
                            {
                                model.Mobile,
                                IsSmsVerified = false,
                                SmsVerificationCode = smsVerificationCode
                            },
                        false);

Step 2, SMS notification to the user’s mobile number was received with the SMS verification code.

Step 3 of the registration process, input the SMS verification code in the SMSVerfication View.

You have now successfully completed the 3 step registration process and have been automatically logged into the site!

Now there are obviously TODO’s here, you can create an new authorize Attribute to verify that the IsSmsVerified property for the user is not false, clean up how we are storing the RegisterModel in session, additional bullet proofing the app in terms of security gaps, etc.. However the emphasis of this blog was multi-step registration to for increased validity of the user.

Last but not least, you can use the a similar implementation for things like forgot password or any other type of workflow that needs that extra degree of validation.

Happy Coding…! 🙂

Download sample application: https://skydrive.live.com/redir?resid=949A1C97C2A17906!2383

Seed Users and Roles with MVC 4, SimpleMembershipProvider, SimpleRoleProvider, Entity Framework 5 CodeFirst, and Custom User Properties

I’ve been Googling over the weekend and so far didn’t find any articles out there on how integrate EF5 CodeFirst nicely with SimpleMembership and at the same time, seeding some of your users, roles and associating users to roles while supporting custom fields/properties during registration, hence this blog post.

I think this is a nice to have, especially during PoC development where you could be developing features that depend on authentication and authorization while making schema changes with EF CodeFirst. The last thing you want to do is run update-database for migrations and have to manually re-insert/re-seed all your users, roles and associating the two every time you ran migrations (e.g. update-database -force from the Package Manager Console).

First, create an “Internet Application” ASP.NET MVC4 Project, because this is the only out of the box MVC template that has the new SimpleMembershipProvider wired up out of the box. One of the features I like the most about the SimpleMembershipProvider is it gives you total control of the highly requested “User” table/entity. Meaning you integrate SimpleMembershipProvider with your own user table, as long as it has a UserId and UserName fields in your table.

Obviously there are many more features in SimpleMembership provider, here are some links in this regard:

Explicitly wire up the providers even though this is implied, so that when do run the “update-database” command from the Package Manager Console for migrations we can use the native “Roles” Api.

In the “System.Web” Section add:


    &lt;roleManager enabled=&quot;true&quot; defaultProvider=&quot;SimpleRoleProvider&quot;&gt;
      &lt;providers&gt;
        &lt;clear/&gt;
        &lt;add name=&quot;SimpleRoleProvider&quot; type=&quot;WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData&quot;/&gt;
      &lt;/providers&gt;
    &lt;/roleManager&gt;
    &lt;membership defaultProvider=&quot;SimpleMembershipProvider&quot;&gt;
      &lt;providers&gt;
        &lt;clear/&gt;
        &lt;add name=&quot;SimpleMembershipProvider&quot; type=&quot;WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData&quot; /&gt;
      &lt;/providers&gt;
    &lt;/membership&gt;

Let’s add a custom field to the User table by adding a Mobile property to the UserProfile entity (MVC4SimpleMembershipCodeFirstSeedingEF5/Models/AccountModel.cs).


    [Table(&quot;UserProfile&quot;)]
    public class UserProfile
    {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int UserId { get; set; }
        public string UserName { get; set; }
        public string Mobile { get; set; }
    }

Enable EF5 CodeFirst Migrations

Seed your Roles and any Users you want to provision, also note the WebSecurity.InitializeDatabaseConnection method we are invoking. This method is what tells SimpleMembership which table to use when working with Users and which columns are for the UserId and UserName. I’m also going to demonstrate how you can hydrate additional custom columns such as requiring a User’s mobile number when registering on the site.


#region

using System.Data.Entity.Migrations;
using System.Linq;
using System.Web.Security;
using MVC4SimpleMembershipCodeFirstSeedingEF5.Models;
using WebMatrix.WebData;

#endregion

namespace MVC4SimpleMembershipCodeFirstSeedingEF5.Migrations
{
    internal sealed class Configuration : DbMigrationsConfiguration&lt;UsersContext&gt;
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = true;
        }

        protected override void Seed(UsersContext context)
        {
            WebSecurity.InitializeDatabaseConnection(
                &quot;DefaultConnection&quot;,
                &quot;UserProfile&quot;,
                &quot;UserId&quot;,
                &quot;UserName&quot;, autoCreateTables: true);

            if (!Roles.RoleExists(&quot;Administrator&quot;))
                Roles.CreateRole(&quot;Administrator&quot;);

            if (!WebSecurity.UserExists(&quot;lelong37&quot;))
                WebSecurity.CreateUserAndAccount(
                    &quot;lelong37&quot;,
                    &quot;password&quot;,
                    new {Mobile = &quot;+19725000000&quot;});

            if (!Roles.GetRolesForUser(&quot;lelong37&quot;).Contains(&quot;Administrator&quot;))
                Roles.AddUsersToRoles(new[] {&quot;lelong37&quot;}, new[] {&quot;Administrator&quot;});
        }
    }
}

Now, run the update-database -verbose command from Package Manager Console, we are using the -verbose switch so that we can get better visibility on what’s getting executed on SQL. Notice the Mobile field is being created.

Let’s go ahead and do a sanity check and make sure all of our Users and Roles were provisioned correctly from the Seed method in our migration configuration, by executing a few queries.


SELECT TOP 1000 [UserId]
      ,[UserName]
      ,[Mobile]
  FROM [aspnet-MVC4SimpleMembershipCodeFirstSeedingEF5].[dbo].[UserProfile]
  
  SELECT TOP 1000 [RoleId]
      ,[RoleName]
  FROM [aspnet-MVC4SimpleMembershipCodeFirstSeedingEF5].[dbo].[webpages_Roles]
  
  SELECT TOP 1000 [UserId]
      ,[RoleId]
  FROM [aspnet-MVC4SimpleMembershipCodeFirstSeedingEF5].[dbo].[webpages_UsersInRoles]

Results

  • Users were inserted
  • Roles were provisioned
  • The user “LeLong37” was added and associated to the Administrator role

Finally for a sanity check, let’s go ahead and run the app and sign-in with the provisioned user from our Seed method.

Successfully authenticated with our seeded provisioned user (thought I’d add a blue star badge to the screenshot to add some humor 😛 )!

One last thing, let’s go ahead and modify our Register view, Register model and AccountController to gather the user’s mobile number during registration.

Register View (Register.cshtml)


@model MVC4SimpleMembershipCodeFirstSeedingEF5.Models.RegisterModel
@{
    ViewBag.Title = &quot;Register&quot;;
}

&lt;hgroup class=&quot;title&quot;&gt;
    &lt;h1&gt;@ViewBag.Title.&lt;/h1&gt;
    &lt;h2&gt;Create a new account.&lt;/h2&gt;
&lt;/hgroup&gt;

@using (Html.BeginForm()) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary()

    &lt;fieldset&gt;
        &lt;legend&gt;Registration Form&lt;/legend&gt;
        &lt;ol&gt;
            &lt;li&gt;
                @Html.LabelFor(m =&gt; m.UserName)
                @Html.TextBoxFor(m =&gt; m.UserName)
            &lt;/li&gt;
            &lt;li&gt;
                @Html.LabelFor(m =&gt; m.Password)
                @Html.PasswordFor(m =&gt; m.Password)
            &lt;/li&gt;
            &lt;li&gt;
                @Html.LabelFor(m =&gt; m.ConfirmPassword)
                @Html.PasswordFor(m =&gt; m.ConfirmPassword)
            &lt;/li&gt;
            &lt;li&gt;
                @Html.LabelFor(m =&gt; m.Mobile)
                @Html.TextBoxFor(m =&gt; m.Mobile)
            &lt;/li&gt;
        &lt;/ol&gt;
        &lt;input type=&quot;submit&quot; value=&quot;Register&quot; /&gt;
    &lt;/fieldset&gt;
}

@section Scripts {
    @Scripts.Render(&quot;~/bundles/jqueryval&quot;)
}


Register model (AccountModel.cs)


    public class RegisterModel
    {
        [Required]
        [Display(Name = &quot;User name&quot;)]
        public string UserName { get; set; }

        [Required]
        [StringLength(100, ErrorMessage = &quot;The {0} must be at least {2} characters long.&quot;, MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = &quot;Password&quot;)]
        public string Password { get; set; }

        [DataType(DataType.Password)]
        [Display(Name = &quot;Confirm password&quot;)]
        [Compare(&quot;Password&quot;, ErrorMessage = &quot;The password and confirmation password do not match.&quot;)]
        public string ConfirmPassword { get; set; }

        [Required]
        [DataType(DataType.PhoneNumber)]
        [Display(Name = &quot;Mobile&quot;)]
        public string Mobile { get; set; }
    }


Register Action (AccountController.cs)


        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult Register(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                try
                {
                    WebSecurity.CreateUserAndAccount(
                        model.UserName, 
                        model.Password, 
                        new { Mobile = model.Mobile }, 
                        false);

                    WebSecurity.Login(model.UserName, model.Password);
                    return RedirectToAction(&quot;Index&quot;, &quot;Home&quot;);
                }
                catch (MembershipCreateUserException e)
                {
                    ModelState.AddModelError(&quot;&quot;, ErrorCodeToString(e.StatusCode));
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

Finally, let’s register.

Let’s go ahead and run our SQL queries again and make sure the mobile number was actually saved to our UserProfile table during the registration.

Sweet! Registration successful, with mobile number saved to the UserProfile table.

Happy Coding…!

Download Sample Application: http://blog.longle.net/2012/09/26/multi-step-asp-net-mvc-4-registration-with-sms-using-twilio-cloud-communication-and-simplemembershipprovider-for-increased-user-validity/

Declaritively and Programitcally Subscribing to the Windows Azure Service Bus Relay with WCF

Preferably I like to have most of the configuration for WCF in my config file(s), however when PoC’ing and time is of essence, spending time troubleshooting your config file(s) can be frustrating, for example:

Web.config ‘TransportClientEndPointBehavior‘ element is not recognized when trying to configure your service/application to wire up to Windows Azure Service Bus so that you can push messages on to it, so that you can start relaying.

Error squiggly (message):

“The element ‘behavior’ has invalid child element ‘transportClientEndpointBehavior’. List of possible elements expected: ‘clientVia, callbackDebug, callbackTimeouts, clear, clientCredentials, transactedBatching, dataContractSerializer, dispatcherSyncronization, remove, synchronousRecieve, enableWebScript, webHttp, endpointDiscovery, soapProcessing’.”

Spent some time Googling and regretfully didn’t find any documentation out there on how subscribe to Windows Azure Service Bus 100% programitcally, so hence this blog post. So, let’s get started on how to wire up to Azure’s Service Bus with both approaches.

If you need to know how to setup the Windows Azure Service Bus in the Azure Portal please read https://www.windowsazure.com/en-us/develop/net/how-to-guides/service-bus-relay/.

First, let’s review how to push messages onto the Windows Azure Service Bus for relaying.

Programitically (zero configuration in your .config file)

  • Create an interface that implements IAzureTunnelService, IClientChannel.

    
        public interface IAzureTunnelServiceChannel : IAzureTunnelService, IClientChannel
        {
        }
    
    
  • Wire up to push messages on Windows Azure Service Bus for relay.

    
                var serviceUri = ServiceBusEnvironment
                    .CreateServiceUri("sb", "yournamespace", "relaystatus");
    
                var sharedSecretServiceBusCredential = new TransportClientEndpointBehavior();
    
                var tokenProvider = TokenProvider
                    .CreateSharedSecretTokenProvider("owner", "secretkey");
    
                sharedSecretServiceBusCredential.TokenProvider = tokenProvider;
    
                var endpoint = new ServiceEndpoint(
                    ContractDescription.GetContract(typeof(IAzureTunnelService)),
                    new NetTcpRelayBinding(
                        EndToEndSecurityMode.Transport, 
                        RelayClientAuthenticationType.None),
                        new EndpointAddress(serviceUri));
    
                var channelFactory = new ChannelFactory<IAzureTunnelService>(endpoint);
                channelFactory.Endpoint.Behaviors.Add(sharedSecretServiceBusCredential);
                var channel = channelFactory.CreateChannel();
                var result = channel.RelayRequest(yourmodel);
    
    

Declaritively

  • web.config/app.config (system.serviceModel section)

    In the config we are introducing all known service bus extensions. You can remove the ones you don’t need.

    
      <system.serviceModel>
        <client>
          <endpoint name="relayrequest" contract="YourNameSpace.AzureTunnel.Common.Contracts.IAzureTunnelService" binding="netTcpRelayBinding" address="sb://yourSBnamespace.servicebus.windows.net/relayrequest" behaviorConfiguration="sbTokenProvider" />
        </client>
        <behaviors>
          <endpointBehaviors>
            <behavior name="sbTokenProvider">
              <transportClientEndpointBehavior>
                <tokenProvider>
                  <sharedSecret issuerName="owner" issuerSecret="yoursecretykeygoeshere" />
                </tokenProvider>
              </transportClientEndpointBehavior>
            </behavior>
          </endpointBehaviors>
        </behaviors>
        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
        <extensions>
          <!-- In this extension section we are introducing all known service bus extensions. User can remove the ones they don't need. -->
          <behaviorExtensions>
            <add name="connectionStatusBehavior" type="Microsoft.ServiceBus.Configuration.ConnectionStatusElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="transportClientEndpointBehavior" type="Microsoft.ServiceBus.Configuration.TransportClientEndpointBehaviorElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="serviceRegistrySettings" type="Microsoft.ServiceBus.Configuration.ServiceRegistrySettingsElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
          </behaviorExtensions>
          <bindingElementExtensions>
            <add name="netMessagingTransport" type="Microsoft.ServiceBus.Messaging.Configuration.NetMessagingTransportExtensionElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="tcpRelayTransport" type="Microsoft.ServiceBus.Configuration.TcpRelayTransportElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="httpRelayTransport" type="Microsoft.ServiceBus.Configuration.HttpRelayTransportElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="httpsRelayTransport" type="Microsoft.ServiceBus.Configuration.HttpsRelayTransportElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="onewayRelayTransport" type="Microsoft.ServiceBus.Configuration.RelayedOnewayTransportElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
          </bindingElementExtensions>
          <bindingExtensions>
            <add name="basicHttpRelayBinding" type="Microsoft.ServiceBus.Configuration.BasicHttpRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="webHttpRelayBinding" type="Microsoft.ServiceBus.Configuration.WebHttpRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="ws2007HttpRelayBinding" type="Microsoft.ServiceBus.Configuration.WS2007HttpRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="netTcpRelayBinding" type="Microsoft.ServiceBus.Configuration.NetTcpRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="netOnewayRelayBinding" type="Microsoft.ServiceBus.Configuration.NetOnewayRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="netEventRelayBinding" type="Microsoft.ServiceBus.Configuration.NetEventRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="netMessagingBinding" type="Microsoft.ServiceBus.Messaging.Configuration.NetMessagingBindingCollectionElement, Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
          </bindingExtensions>
        </extensions>
      </system.serviceModel>
    
    
  • C# Code

    
                var channelFactory = new ChannelFactory<IAzureTunnelServiceChannel>("relayrequest");
                using (var channel = channelFactory.CreateChannel())
                {
                    return channel.RelayRequest(url, myModel);
                }
    
    

Note: To shortcut some of this configuration you can add the appropriate references and config configurations by using NuGet and installing the Windows Azure Service Bus package.


Finally, let’s wire up to receive messages off the Windows Azure Service Bus that we relayed earlier (consumer, demonstrated with a console app) programatically.

  • Service Interface

    
        [ServiceContract(Namespace = "urn:ps")]
        public interface IAzureTunnelService
        {
            [OperationContract]
            XElement RelayRequest(string url, YourModel yourModel);
        }
    
    
  • Service Implementation

    
        public class AzureTunnelService : IAzureTunnelService
        {
            public XElement RelayRequest(string url, YourModel yourModel)
            {
                Console.WriteLine("{0,13}|{1,13}", 
                  yourModel.yourProperty1, 
                  yourModel.yourProperty2);
            }
        }
    
    
  • Host the WCF Service

    
            private static void Main(string[] args)
            {
                var serviceHost = new ServiceHost(typeof (AzureTunnelService));
    
                serviceHost.AddServiceEndpoint(
                    typeof (IAzureTunnelService), 
                    new NetTcpBinding(), "net.tcp://localhost:9385/relayrequest");
    
                serviceHost.AddServiceEndpoint(
                    typeof(IAzureTunnelService), 
                    new NetTcpRelayBinding(),
                    ServiceBusEnvironment
                        .CreateServiceUri("sb", "yourSBnamespace", "relayrequest"))
                        .Behaviors.Add(new TransportClientEndpointBehavior
                            {
                                TokenProvider = TokenProvider
                                    .CreateSharedSecretTokenProvider(
                                        "owner", 
                                        "yoursecretkey"
                                    )
                            });
    
                serviceHost.Open();
                Console.WriteLine("Press ENTER to close.");
                Console.ReadLine();
                serviceHost.Close();
            }
    
    

Yes, we have configuration in code, however push comes to shove, it’s always good to have an alternative solution. Being pragmatic about this, how often are you going to need to change your configuration on how your are communicating with Windows Azure Service Bus anyway?

Happy Coding…! 🙂