Chitika

February 4, 2013

Knockout validation: Сomparison of the two fields

I would like to share how I've solved this problem.

The typical example is a simple registration form with the view model:

    var viewModel = ko.validatedObservable({
        userName: ko.observable().extend({ required: true }),
        password: ko.observable().extend({ required: true }),
        passwordConfirm: ko.observable().extend({ required: true })
    });

Then you can easily check is your viewModel valid using:

    viewModel.isValid();

And it works very good. But you don't have validation are your password and password confirmation fields equal.

To do it you have to add these lines:

    viewModel().password.extend({ equal: viewModel().passwordConfirm });
    viewModel().passwordConfirm.extend({ equal: viewModel().password });

After that you will have client notification as well as ability to check is your view model valid in code (as mentioned above).

That's all.
Good luck.

November 14, 2012

JavaScript modularity with RequireJS (from spaghetti code to ravioli code)

Today I would like to describe how you can make your JavaScript code much much much better.

We know a lot about how to make our c# code much better. And we always use it.
We split out our c# code to classes, put the classes to modules, put the modules to layers, etc.

But we never do the same for our JavaScript code. And this is a big mistake.

And that's why we have a lot of Spaghetti Code inside our apps.

The main problems with function spaghetti code are:

  • It's really hard to figure out where the one block of code begins and where the other ends
  • Who's responsible for what?
  • How are we deal with global scope pollution (e.g. use the same variables in different pieces of code)
  • Low code re-use
  • Not easy to maintain, test and debug.

I'm not going to describe in details what the functional spaghetti code is, because you can find a lot of references in the Internet.
I would like to show here how to avoid it and make your code better using RequireJS.

Function spaghetti code

Let's start with a simple example of spaghetti code. (I can't say that it is really good example of horrible spaghetti code, but it is simple, so it's easy to understand and see all the changes)

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Phase 1</title>
</head>
<body>
    <div>
        <h1>Modular Demo 1</h1>
    </div>
    <div id="messagebox"></div>

    <script src="../Scripts/jquery-1.8.2.min.js" type="text/javascript"></script>

    <script type="text/javascript">

        var baseUrl = '/api/messenger/';

        function ShowMessage(id) {
            $.ajax({
                url: baseUrl + id,
                type: 'GET',
                dataType: 'json',
                success: function(data) {
                    $("#messagebox").html(data);
                }
            });
        }

        var id = 55;
        ShowMessage(id);
        
    </script>
</body>
</html>

As you can see it's really simple example. The code sends ajax request to get a message from server and then puts this message to div container.
This code is correct and works well. And at the same time not perfect but is an example of spaghetti code.

All of your code logic (sending the request, putting a message to a div container) located in the same function.

I would like to repeat again, that it is not perfect example, but we need really simple one to better undersand how we can improve it.

JavaScript modules

First of all I would like to describe how you can use the module pattern to create a module in JavaScript.

Let's start with an example first.

        var messenger = (function ($) {
            var text = 'I am a module',
                showMessage = function() {
                    $("#messagebox").html(text);
                };

            return {
                showMessage: showMessage
            };
        })($);

That's it. You have a module - messenger.
This module has internal part:

            text = 'I am a module',

And exposes externally function:

            return {
                showMessage: showMessage
            };

So, for the other code only showMessage will be visible.
And it is really simple to use it:

            messenger.showMessage();

Also in this example our module depends on jQuery. You can see it here:

        var messenger = (function ($) {
            . . .
        })($);

As you can see it's really simple to create a module in JavaScript.

Let's see how we can re-factor our code.

Ravioli code

When you eating the ravioli you are totally sure where is the one ravioli and where is another one.
Also, to take SRP (single responsibility principle) into account we have to separate our code into modules which have only single responsibilities.

This is the result:

        var config = (function() {
            var baseUrl = '/api/messenger/';

            return {
                baseUrl: baseUrl
            };
        })();

        var dataservice = (function($, config) {
            var callApi = function (url, type, callback) {
                    $.ajax({
                        url: url,
                        type: type,
                        dataType: 'json',
                        success: function (data) {
                            callback(data);
                        }
                    });
                },
                getMessage = function (id, callback) {
                    url = config.baseUrl + id;
                    callApi(url, 'GET', callback);
                };

            return {
                getMessage: getMessage
            };
        })($, config);

        var messenger = (function ($, dataservice) {
            var showMessage = function(id) {
                dataservice.getMessage(id, function(message) {
                    $("#messagebox").html(message);
                });
            };

            return {
                showMessage: showMessage
            };
        })($, dataservice);

        (function (messenger) {
            var id = 55;
            messenger.showMessage(id);
        })(messenger);

