Persistence ignorant localization of persisted (incl. POCO) entities

Introduction

When localizing an ASP.NET MVC application three main areas deserve our attention:

  1. The very front-end: this is the generated HTML plus some Javascript, containing hard-coded strings.
  2. The middle tier, or the MVC itself.
  3. The Domain Model, which translates into Data Access Objects (DAO, Entities) and gets persisted into some sort of a storage, most often a SQL database.

Points 1 and 2 fall outside our discussion.

Localizing string contents by utilizing SQL lookup tables is possible, however like some other SQL-related stuff (keys, indices, etc.) falls outside the Domain Model and therefore is often considered as a patch, something artificial, or just PITA.

Making a persistence-ignorant localization is a simple, yet very elegant idea, which completely eliminates the need to alter database schema, or deal with the database in any way.

However, first thing first…

The Problem: say we live in Canada and we need our ASP.NET MVC application translated in two languages—English and French. The application itself was written in the US and therefore is culture-ignorant (to be exact the only culture is the default en-US culture). So, we need en-CA and fr-CA, which replace en-US.

The solution: making localized strings structured (SQL purists would stop reading here…). A serialized of Dictionary<string, string> type is a perfect candidate for our solution. (Yes, I know .NET’s XML serialization has issues when serializing such objects, so, we can choose different XML serializer, or simply use List<Pair<string, string>> paying attention not to have duplicates in the first string, which is quite easy in the case.)

Let’s show this in a simplest possible example. The model is as simple as possible:

public class Thing
{
    public string Name { get; set; }

    public string Description { get; set; }
}

The highlighted line is what we need in both English, and French.

Same data, different views

up-down

What we need on screen is this:

A. English

capture1

B. …and French (pardon me, this is Google translation)capture2

You can see that Name does not change while Description gets updated when culture changes.

(Besides changing contents of Description you can see changes in form labels and static texts. These belong to p.2 above and is not subject to this material.)

down-up

What we need stored in our database (or any other type of persistent storage) is something like this:

<description>
  <item culture="en-CA" value="This is ONE thing."/>
  <item culture="fr-CA" value="Ceci est UNE chose" />
</description>

or

{"en-CA":"This is ONE thing.","fr-CA":"Ceci est UNE chose."}

The Decorator Design Pattern

The Decorator and the Decorated objects share the same structure and, from a certain point of view, they are indistinguishable. Well, this is an exaggeration of course, but for our presentation it looks like a good abstraction.

Above I presented the very simple Thing model, here’s the ThingDecorator:

public class ThingDecorator : Thing
{
    private readonly Thing component;

    public ThingDecorator(Thing component)
    {
        this.component component ?? new Thing();
    }

    public Thing Component => this.component;

    public new string Name
    {
        get { return this.component?.Name; }
        set { this.component.Name = value; }
    }

    public new string Description
    {
        get { return ...; }
        set { this.component.Description = ...; }
    }
}

Nothing special so far. The interesting part is what Description‘s getter and setter do.

The ILocalizer

Implementors of this interface are responsible for “the magic” that happens behind the scenes. Here’s the interface first:

public interface ILocalizer
{
    string GetLocalizedValue(string localizedProperty);

    string SetLocalizedValue(string localizedProperty, string value);

    T Merge<T>(T thisObject, T otherObject) where T : class;
}

Earlier, even in prehistoric days, when XML was ubiquitous and Entity Framework did not exist, I used XML serialization with all the burden it used to carry with it. Still the idea and its implementation proved to be useful.

Now, having the more simple and powerful weapon like JSON , things got even better. Here’s the code of the JsonLocalizer:

public class JsonLocalizer : ILocalizer
{
    public string GetLocalizedValue(string localizedProperty)
    {
        var culture = Thread.CurrentThread.CurrentCulture; // CultureInfo.CurrentCulture; - Core!!!
        var values = new Dictionary<CultureInfo, string>();
        try
        {
            values = JsonConvert.DeserializeObject<Dictionary<CultureInfo, string>>(localizedProperty);
        }
        catch (JsonReaderException)
        {
            values[culture] = localizedProperty; // that's all we have, hopefully value is not JSON
        }
        catch (ArgumentNullException)
        {
            values[culture] = null;
        }

        // if text corresponding to InvariantCulture has not been set, then set it here
        if (values.ContainsKey(CultureInfo.InvariantCulture) == false)
        {
            values[CultureInfo.InvariantCulture] = null;//JsonLocalizer.InvariantCultureDefaultText;
        }

        var result = values.ContainsKey(culture) ? values[culture] : values[CultureInfo.InvariantCulture];
        return result;
    }