As a result we have 4 modules. Let's describe them:

  • config module - for storing our global variables
  • dataservice module - for doing communication with the server (sending ajax requests and getting the response back)
  • messenger module - for showing a message (placing a message into containers)
  • main module - as starting point of our app

And it's really easy now to change our modules if needed, for example if we will decide to change our communication mechanism with the server, or to change our messenger to show a message into jQuery dialog.

Split out your modules

The next step is splitting your modules out into JavaScript files.
Because it is not really good solution to place your JavaScript code into HTML.

At the end you will have four JavaScript files.

config.js

        var config = (function() {
            var baseUrl = '/api/messenger/';

            return {
                baseUrl: baseUrl
            };
        })();

dataservice.js

        var dataservice = (function($, config) {
            var callApi = function (url, type, callback) {
                    $.ajax({
                        url: url,
                        type: type,
                        dataType: 'json',
                        success: function (data) {
                            callback(data);
                        }
                    });
                },
                getMessage = function (id, callback) {
                    url = config.baseUrl + id;
                    callApi(url, 'GET', callback);
                };

            return {
                getMessage: getMessage
            };
        })($, config);   

messenger.js

        var messenger = (function ($, dataservice) {
            var showMessage = function(id) {
                dataservice.getMessage(id, function(message) {
                    $("#messagebox").html(message);
                });
            };

            return {
                showMessage: showMessage
            };
        })($, dataservice);

main.js

        (function (messenger) {
            var id = 55;
            messenger.showMessage(id);
        })(messenger);

Also, we have to change our HTML to load all of these JavaScript files.

index.html

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Phase 1</title>
</head>
<body>
    <div>
        <h1>Modular Demo 1</h1>
    </div>
    <div id="messagebox"></div>

    <script src="../Scripts/jquery-1.8.2.min.js" type="text/javascript"></script>

    <script src="config.js" type="text/javascript"></script>
    <script src="dataservice.js" type="text/javascript"></script>
    <script src="messenger.js" type="text/javascript"></script>
    <script src="main.js" type="text/javascript"></script>
   
</body>
</html>

Finally, our code looks much better now.

Loading modules in proper order

Everything almost perfect in our code, except of loading scripts in the proper order.
Honestly, we do this task, but we do it manually.
Everything changes if you decide to order your modules in HTML files in alphabetical order.

    <script src="config.js" type="text/javascript"></script>
    <script src="dataservice.js" type="text/javascript"></script>
    <script src="main.js" type="text/javascript"></script>
    <script src="messenger.js" type="text/javascript"></script>

I've just put the module main.js above messenger.js. And unfortunately it has really changed behavior of our app.
Instead of showing a message it shows an exception now.

Line: 1
Error: 'messenger' is undefined

It has been happened because we changed the order, and module main.js has been loaded before messenger.js. As a result module main.js tries to call messenger.showMessage(), but the messenger is undefined, because it has not been loaded yet.

Of course, in this simple example we can easily control the order of the four scripts, but in a real application we can manage 30, or 50 or even more modules.

And it becomes a serious problem.

In this case RequireJS can really helps.

RequireJS

The following command in the Package Manager console will install RequireJS package into your ASP.NET application:

PM > Install-Package RequireJS

RequireJS is a JavaScript file and module loader. It is optimized for in-browser use, but it can be used in other JavaScript environments, like Rhino and Node. Using a modular script loader like RequireJS will improve the speed and quality of your code.

In other words RequireJS really helps:

  • To define our modules
  • To resolve module dependencies
  • To load scripts in the proper order (and asynchronously)

So, RequireJS really helps to define a structure to the modules in a JavaScript applications.

RequireJS modules

First I would like to show how you can create modules using RequireJS.
I will use the same example as I used to show how to create a JavaScript module.

    define('messenger',
        ['jquery'],
        function ($) {
            var text = 'I am a module',
                showMessage = function() {
                    $("#messagebox").html(text);
                };

            return {
                showMessage: showMessage
            };
        }
    );

It looks as easy as a JavaScript module. But I would like to describe some differences.
The RequireJS module starts with:

    define('messenger',

Where 'messenger' is the module ID. You can use this ID if you want to reference this module in other modules.

The next line describes dependencies of this module:

       ['jquery'],

In this example our module depends on jQuery only.

And then you have to specify module body as a function.

As you can see it's really simple to create a module using RequireJS.

Using RequireJS

Let's change all of our modules.

config.js

define('config',
    [],
    function () {
        var baseUrl = '/api/messenger/';

        return {
            baseUrl: baseUrl
        };
    }
);

dataservice.js

define('dataservice',
    ['jquery', 'config'],
    function ($, config) {
        var
            callApi = function (url, type, callback) {
                $.ajax({
                    url: url,
                    type: type,
                    dataType: 'json',
                    success: function (data) {
                        callback(data);
                    }
                });
            },
            
            getMessage = function (id, callback) {
                url = config.baseUrl + id;
                callApi(url, 'GET', callback);
            };

        return {
            getMessage: getMessage
        };
    }
);

messenger.js

define('messenger',
    ['jquery', 'dataservice'],
    function ($, dataservice) {
        var showMessage = function (id) {
            dataservice.getMessage(id, function (message) {
                $("#messagebox").html(message);
            });
        };

        return {
            showMessage: showMessage
        };
    }
);

main.js

(function() {
    requirejs.config(
        {
            paths: {
                'jquery': '../Scripts/jquery-1.8.2.min'
            }
        }
    );

    require(
        ['messenger'],
        function(messenger) {
            var id = 55;
            messenger.showMessage(id);
        }
    );
})();

All of the modules look as they were before, except of main module.

In this module I have configured RequireJS to specify where RequiteJS can find the jquery module.

    requirejs.config(
        {
            paths: {
                'jquery': '../Scripts/jquery-1.8.2.min'
            }
        }
    );

And then, I've specified the start up code, which depends on messenger module:

    require(
        ['messenger'],
        function(messenger) {
            var id = 55;
            messenger.showMessage(id);
        }
    );

After all, we have to change our HTML to load our modules.

index.html

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Phase 1</title>
</head>
<body>
    <div>
        <h1>Modular Demo 1</h1>
    </div>
    <div id="messagebox"></div>

    <script data-main="main" src="../Scripts/require.js" type="text/javascript"></script>
   
</body>
</html>

Small remarks about our HTML changes.

We should not load any of our modules or jQuery, because RequireJS will handle it for us.
We have to load RequireJS only, and specify 'data-main' attribute, which tells RequireJS to load main.js script after RequireJS loads. In other words, we specify start up script in 'data-main' attribute.

And after all RequireJS does the 'magic' and loads all of our modules in proper order automatically.

As a result, our code becomes much much better now, as I promised at the beginning of this post.

That's all. And see you next time.

June 27, 2012

ASP.NET MVC 4 WebAPI. Support Areas in HttpControllerSelector

This article was written for ASP.NET MVC 4 RC (Release Candidate). If you are still using Beta version of ASP.NET MVC 4 then you have to read the previous article.

HttpControllerFactory was deleted in ASP.NET MVC 4 RC. Actually, it was replaced by two interfaces: IHtttpControllerActivator and IHttpControllerSelector.

Unfortunately DefaultHttpControllerSelector still doesn't support Areas by default. To support it you have to write your HttpControllerSelector from scratch. To be honest, I will derive my selector from DefaultHttpControllerSelector.

In this post I will show you how you can do it.

AreaHttpControllerSelector

First of all, you have to derive your class from DefaultHttpControllerSelector class:

    public class AreaHttpControllerSelector : DefaultHttpControllerSelector
    {
        private readonly HttpConfiguration _configuration;

        public AreaHttpControllerSelector(HttpConfiguration configuration)
            : base(configuration)
        {
            _configuration = configuration;
        }
    }

In the constructor mentioned above I called the base constructor and stored the HttpConfiguration. We will use it a little bit later.

My code will use two constants:

        private const string ControllerSuffix = "Controller";
        private const string AreaRouteVariableName = "area";

You can understand why we need first one by name. The second one contains the name of the variable which we will use to specify area name in Routes collection.

Somewhere we have to store all of the API controllers.

        private Dictionary<string, Type> _apiControllerTypes;

        private Dictionary<string, Type> ApiControllerTypes
        {
            get { return _apiControllerTypes ?? (_apiControllerTypes = GetControllerTypes()); }
        }

        private static Dictionary<string, Type> GetControllerTypes()
        {
            var assemblies = AppDomain.CurrentDomain.GetAssemblies();

            var types = assemblies.SelectMany(a => a.GetTypes().Where(t => !t.IsAbstract && t.Name.EndsWith(ControllerSuffix) && typeof(IHttpController).IsAssignableFrom(t)))
                .ToDictionary(t => t.FullName, t => t);

            return types;
        }

Method GetControllerTypes takes all the API controllers types from all of your assemblies, and store it inside the dictionary, where the key is FullName of the type and value is the type itself.
Of course we will set this dictionary only once. And then just use it.

Now we are ready to implement one of the important method:

        public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
        {
            return GetApiController(request) ?? base.SelectController(request);
        }

In that method I try to take the HttpControllerDescriptor from method GetApiController and if it return null then call the base method.

And additional methods:

        private static string GetAreaName(HttpRequestMessage request)
        {
            var data = request.GetRouteData();

            if (!data.Values.ContainsKey(AreaRouteVariableName))
            {
                return null;
            }

            return data.Values[AreaRouteVariableName].ToString().ToLower();
        }

        private Type GetControllerTypeByArea(string areaName, string controllerName)
        {
            var areaNameToFind = string.Format(".{0}.", areaName.ToLower());
            var controllerNameToFind = string.Format(".{0}{1}", controllerName, ControllerSuffix);

            return ApiControllerTypes.Where(t => t.Key.ToLower().Contains(areaNameToFind) && t.Key.EndsWith(controllerNameToFind, StringComparison.OrdinalIgnoreCase))
                    .Select(t => t.Value).FirstOrDefault();
        }

        private HttpControllerDescriptor GetApiController(HttpRequestMessage request)
        {
            var controllerName = base.GetControllerName(request);

            var areaName = GetAreaName(request);
            if (string.IsNullOrEmpty(areaName))
            {
                return null;
            }

            var type = GetControllerTypeByArea(areaName, controllerName);
            if (type == null)
            {
                return null;
            }

            return new HttpControllerDescriptor(_configuration, controllerName, type);
        }
Method GetAreaName just takes area name from HttpRequestMessage.

Method GetControllerTypeByArea are tries to find the controller in the ApiControllerTypes by full name of the controller where the full name contains area's name surrounded by "." (e.g. ".Admin.") and ends with controller name + controller suffix (e.g. UsersController).

And if a controller type found then method GetApiController will create and return back HttpControllerDescriptor.

So, my AreaHttpControllerSelector is ready to be registered in my application.

Registering AreaHttpControllerSelector

The next thing you have to do is to say to your application to use this controller selector instead of DefaultHttpControllerSelector. And fortunately it is really easy - just add one additional line to the end of Application_Start method in Glogal.asax file:
        protected void Application_Start()
        {
            // your default code
                    GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector), new AreaHttpControllerSelector(GlobalConfiguration.Configuration));
        }