    public string SetLocalizedValue(string localizedProperty, string value)
    {
        var culture = Thread.CurrentThread.CurrentCulture; // CultureInfo.CurrentCulture; - Core!!!
        var values = new Dictionary<CultureInfo, string>();
        try { values = JsonConvert.DeserializeObject<Dictionary<CultureInfo, string>>(localizedProperty); }
        catch { /* do nothing */ }
        values[culture] = value;
        return JsonConvert.SerializeObject(values);
    }

    public T Merge<T>(T thisObject, T otherObject) where T : class
    {
        if (otherObject == null) { return thisObject; }

        var thisObjectJson = JsonConvert.SerializeObject(thisObject);
        var thisJObject = JObject.Parse(thisObjectJson);
        var thisId = thisJObject.SelectToken("Id");

        var otherObjectJson = JsonConvert.SerializeObject(otherObject);
        var otherJObject = JObject.Parse(otherObjectJson);
        var otherId = thisJObject.SelectToken("Id");

        // same object? -> yes, merge!
        if (thisId.ToObject(typeof(Guid)).Equals(otherId.ToObject(typeof(Guid))))
        {
            // prop by prop merge
            foreach (var thisToken in thisJObject.Children())
            {
                var thisJValue = (JValue)thisJObject.SelectToken(thisToken.Path);
                var otherJValue = (JValue)otherJObject.SelectToken(thisToken.Path);
                thisJValue.Value = JsonLocalizer.DoMerge(thisJValue, otherJValue);
            }
        }

        var result = thisJObject.ToObject<T>();
        return result;
    }

    private static object DoMerge(JValue thisValue, JValue otherValue)
    {
        var result = thisValue.Value ?? otherValue.Value;
        var value = thisValue.Value as string;
        if (value != null)
        {
            try
            {
                var thisJObject = (JObject)JsonConvert.DeserializeObject(value);
                var otherJObject = (JObject)JsonConvert.DeserializeObject((string)otherValue.Value);
                foreach (var otherToken in otherJObject.Children())
                {
                    var thisJValue = (JValue)thisJObject.SelectToken(otherToken.Path);
                    var otherJValue = (JValue)otherJObject.SelectToken(otherToken.Path);
                    if (thisJValue == null && otherJValue != null)
                    {
                        thisJObject.Add(otherToken);
                    }
                }

                result = JsonConvert.SerializeObject(thisJObject);
            }
            catch
            {
                // do nothing, not a loclizable
            }
        }

        return result;
    }
}

You may have noticed that this localizer has been written with ASP.NET Core in mind. Anyway, the changes regarding ASP.NET MVC 5 are really quite few and the code can be used in both ASP.NET and ASP.NET Core almost without changes.

Now let’s see how the decorator changes. What we need is an implementation of Descriptions getter and setter.

Here’s the full code of the ThingDecorator:

public class ThingDecorator : Thing
{
    private readonly Thing component;
    private readonly ILocalizer localizer;

    public ThingDecorator(Thing component, ILocalizer localizer = null)
    {
        this.component = component ?? new Thing();
        this.localizer = localizer ?? new JsonLocalizer();
    }

    public Thing Component => this.component;

    public new Guid Id
    {
        get { return this.component?.Id ?? Guid.Empty; }
        set { this.component.Id = value; }
    }

    [Display(Name = "Name", ResourceType = typeof(Resources))]
    public new string Name
    {
        get { return this.component?.Name; }
        set { this.component.Name = value; }
    }

    [MultiLanguage]
    [Required(AllowEmptyStrings = false, ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "Required")]
    [Display(Name = "Description", ResourceType = typeof(Resources))]
    public new string Description
    {
        get { return this.component != null ? this.localizer.GetLocalizedValue(this.component.Description) : null; }
        set { this.component.Description = this.localizer.SetLocalizedValue(this.component.Description, value); }
    }
}

Couple of things to comment:

  1. I need the localizer injected in decorator’s ctor. If not, the default is used—Json’s one (lines 4, 6, and 9).
  2. Lines 14-18 relate to the Id, quite self-explanatory.
  3. Lines 20, 28, and 29 add metadata to the model. What these mean is explained elsewhere.
  4. Line 27 which decorates the property Description makes it discoverable by the ModelBinder (as well as ModelBinderProvider).
  5. Finally, lines 32 and 33 are the previously mentioned getter and setter.

 

The ModelBinder and ModelBinderProvider

Strictly speaking both do not relate to storing and retrieving the values in the decorated object. However, the decorated object which is the real “meat” in this solution (and is the actual object persisted in a database) needs to be “injected” in the decorator (see ThingDecorator‘s ctor). The  injection happens when the model gets bound to HTTP request’s (usually POST) parameters. Unfortunately, this happens prior to any filters got executed. Hence the need of specialized ModelBinder (and ModelBinderProvider).

Please note, these two classes do not relate to localization itself. They are required by ASP.NET and the way it works.