That's all.

Using AreaHttpControllerSelector

If you did everything right, now you can forget about that "nightmare" code mentioned above. And just start to use it!

You have to add new HttpRoute to your AreaRegistration.cs file:

        public override void RegisterArea(AreaRegistrationContext context)
        {
            context.Routes.MapHttpRoute(
                name: "Admin_Api",
                routeTemplate: "api/admin/{controller}/{id}",
                defaults: new { area = "admin", id = RouteParameter.Optional }
            );

            // other mappings
        }

Or just use one global route in your Global.asax like:


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

That's all. Good luck, and have a nice day.

April 23, 2012

Localizable text template engine using StringTemplate 4

In the previous post I shown how to create localizable text template engine using RazorEngine.
I suggest to use the RazorEngine in any case.
But there is an one case where RazorEngine can not help you. It will happened if you try to use RazorEngine in dynamically loaded assembly.
There is a simple example. Your system can load the plugins dynamically. One of your plugin have to use text template engine to parse the strings. In that case RazorEngine will throw an error with the message:

Precondition failed: templateType != null

It's known issue and if you interested in it you can find a detailed description of this problem here.

In that case, you have to use something else for a template engine and I suggest to use StringTemplate to avoid that kind of problems.

In this post I will show you how to use StringTemplate engine.


Using the StringTemplate engine


The following command in the Package Manager console will install StringTemplate 4 package into your ASP.NET MVC 4 WebAPI application:

PM > Install-Package Antlr4.StringTemplate