This is why neither the culture switching mechanism, nor the two classes above are discussed in greater details here. If, however, someone is interested in the whole solution, let me know.

 

 

Advertisements

AngularJS and WebAPI: A Simple ToDo Application, Part 2

Disclaimer: What I describe here is a sequence of steps required to build a demo web application, not a real-world one. The sequence might be different in a number of scenarios, however the idea remains the same and maybe widely reused.
This post, as well as the subsequent ones, are not meant to teach anyone. They are a result of my own learning, and will be used as a reference, or a refreshing material, to which I expect to get back every now and then.
I would be happy if it’d help someone else too. I’d be even happier if somebody posts comments, thus contributing to this series. To those who do this, thanks in advance!

Previous post maybe found here.

The Server

A change in the client is required so as to have the model data fetched from outside the web application instead of having it hard-coded in it.

Step 1: The Request
The change is almost obvious, but here’s the code:

todoApp.controller("ToDoCtrl", function ($scope, $http) {
    $http.get('http://localhost:8888/api/todo?name=Bombastic')
        .success(function (data) {
	    $scope.todo = data;
	})
        .error(function (data, status) {
	    alert('ERROR: ' + status + ', data: ' + data);
        });
	...
}

There are two important changes here. The controller method parameters are now two, the Angular core $http service was added, and right on the next line it is used to fetch data from the server. Once data is successfully retrieved the todo model is initialized from it (line 4).
After making this changes to the ToDoCtrl, the server gets the whole focus.

Step 2: The Console App (The Host)
The server is a OWIN web app hosted in a console application. The empty console application hosts the web app by referencing the Microsoft.AspNet.WebApi.OwinSelfHost package, which may be downloaded and added to the project via the NuGet Package Manager. We can do this either by searching it from the package manager GUI, or by issuing the following command in NuGet Package Manager Console:

PM> Install-Package Microsoft.AspNet.WebApi.OwinSelfHost

The package allows for hosting ASP.NET Web API in a Windows process using the OWIN HttpListener server.

Step 3: The OWIN HttpListener
The listener is invoked like this:

static void Main(string[] args)
{
    const string baseAddress = "http://localhost:8888/";

    // start OWIN host
    using (WebApp.Start<Startup>(baseAddress))
    {
        Console.WriteLine("Web API Started: " + baseAddress);
        Console.WriteLine("Press ENTER to stop server...");
        Console.ReadLine();
    }
}

The base address is set to localhost:8888 and may be changed to whatever needed. For our purpose we need something easy to remember—the port number 8888.
The code in line 6 starts the listener and waits for the user to stop the server by pressing enter key.
The type parameter Startup is the class whose Configuration() method gets called to configure the Web API.

Step 4: Configuring The Web API
Here’s the body of the Configuration method, followed by a brief discussion:

public void Configuration(IAppBuilder appBuilder)
{
    var config = new HttpConfiguration();
    config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional });
    appBuilder.UseWebApi(config);
}

What we configure in this method is a route mapping added to the routes table. An important part is the “api/” prefix which is fixed, constant part of the WebAPI route, helping to distinguish from, or to avoid collisions with, the “normal” ASP.NET MVC route. Also, it is quite unusual at first sight that there’s no action specified. In fact actions are there and are named after the usual HTTP verbs: GET, POST, PUT, DELETE. This is what WebAPI looks for given the request method is known (more on WebAPI routing here).

Also, it is necessary to mention the IAppBuilder interface. It is the core of OWIN, and defines methods to chain OWIN middleware (more about OWIN and the IAppBuilder here). The HTTP Listener we created is such a middleware which serves Web API requests.

Step 5: The WebAPI Controller
So far we talked about our server infrastructure. We’ll have to return back to it later, but now’s the time to get to the tissue of our server. The piece of code which serves the clients’ requests, returning data back to the clients is the ToDoController:

public class ToDoController : ApiController
{
    private readonly IRepository repository;

    public ToDoController(/*IRepository repository*/)
    {
        this.repository = new Repository();
    }

    // GET api/users
    public IEnumerable<UserModel> Get()
    {
        Console.WriteLine(this.Request.RequestUri.ToString());
        var model = repository.GetUsers();
        return model;
    }

    // GET api/user?name=Bombastic, or, api/user/Bombastic if we have suitable route defined
    public UserModel Get(string name)
    {
        var model = repository.GetUser(name);
        return model;
    }

    // GET api/user/id
    public UserModel Get(Guid id)
    {
        var model = repository.GetUser(id);
        return model;
    }

    // POST api/user
    public void Post([FromBody]UserModel user)
    {
    }

    // PUT api/users/Id
    public void Put(Guid id, [FromBody]UserModel user)
    {
    }

    // DELETE api/values/Id
    public void Delete(Guid id)
    {
    }
}

The controller inherits from ApiController (line 1), not the Controller. This is one of the differences with ASP.NET MVC.
The data which the controller returns is managed by the Repository object. In the controller’s constructor we have a parameter (line 5), which may serve as an dependency injection point. Provided we need either to select between different Repository implementations, or we need to perform some unit tests, this is how we can do it. Our goal, however, is to have a controller with a reference to the Repository (a single implementation so far), so we have the parameter commented out and the repository initialization hard-coded in the Controller’s constructor (line 7). That’s just fine.
The three overloaded Get()s retrieve data from the repository and return it back to the clients.

Step 6: The Repository
It implements the IRepository interface and is ready to be replaced by a more elaborate implementation, say, one using EntityFramework. (If there’s a time and someone is interested in such an implementation I’ll provide one.)
The IRepository interface is defined like this:

public interface IRepository
{
    IEnumerable<UserModel> GetUsers();
    UserModel GetUser(string name);
    UserModel GetUser(Guid id);
}

So far we need only the get methods, therefore no data manipulation methods are presented in the interface.
The implementation is simple:

public class Repository : IRepository
{
    private readonly IEnumerable<UserModel> users = new[]
    {
        new UserModel
        {
            Name = "Bombastic",
            Items =
            {
                new ToDoModel { Action = "Sharpening Swords", Done = false },
                new ToDoModel { Action = "Grooming Beards", Done = false },
                new ToDoModel { Action = "Petting Dragons", Done = true },
                new ToDoModel { Action = "Lightning Fires", Done = false },
            }
        },
        new UserModel
        {
            Name = "Gauntlet",
            Items =
            {
                new ToDoModel { Action = "Grooming Beards", Done = true },
                new ToDoModel { Action = "Petting Dragons", Done = false },
                new ToDoModel { Action = "Sharpening Swords", Done = true },
                new ToDoModel { Action = "Lightning Fires", Done = true },
                new ToDoModel { Action = "Loading Airship", Done = true },
            }
        }
    };

    public IEnumerable<UserModel> GetUsers()
    {
        return this.users;
    }

    public UserModel GetUser(string name)
    {
        var user = this.users.SingleOrDefault(u => u.Name == name);
        return user;
    }

    public UserModel GetUser(Guid id)
    {
        var user = this.users.SingleOrDefault(u => u.Id == id);
        return user;
    }
}

What needs to be defined are the two models—UserModel and ToDoModel. And here they are:

public class UserModel
{
    public Guid Id { get; set; }

    public string Name { get; set; }

    public ICollection<ToDoModel> Items { get; set; }

    public UserModel()
    {
        this.Id = Guid.NewGuid();
        this.Items = new List<ToDoModel>();
    }
}
public class ToDoModel
{
    public Guid Id { get; set; }

    public string Action { get; set; }

    public bool Done { get; set; }

    public ToDoModel()
    {
        this.Id = Guid.NewGuid();
    }
}

That’s all that’s it to our models and the repository. Maybe except a couple of (almost!) obvious notes:

  • Both models define an Id of type Guid. This is my favourite record identity type, not int. Say Ids were of type int, if you have to merge data from two existing databases, I wouldn’t like to be in your place.
  • Next, to keep things simple, the model data is initialized in the repository. Not a big deal to move it to a relational database, or somewhere else: a file (XMl, CSV, JSON), a non-SQL database (MongoDB), etc.

Step 7: See What We Have
It’s time to stop coding and start inspecting our server. After we run the console app let’s examine what data it provides upon every of the GET requests.

To get all users and their todos we issue the following request in a web browser:

http://localhost:8888/api/todo

What we get is the following data (output cut to avoid unnecessary repetitions):
ScreenClip3
Good! Almost there. Only, the XML looks pretty inconvenient for our purposes. What if we represent our data in another, more suitable format, say the JavaScript native one—JSON.
We have two options here: always add Content-type: application/json to the header of every request we make to our Web API, or change the way the server renders the data.
The second one is a better choice, IMHO. What needs to be done is change the server configuration.

public void Configuration(IAppBuilder appBuilder)
{
    var config = new HttpConfiguration();
    config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional });
    Startup.ForceJsonSerialization(config);
    appBuilder.UseWebApi(config);
}

and the method, which forces JSON is here:

private static void ForceJsonSerialization(HttpConfiguration config)
{
    config.Formatters.Clear();
    config.Formatters.Add(new JsonMediaTypeFormatter());
}

The method just removes all but the newly created Json formatter. And the result is getting closer to what we need:

ScreenClip4