StringTemplate is a template engine library used for generating text from data structures. StringTemplate's distinguishing characteristic is that it strictly enforces model-view separation unlike other comparable template engines. It is particularly good at multi-targeted code generators, multiple site skins, and internationalization/localization.

So, it fully meets our needs.

In my previous post I shown how to write and use the localizable template service.

So, here I will talk only about another realization of the interface ITemplateEngine for StringTemplate, because everything else will stay the same.

I would like to remind you how the ITemplateEngine interface looks:

    public interface ITemplateEngine
    {
        string Parse(string template, dynamic model);
    }

And there is the realization of this interface for StringTemplate engine:

    public class StringTemplateEngine : ITemplateEngine
    {
        public string Parse(string template, dynamic model)
        {
            var group = new TemplateGroupString("group", "delimiters \"$\", \"$\"");

            var renderer = new AdvancedRenderer();
            group.RegisterRenderer(typeof(DateTime), renderer);
            group.RegisterRenderer(typeof(double), renderer);

            group.DefineTemplate("template", template, new[] { "Model" });

            var stringTemplate = group.GetInstanceOf("template");
            stringTemplate.Add("Model", model);

            return stringTemplate.Render();
        }
    }

It is a little bit complicated example and I will explain you why.
The first line just creates a template group with specified delimiters '$' (default delimiters are '<' and '>').
The next three lines help us to specify the renderer for the types DateTime and double. I have to use custom renderer to allow formatting my DateTime and double values, and that is only one reason why I use the template group instead of specify only one template.
The next line creates new template in the template group with the name 'template' and use the template text for a content of the template.
Then I take this template from a group and add my model to template.
At last, just call Render method of the template and return result back.

To make formatting inside the template possible I use custom renderer for StringTemplate called AdvancedRenderer:

    public class AdvancedRenderer : IAttributeRenderer
    {
        public string ToString(object obj, string formatString, System.Globalization.CultureInfo culture)
        {
            if (obj == null)
                return null;

            if (string.IsNullOrEmpty(formatString))
                return obj.ToString();

            return string.Format("{0:" + formatString + "}", obj);
        }
    }

It is really simple but powerful renderer. I will show you how to use the formatting directly in the template later.

So, I have done with the template engine. And we can start using it already.

In the last part of the post, I would like to share the example of template that would be easier to understand the syntax of StringTemplate.

Using the localizable template service


To demonstrate how to use this service let's create the template file first.
Create a directory 'Templates' in your project.
Then click the right mouse button on this directory in the 'Solution Explorer' and select 'Add' -> 'New Item...' (or just press Ctrl+Shift+A).
In the new window click on 'Visual C# Items' and select the 'Text File' in the list. Enter the file name - 'first.template' and click 'Add' button.

Then insert the next text into template file:

ID: $Model.Id$
CreatedDate: $Model.CreatedDate; format="dd.MM.yyyy HH:mm"$
Name: $Model.Name$
Price: $Model.Price; format="0.00"$
Items:
$Model.Items:{item |
    item $i$ - $item.Key$  $if(item.Value)$enabled$else$-$endif$
}$

Then write some simple code to prepare the data model and to parse the template:

            
            var model = new { 
                Id = 10,
                CreatedDate = DateTime.Now,
                Name = "Name1",
                Price = 123.45356,
                Items = new List<KeyValuePair<string, bool>> {
                    new KeyValuePair<string, bool>("Item1", false),
                    new KeyValuePair<string, bool>("Item2", true),
                    new KeyValuePair<string, bool>("Item3", false),
                    new KeyValuePair<string, bool>("Item4", false),
                    new KeyValuePair<string, bool>("Item5", true)
                }
            };

            var templateService = new TemplatesService(new FileSystemService(), new StringTemplateEngine());

            var result = templateService.Parse("first", model);

You can find detailed information about TemplateService and FileSystemService in my previous post how to create localizable text template engine using RazorEngine.

After that, put the break point after the last line (var result = ...) and run your application in Debug mode.
When the debugger stops on that break point just check the value of the result variable in the Text Visualizer.

If should contains the next text:

ID: 10
CreatedDate: 23.04.2012 15:54
Name: Name1
Price: 123.45
Items:
    item 1 - Item1  -
    item 2 - Item2  enabled
    item 3 - Item3  -
    item 4 - Item4  -
    item 5 - Item5  enabled

So, as you can see our renderer (AdvancedRenderer) allows us to specify string for formatting as we use usually for string.Format() method.