The last thing to pay attention at is the name’s case—all names are Pascal case (as is normal to C#), while JavaScript usually uses camelCaseFormatted names. Not a big deal, but let’s be polite hoping that someone will be polite to us too. Here’s what we can do for it:

private static void ForceJsonSerialization(HttpConfiguration config)
{
    config.Formatters.Clear();
    config.Formatters.Add(new JsonMediaTypeFormatter
    {
        // optional: set serializer settings here, in this case set Pascal to camelCase name resolver
        SerializerSettings = { ContractResolver = new CamelCasePropertyNamesContractResolver() }
    });
}

And that’s what we get:

ScreenClip5

In order to get all todos for our favourite user Bombastic we need to issue the request we already have at the top of this post. I’ll copy it here for your/my convenience…

http://localhost:8888/api/todo?name=Bombastic

… and will execute it in the browser (the JSON is complette, no cut offs):

ScreenClip6

Now everything looks OK, let’s see it in the client.

Step 8: Back To Client
The client is ready for the server, so refreshing the browser should be all it should take to see the Bombastic’s “real” todo’s. Unfortunately, we see nothing! Data is null, the status is 0 and we see nothing in the view. After the $http.get the success() function gets no data whatsoever (the error() never gets called so as to give us a hint what exactly happens).
And the reason is CORS (Cross-Origin Resource Sharing). We need to tell the server to serve requests from another domain (method, header). And indeed, we have two domains: localhost:8888 (the server), and localhost:xxxxx (the client). Different ports make the server think that the request comes from another domain. In fact this is a good thing, since it stops requests from domains, other than the server’s one, thus securing the server data.
What needs to be done is adding another NuGet package to the server. This package is Microsoft Web API 2.2 Cross-Origin Support.
The server configuration changes a bit:

public void Configuration(IAppBuilder appBuilder)
{
    var config = new HttpConfiguration();
    config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional });
    Startup.ForceJsonSerialization(config);
    config.EnableCors();
    appBuilder.UseWebApi(config);
}

One more thing remains and it is we need to decorate our ToDoController with the following attribute:

[EnableCors("*", "*", "*")]

The asterisks enable all domains, all methods, all headers. For a demo quite legal and acceptable, dangerous in production code though.
Now, after we run the client we see all we expected to see.

AngularJS and WebAPI: A Simple ToDo Application, Part 1

Disclaimer: What I describe here is a sequence of steps required to build a demo web application, not a real-world one. The sequence might be different in a number of scenarios, however the idea remains the same and maybe widely reused.
This post, as well as the subsequent ones, are not meant to teach anyone. They are a result of my own learning, and will be used as a reference, or a refreshing material, to which I expect to get back every now and then.
I would be happy if it’d help someone else too. I’d be even happier if somebody posts comments, thus contributing to this series. To those who do this, thanks in advance!

The Client

The demo starts as a static markup, so there’s very little in it: a simple HTML file (index.html), two references to css files—bootstrap.css and bootstrap-theme.css, and one more—to angular.js. The referenced CSS are not necessary, but I want to make things look a bit pleasing to the eye with as little efforts as possible. Bootstrap seems to be a perfect fit for that.
Let’s get started.
Step 1: The HTML

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>TO DO Demo Application</title>
    <link href="css/bootstrap.css" rel="stylesheet"/>
    <link href="css/bootstrap-theme.css" rel="stylesheet"/>
    <script src="js/angular.js"></script>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <div class="page-header">
                <h1>
                    My To Do List
                </h1>
            </div>
            <div class="panel">
                <table class="table table-striped">
                    <thead>
                    <tr>
                        <th>Description</th>
                        <th>Done</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                        <td>action</td>
                        <td>status</td>
                    </tr>
                    </tbody>
                </table>
                <div class="input-group">
                    <input class="form-control"/>
                    <span class="input-group-btn">
                        <button class="btn btn-primary">Add</button>
                    </span>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
</html>

Nothing special so far, just a piece of HTML beautified with bootstrap. As I’ve already mentioned, the nice look is important—it prevents the annoyance of the ugly, raw UI look.
This is how the things look at the very beginning:

ScreenClip

Step 2: The Angular Application
Obviously, we need to display some data from the ToDo items. Here the unused reference to angular.js comes into play (line 8 above). We need to add an Angular application to make our markup live. We’ll add it like this (line 2 in the above listing):

...
<html ng-app="todoApp">
...

And we’ll test that it works like this:

...
<body>
{{ 1 + 2 }}
...

If we see 3 at the top-left corner of the screen, then the reference to angular.js is OK.
There are couple of things to note here:
1. Looking at the UI does not help in telling if the reference to angular.js is correct—it requires a simple test like the one above.
2. It’s almost obvious that the .css files reside in a sub-directory named css, and .js in the js sub-directory.
3. The reference to angular.js is not at the end of the body, neither it is attributed with async=…. All the optimization parts are omitted.

Step 3: The Controller
So far we spoke about the View, now it’s time to get to the Controller. The demo application is a small one and it’s better to keep everything in one place.
Adding the controller declaration to the HTML body is perfectly fine:

...
<body ng-controller="ToDoCtrl">
...

The definition of the controller is also simple:

<script>
    // model definition here
    ...
    var todoApp = angular.module("todoApp", []);

    todoApp.controller("ToDoCtrl", function ($scope) { 
        $scope.todo = model; 
    });
</script>

It is placed right before the closing head tag.

Step 4: The Model
This is the last (in fact the first, following the MVC abbreviation) part of the MVC pattern. It is as follows:

var model = {
    name: "Bombastic",
    items: [{ action: "Sharpening Swords", done: false },
        { action: "Grooming Beards", done: false },
        { action: "Petting Dragons", done: true },
        { action: "Lightning Fires", done: true },
        { action: "Loading Airship", done: false }]
};

Step 5: Binding The View (HTML) With The Controller
…since the model is already bound (line 7 in the definition of the controller above).
There are couple of places where the model data, delivered by the controller, has to be bound to elements in the view. Binding the name (line 2 above, and also, line 4 below) is pretty straightforward:

...
<div class="page-header">
    <h1>
        {{todo.name}}'s To Do List
    </h1>
</div>
...

The next step is to bind every item in the list with some HTML element(s). These are two table columns, which, are bound like this:

...
<tbody>
    <tr ng-repeat="item in todo.items">
        <td>{{item.action}}</td>
        <td>{{item.done}}</td>
    </tr>
</tbody>
...

What is worth to mention is the repeater on line 3, which iterates over items and repeats the element in which it is defined, as well as the inner HTML of the element.

Here’s a how things look at this point:

ScreenClip2

Well, that’s all that it is to the client part, or, rather the client prototype. The actual data usually comes from a server. Embedded in the client’s code the data is almost useless. In the next post I’ll change the client to fetch the data from the server, which will be implemented as a WebAPI, hosted in a console application.

Convert class library project to ASP.NET MVC WebApplication

Summary: The purpose of this conversion is to add MVC tooling to the class library project.

Whatever reason, you may need to add a Controller descendent to your project (class library) and use the VS MVC tools to add view to a controller’s action. In order to do this you’ll need to edit your project file (*.csproj) as a text one and add the following:

1. Add ProjectTypeGuids node

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>8.0.30703</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{74D88AE8-B969-4962-89CD-E6624059FC1B}</ProjectGuid>
    <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
    <OutputType>Library</OutputType>
	<!-- ... -->
  </PropertyGroup>
	<!-- ... -->
</Project>

2. Add the following Import node at the end, just before the closing </Project>

  <!-- ... -->
  <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v12.0\WebApplications\Microsoft.WebApplication.targets" />
  <!-- ... -->

Without the last you’ll get a nasty exception from the VS IDE that the MVC corresponding .targets
file cannot be found.

Two things to note:

  1. The first is the VisualStudio version (in this case v12.0). Change to yours if different.
  2. $(MSBuildExtensionsPath) depends on machine’s architecture – x86 or x64. More info here.

After all these done (not too much indeed!) re-open the project by VS IDE. All the commands for adding/managing ASP.NET MVC related items are there.

NB: VS adds one more node right after the last one you added. If you are curious take a look. It all relates to web app, nothing unusual.

VS IDE will reports error(s) while generating MVC items. Right click the project node and “Add Item” to add a web configuration file.
Or, just add a minimal web.config to the project.

<?xml version="1.0">
<configuration>
</configuration>

(Maybe an empty file would also do, not tested though!)
This is all that VS IDE needs to enable ASP.NET MVC tooling for the project. Of course, a global.asax with Main() and everything else will also be required if you need a full featured web application.

Hope this will save your time!


View Alexander Christov's profile on LinkedIn

CryptoLib

Quick Intro This is a very simple but (hopefully!) convenient wrapper around two  System.Security.Cryptography classes: 1. SymmetricAlgorithm, from which descend DES, TrippleDES, RC2, Rijndael, AES, and 2. HashAlgorithm, ancestor of MD5, RIPEMD160, SHA1, SHA256, SHA384, SHA512. The encryption part was left almost identical to its original http://www.superstarcoders.com/blogs/posts/symmetric-encryption-in-c-sharp.aspx. Only it was slightly beautified according to StyleCop’s suggestions, except for comments and headings. Hashing was added so as to complete the picture. You may use the CryptoHelper by calling any of its three static methods like this:

// T descends from System.Security.Cryptography.SymmetricAlgorithm
var encrypted = CryptoHelper.Encrypt<TripleDESCryptoServiceProvider>(value, password, salt);
var decrypted = CryptoHelper.Decrypt<TripleDESCryptoServiceProvider>(value, password, salt);