That's all.
Good luck.

April 19, 2012

Localizable text template engine using RazorEngine

In some cases you need to use something like text template engine in your applications.
The best example is sending the email messages from an application.
Of course you can write a subject and a body for email message directly in your code:

    var subject = string.Format("Details about item ID - {0}", item.Id);
    var body = string.Format(@"Dear {0} {1},
This is a details about your item ID - {2}.
Regards.", item.FirstName, item.LastName, item.Id);

And everything is OK unless somebody ask you to change the text of  a subject or a body message.
In that case you have to change it in the code, release your application and deploy it again.
It often happens that when you already finished the deployment, you receive the new text message for a body, and based on my experience you will receive that kind of messages again and again.
Then somebody can ask you - what about localization? You need to send one message in English and another message in German. Later somebody ask about a Korean message, etc.

So, it's good example where a text template engine could help you.

In this post i will show you how to use RazorEngine for it.


Using the RazorEngine


The following command in the Package Manager console will install RazorEngine package into your ASP.NET MVC 4 WebAPI application.

PM > Install-Package RazorEngine

RazorEngine is a templating engine built upon Microsoft's Razor parsing technology. The RazorEngine allows you to use Razor syntax to build robust templates. Currently RazorEngine has integrated the vanilla Html + Code support, but it would support other markup languages in future.

So, let's start with TemplateEngine interface:

    public interface ITemplateEngine
    {
        string Parse(string template, dynamic model);
    }

This interface introduce just one method which receive a template text and a data model for a template in a parameters and send the generated text back.

Continue with realization:

    public class RazorTemplateEngine : ITemplateEngine
    {
        public string Parse(string template, dynamic model)
        {
            return Razor.Parse(template, model);
        }
    }

It's really easy, just don't forget include RazorEngine to your using block.


The localized templates service


Our template engine is ready. But we don't want to just convert one text to another using string variables.
We would like to specify the template name, the template data model and the current culture, and get the generated text back.

For that reason I will create an TemplatesService class, but let's start with an interface first:

    public interface ITemplatesService
    {
        string Parse(string templateName, dynamic model, CultureInfo cultureInfo = null);
    }

This simple interface has only one method which takes the template name, data model and current culture as a parameters and will return the generated text as well.

Realization of this simple interface is not so simple, but i will explain all the methods later.
But before I show you the realization I would like to tell you that our TemplatesService class needs to do some file system operations, e.g. read all contents of the files, check if a file exists.

I suggest to create a separate interface (and realization of course) to do all of this file system tasks. It allows you to avoid a lot of problems in unit testing, and make your services more clear to another developers.

The interface for the file system operations:

    public interface IFileSystemService
    {
        string ReadAllText(string fileName);
        bool FileExists(string fileName);
        string GetCurrentDirectory();
    }

And really simple realization:

    public class FileSystemService : IFileSystemService
    {
        public string ReadAllText(string fileName)
        {
            return File.ReadAllText(fileName);
        }

        public bool FileExists(string fileName)
        {
            return File.Exists(fileName);
        }

        public string GetCurrentDirectory()
        {
            return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        }
    }

I hope everything is clear to you in this class.

So, let's return to realization of TemplatesService. I will show you the realization from methods to methods. The constants, the properties and a constructor of the class, first:

    public class TemplatesService : ITemplatesService
    {
        private const string DefaultLanguage = "en";
        private const string TemplatesDirectoryName = "Templates";
        private const string TemplateFileNameWithCultureTemplate = "{0}.{1}.template";
        private const string TemplateFileNameWithoutCultureTemplate = "{0}.template";
        
        private readonly IFileSystemService _fileSystemService;
        private readonly ITemplateEngine _templateEngine;
        private readonly string _templatesDirectoryFullName;

        public TemplatesService(IFileSystemService fileSystemService, ITemplateEngine templateEngine)
        {
            _fileSystemService = fileSystemService;
            _templateEngine = templateEngine;
            _templatesDirectoryFullName = Path.Combine(_fileSystemService.GetCurrentDirectory(), TemplatesDirectoryName);
        }

        // rest of the code
    }

Nothing complex in this code: just declaring the four constants where I specified the default language name, the name of the directory where the templates are stored, and the string templates for the file name of template with and without a culture.
Also, I stored the full path to templates directory in the _templateDirectoryFullName property in the constructor of the class.

Then, the implementation of the one public method which declared in the interface:

        public string Parse(string templateName, dynamic model, CultureInfo cultureInfo = null)
        {
            var templateContent = GetContent(templateName, cultureInfo);

            return _templateEngine.Parse(templateContent, model);
        }

It takes the content of the template from GetContent method and call the template engine to get a string result.

        private string GetContent(string templateName, CultureInfo cultureInfo)
        {
            var templateFileName = TryGetFileName(templateName, cultureInfo);
            if (string.IsNullOrEmpty(templateFileName))
            {
                throw new FileNotFoundException(string.Format("Template file not found for template '{0}' in '{1}'", templateName, _templatesDirectoryFullName));
            }

            return _fileSystemService.ReadAllText(templateFileName);
        }

Te method GetContent tries to take the template full file name (a file name with a path) from the method TryGetFileName, and if this method return null or empty string throws an exception. Otherwise it reads all the template file content and return it.

        private string TryGetFileName(string templateName, CultureInfo cultureInfo)
        {
            var language = GetLanguageName(cultureInfo);

            // check file for current culture
            var fullFileName = GetFullFileName(templateName, language);
            if (_fileSystemService.FileExists(fullFileName))
            {
                return fullFileName;
            }

            // check file for default culture
            if (language != DefaultLanguage) 
            {
                fullFileName = GetFullFileName(templateName, DefaultLanguage);
                if (_fileSystemService.FileExists(fullFileName))
                {
                    return fullFileName;
                }
            }

            // check file without culture
            fullFileName = GetFullFileName(templateName, string.Empty);
            if (_fileSystemService.FileExists(fullFileName))
            {
                return fullFileName;
            }

            return string.Empty;
        }

This method gets the language name from CultureInfo parameters, and checks is the template file for that language exist, and if no, checks is the template file for default language exists, and if it is not found then checks is the template file without any culture exist.
For example, look at the templates files structure:

    subject.template
    subject.de.template

Let's imagine, that the current culture is German. The language is "de". The method should check the template file for this language and should found the second template 'subject.de.template'.
Then, let's imagine, that for now, the current culture is Korean. The language is "ko". The method should check the template file for this language, and will not find it, because we don't have a template file for Korean culture. Then the method should check the template file for default language which is 'en', and will not find it as well. The latest check will be for the template file without any culture and the first one template 'subject.template' should be found.

The implementation of the GetLanguage method is really simple:

        private static string GetLanguageName(CultureInfo cultureInfo)
        {
            return cultureInfo != null ? cultureInfo.TwoLetterISOLanguageName.ToLower() : DefaultLanguage;
        }

It returns the two letter ISO language name or the default language name if culture is not specified.

And the last method:

        
        private string GetFullFileName(string templateName, string language)
        {
            var fileNameTemplate = string.IsNullOrEmpty(language) ? TemplateFileNameWithoutCultureTemplate : TemplateFileNameWithCultureTemplate;

            var templateFileName = string.Format(fileNameTemplate, templateName, language);

            return Path.Combine(_templatesDirectoryFullName, templateFileName);
        }

That's all with the TemplatesService.


Using the localizable template service


To demonstrate how to use this service let's create the template file first.
Create a directory 'Templates' in your project.
Then click the right mouse button on this directory in the 'Solution Explorer' and select 'Add' -> 'New Item...' (or just press Ctrl+Shift+A).
In the new window click on 'Visual C# Items' and select the 'Text File' in the list. Enter the file name - 'first.template' and click 'Add' button.

Then insert the next text into template file:

ID: @Model.Id
Name: @Model.Name
Items:
@for(int i = 0; i < @Model.Items.Count; i++) {
    @:item #@i - @Model.Items[i]
}

Then write some simple code to parse the template:

            var model = new {
                Id = 10,
                Name = "Name1",
                Items = new List<string> {"Item1", "Item2", "Item3", "Item4", "Item5"}
            };

            var templateService = new TemplatesService(new FileSystemService(), new RazorTemplateEngine());

            var result = templateService.Parse("first", model);

After that, put the break point after the last line (var result = ...) and run your application in Debug mode.
When the debugger stops on that break point just check the value of the result variable in the Text Visualizer.

If should contains the next text:

ID: 10
Name: Name1
Items:
    item #0 - Item1
    item #1 - Item2
    item #2 - Item3
    item #3 - Item4
    item #4 - Item5

In my next post you can find how to create a localizable text template engine using StringTemplate.

That's all.
Good luck.