// T descends from System.Security.Cryptography.HashAlgorithm
var hashed = CryptoHelper.ComputeHash<SHA256Managed>(value);

Very basic usage guidelines: 1. Original value is not required – use hashing; it is safer because no password and salt values are needed and therefore there’s no need to be kept, and 2. Original value is required – encryption/decryption is the choice, but beware, password and salt values should be kept safe. The full source code here:

// adapted from http://www.superstarcoders.com/blogs/posts/symmetric-encryption-in-c-sharp.aspx

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace CryptoLibrary
{
  public class CryptoHelper
  {
    // Encrypts the specified value given a password and salt.
    public static string Encrypt<T>(string value, string password, string salt)
      where T : SymmetricAlgorithm, new()
    {
      var rgb = new Rfc2898DeriveBytes(password, Encoding.Unicode.GetBytes(salt));
      SymmetricAlgorithm algorithm = new T();
      var rgbKey = rgb.GetBytes(algorithm.KeySize >> 3);
      var rgbIv = rgb.GetBytes(algorithm.BlockSize >> 3);
      var transform = algorithm.CreateEncryptor(rgbKey, rgbIv);
      using (var buffer = new MemoryStream())
      {
        using (var stream = new CryptoStream(buffer, transform, CryptoStreamMode.Write))
        using (var writer = new StreamWriter(stream, Encoding.Unicode))
        {
          writer.Write(value);
        }

        var result = Convert.ToBase64String(buffer.ToArray());
        return result;
      }
    }

    // Decrypts the specified text given a password and salt.
    public static string Decrypt<T>(string text, string password, string salt)
      where T : SymmetricAlgorithm, new()
    {
      var rgb = new Rfc2898DeriveBytes(password, Encoding.Unicode.GetBytes(salt));
      SymmetricAlgorithm algorithm = new T();
      var rgbKey = rgb.GetBytes(algorithm.KeySize >> 3);
      var rgbIv = rgb.GetBytes(algorithm.BlockSize >> 3);
      var transform = algorithm.CreateDecryptor(rgbKey, rgbIv);
      using (var buffer = new MemoryStream(Convert.FromBase64String(text)))
      using (var stream = new CryptoStream(buffer, transform, CryptoStreamMode.Read))
      using (var reader = new StreamReader(stream, Encoding.Unicode))
      {
        var result = reader.ReadToEnd();
        return result;
      }
    }

    // Computes the hash of the text.
    public static string ComputeHash<T>(string text) where T : HashAlgorithm, new()
    {
      var algorithm = new T();
      var buffer = algorithm.ComputeHash(Encoding.Unicode.GetBytes(text));
      var result = Convert.ToBase64String(buffer);
      return result;
    }
  }
}

Availability The library is available as a NuGet package here: https://nuget.org/packages/CryptoLib


View Alexander Christov's profile on LinkedIn

MembershipAdapter with customized Users

In the previous post we saw how to create a very simple (perhaps simplest!) MembershipProvider. Now we’ll create another, closer to real life, example. We’ll use our User class to store user information. This is the major reason why the ProfileProvider is not part of the MembershipAdapter package. The class will look like this:

public class User
{
  [Key]
  public int Id { get; set; }

  [StringLength(100)]
  public string FirstName { get; set; }

  [StringLength(100)]
  public string LastName { get; set; }

  [Required]
  [StringLength(200)]
  public string Email { get; set; }

  [Required]
  [StringLength(100)]
  public string Password { get; set; }
}

This class will be stored in a MSSQL Server database table using EntityFramework. For this to work we need a DbContext descendent which will handle all database mappings and calls. Two changes are needed: 1. A class which extends DbContext and defined a set of users

public class ModelContext : DbContext
{
  public ModelContext()
    : base("MADB")
  {
  }

  public DbSet Users { get; set; }
}

and 2. A database initializer called on application start:

protected void Application_Start()
{
  AreaRegistration.RegisterAllAreas();
  RegisterGlobalFilters(GlobalFilters.Filters);
  RegisterRoutes(RouteTable.Routes);
  Database.SetInitializer(new DropCreateDatabaseIfModelChanges());
}

ModelContext defines a parameterless constructor with the only purpose to specify a connection string in its base class constructor. Without it a default database would be created. This is a matter of choice, both approaches work well, although I prefer the explicit one. Now it is time to implement ValidateUser method. It is rather simple except for some security that needs to be taken into account (see the highlighted lines):

public bool ValidateUser(string username, string password)
{
  var encEmail = Encrypt.MD5(username);
  var encPasword = Encrypt.MD5(password);
  var user = from u in this.db.Users
             where u.Email == encEmail && u.Password == encPasword
             select u;
  return user.SingleOrDefault() != default(User);
}

I usually use PasswordHash package, which is available in the NugGet package gallery. Instead of MD5 you may use SHA hashing offered by the package. It is worth to note that how password (and email address, which – in our case replaces username) are stored may be part of the provider’s setting.


View Alexander Christov's profile on LinkedIn

Simplest MembershipProvider

Often a very simple MembershipProvider is required just to develop some features requiring user authentication and, perhaps, authorization.

Using MembershipProviderAdapter it is really very simple and straightforward. Follow the steps below to implement a MVC3 web application with a MembershipProviderAdapter.

1. Create a MVC3 project using Visual Studio MVC3 Internet Application template. This will add all the files necessary to add Forms authentications to the project.

2. Add a NuGet reference to the package named MembershipAdapter. web.config will be changed to reflect the new provider:

    <membership defaultProvider="MembershipProviderAdapter">
      <providers>
        <clear />
        <!-- NOTE: Change userRepositoryType to whatever the implementation of IUserRepository is -->
        <add name="MembershipProviderAdapter"
             type="MembershipAdapter.MembershipProviderAdapter, MembershipAdapter"
             userRepositoryType="MvcApplication1.Samples.SampleUserRepository, MvcApplication1"
             enablePasswordRetrieval="false"
             enablePasswordReset="true"
             requiresQuestionAndAnswer="false"
             requiresUniqueEmail="false"
             maxInvalidPasswordAttempts="5"
             minRequiredPasswordLength="6"
             minRequiredNonalphanumericCharacters="0"
             passwordAttemptWindow="10"
             applicationName="MvcApplication1" />
      </providers>
    </membership>

The new MembershipProviderAdapter will be listed in the membership section and will be made the default one. userRepositoryType (line 7) is the type of the user repository that is injected in adaptee’s constructor. This is where you can implement whatever logic is needed to support membership (and not only) users and their properties.

It is important to note that the user repository constructor expects a single parameter of type NameValueCollection. This collection is passed to the virtual Initialize method of MembershipProvider along with the provider name.

public override void Initialize(string name, NameValueCollection config)
{
    // ...
    SecUtility.GetAndRemoveStringAttribute(config, "userRepositoryType", this.GetType().Name, ref userRepositoryType);
    this.adaptee = this.InitializeAdaptee(userRepositoryType, config);
}

And the InitializeAdaptee method is

private IUserRepository InitializeAdaptee(string userRepository, NameValueCollection config)
{
    // ...
    var type = Type.GetType(userRepository);
    var result = (IUserRepository)Activator.CreateInstance(type, new object[] { config });
    this.settings = result.Settings;
    return result;
}

You may need to look at SampleUserRepository constructor, fetched by the NuGet package. New settings may be added to the collection and passed to MembershipProviderSettings (or a class derived from it). All the initialization logic was moved to MembershipProviderSettings Initialize method thus decoupling the MembershipProviderAdapter from its configuration code and making it really loosely coupled. It is now almost completely independent of its users (MembershipUser) and configuration. Things look much cleaner: the provider is a provider (pardon the tautology!) the users are handled by the adaptee, and the configuration are taken care by a separate class or a class derived from it.

OK, let’s continue after this brief note on MembershipProviderAdapter‘s design and the goals achieved by decoupling both users and settings.

3. Change ValidateUser method so that it returns true instead of throwing an exception

public bool ValidateUser(string username, string password)
{
    return true;// throw new NotImplementedException();
}

4. Run the application and test the LogOn link. Whatever name you enter in User Name box is displayed in the welcome message. The user is authenticated and when you test IsAuthenticated property of the HttpRequest it is set to true.

image

Let us elaborate the example a bit. Say, except authenticated you need the user to be authorized. In addition, if username is admin you want him to be an administrator (i.e. to be in role Administrators).

5. Change shared partial view _LogOnPartial.cshtml

@functions {
    private bool IsAdministrator(string name)
    {
        return Roles.IsUserInRole("administrators");
    }
}
@if (Request.IsAuthenticated)
{
    if (this.IsAdministrator(User.Identity.Name))
    {
        <text>***</text>
    }
    <text>Welcome <strong>@User.Identity.Name</strong>! [ @Html.ActionLink("Log Off", "LogOff", "Account") ]</text>
}
else
{
    @:[ @Html.ActionLink("Log On", "LogOn", "Account") ]
}

This will display three asterisks in front of the welcome message if user is administrator.

6. In order to check belonging to a role we need to modify GetRolesForUser method, part of the SampleRoleRepository class:

public string[] GetRolesForUser(string username)
{
    if (username.Equals("Admin", StringComparison.OrdinalIgnoreCase))
    {
        return new[] {"Administrators"};
    }

    return new[] { "Users" };
}

image


View Alexander Christov's profile on LinkedIn