Chitika

Showing posts with label ASP.NET MVC 4. Show all posts
Showing posts with label ASP.NET MVC 4. Show all posts

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.

April 6, 2012

Dependency Injection in ASP.NET MVC 4 and WebAPI using Unity

In this post, I will demonstrate how to use Dependency Injection in ASP.NET MVC 4 application and WebAPI using Unity. The new ASP.NET MVC 4 is a great framework for building web applications and WebAPI is a great for building HTTP services. I will use Unity IoC container to provide the integration with ASP.NET MVC 4 and WebAPI for applying dependency injection.

Using Unity in ASP.NET MVC 4


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

PM > Install-Package Unity.Mvc3

Unity.Mvc3 is a package that allows simple Integration of Microsoft's Unity IoC container with ASP.NET MVC 3. It also works great for ASP.NET MVC 4.

After installation of the package you will find the Bootstrapper.cs file in the root of your ASP.NET MVC 4 WebAPI project. The course code of that file is:

    public static class Bootstrapper
    {
        public static void Initialise()
        {
            var container = BuildUnityContainer();

            DependencyResolver.SetResolver(new UnityDependencyResolver(container));
        }

        private static IUnityContainer BuildUnityContainer()
        {
            var container = new UnityContainer();

            // register all your components with the container here
            // e.g. container.RegisterType<itestservice, testservice="">();            

            return container;
        }
    }

We will return to this class a little bit later.

To get started, we should add a call to Bootstrapper.Initialize() in the end of the Application_Start method of Global.asax.cs and the MVC framework will then use the Unity.Mvc3 DependencyResolver to resolve your components.

        protected void Application_Start()
        {
            // Default code of the method
            // . . .

            // Initialization of our Unity container
            Bootstrapper.Initialise();
        }


Using Unity in ASP.NET MVC 4 WebAPI


Unfortunately Unity.Mvc3 doesn't change the DependencyResolver for WebAPI. I hope it will be implemented in Unity.Mvc4.
However, there is the nuget package that has already implemented needed functionality - Unity.WebAPI.

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

PM > Install-Package Unity.WebAPI

Unity.WebAPI is a library that allows simple Integration of Microsoft's Unity IoC container with ASP.NET's WebAPI. This project includes a bespoke DependencyResolver that creates a child container per HTTP request and disposes of all registered IDisposable instances at the end of the request.

After installation of the package you just have to add one line of code to your Bootstrapper class into the Initialise method:

        public static void Initialise()
        {
            var container = BuildUnityContainer();

            DependencyResolver.SetResolver(new UnityDependencyResolver(container));

            // register dependency resolver for WebAPI RC
            GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
            // if you still use the beta version - change above line to:
            //GlobalConfiguration.Configuration.ServiceResolver.SetResolver(new Unity.WebApi.UnityDependencyResolver(container));
        }

After that you are ready to create your business logic.

Create service


Let's start with the service class that we want to use in our containers.

First, we will create the interface:

    public interface IValuesService
    {
        int Create(string value);
        string Update(int id, string value);
        void Delete(int id);

        IDictionary<int, string> GetAll();
        string Get(int id);
    }

And the service class which contains realization of this interface:

    public class ValuesService : IValuesService
    {
        private Dictionary<int, string> _values;

        public ValuesService()
        {
            _values = new Dictionary<int, string>
                          {
                              {1, "Value 1"},
                              {2, "Value 2"},
                              {3, "Value 3"},
                              {4, "Value 4"},
                              {5, "Value 5"},
                          };
        }

        private int GetNextId()
        {
            return _values.Keys.Max() + 1;
        }

        public int Create(string value)
        {
            var id = GetNextId();
            _values.Add(id, value);
            return id;
        }

        public string Update(int id, string value)
        {
            _values[id] = value;
            return Get(id);
        }

        public void Delete(int id)
        {
            _values.Remove(id);
        }

        public IDictionary<int, string> GetAll()
        {
            return _values;
        }

        public string Get(int id)
        {
            return _values[id];
        }
    }


This is the really simple service with some predefined values in the constructor (just for this simple example). Of course in the real life your services will be much more complex.

Register service


The next step is register our service and interface in Unity container. This is very simple, you just have to add one line of code to the Bootstrapper class into the BuildUnityContainer method:

        private static IUnityContainer BuildUnityContainer()
        {
            var container = new UnityContainer();

            // register values service
            container.RegisterType<IValuesService, ValuesService>();

            return container;
        }

As you can see it is really simple.
Also, if you read this method carefully you should see that Unity.Mvc3 registered all of our controllers by default in the Unity container. This is the line where it's happened:

            container.RegisterControllers();


Inject service to Controller


So, let's get our service in the home controller:

    public class HomeController : Controller
    {
        private readonly IValuesService _valuesService;

        public HomeController(IValuesService valuesService)
        {
            _valuesService = valuesService;
        }

        public ActionResult Values()
        {
            var viewModel = _valuesService.GetAll();

            return View(viewModel);
        }


        // old code
        public ActionResult Index()
        {
            return View();
        }
    }

I've just added the constructor which receive IValuesService as a parameters. And Unity will do all the "magic" of resolving out service interface for us.
Then. to test it, let's create a simple view named as the same as the action - Values.cshtml (tip: you can create a view just clicking the right mouse button on the action name, and selecting 'Add View...' in the context menu):

@model Dictionary<int,string>

@{
    ViewBag.Title = "Values";
}

<h2>Values</h2>

<ul>
    @foreach(var item in Model)
    {
        <li>ID: @item.Key, Value: @item.Value</li>
    }
</ul>

Then, compile our solution and run it.
Then, navigate to http://localhost:<your port number>/Home/Values. You should see the list of the five values with ID.
If you see it then injection for our Controllers works properly.

Inject service to ApiController


Next, let's inject our service to ApiControllers:

    public class ValuesController : ApiController
    {
        private readonly IValuesService _valuesService;
        
        public ValuesController(IValuesService valuesService)
        {
            _valuesService = valuesService;
        }

        // GET /api/values
        public IEnumerable<KeyValuePair<int, string>> Get()
        {
            return _valuesService.GetAll();
        }

        // GET /api/values/5
        public string Get(int id)
        {
            return _valuesService.Get(id);
        }

        // POST /api/values
        public void Post(string value)
        {
            _valuesService.Create(value);
        }

        // PUT /api/values/5
        public void Put(int id, string value)
        {
            _valuesService.Update(id, value);
        }

        // DELETE /api/values/5
        public void Delete(int id)
        {
            _valuesService.Delete(id);
        }
    }

To test is everything fine with the ApiController, just compile the solution and run it.
After that, open the IE developers tools and click the 'Start capturing' button in the Network tab.
Then, navigate to http://localhost:<your port number>/api/values.
You should see something like this in the Response body tab:

[{"key":1,"value":"Value 1"},{"key":2,"value":"Value 2"},{"key":3,"value":"Value 3"},{"key":4,"value":"Value 4"},{"key":5,"value":"Value 5"}]

So, for now all of your Controllers and ApiControllers can use your services.

That's all.

UPDATED:
You can download sources at: UnityApplication14.zip

March 26, 2012

ASP.NET MVC 4 WebAPI. Support Areas in HttpControllerFactory

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

Unfortunately DefaultHttpControllerFactory doesn't support Areas by default.
To support it you have to write your HttpControllerFactory from scratch.

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

AreaHttpControllerFactory


First of all, you have to implement IHttpControllerFactory interface:
    public class AreaHttpControllerFactory : IHttpControllerFactory
    {
        public IHttpController CreateController(HttpControllerContext controllerContext, string controllerName)
        {
            throw new NotImplementedException();
        }

        public void ReleaseController(IHttpController controller)
        {
            throw new NotImplementedException();
        }
    }
We will implement two obligatory methods CreateController and ReleaseController later.

Let's start with fields and constructor:
        private const string ControllerSuffix = "Controller";
        private const string AreaRouteVariableName = "area";

        private IHttpControllerFactory _defaultFactory;
        private HttpConfiguration _configuration;
        private Dictionary<string, Type> _apiControllerTypes;

        public AreaHttpControllerFactory(HttpConfiguration configuration)
        {
            _configuration = configuration;
            _defaultFactory = new DefaultHttpControllerFactory(configuration);
        }
Our class is wrapper around DefaultHttpControllerFactory.
I hope i don't need to explain meaning of ControllerSuffix constant. But I would like to explain the AreaRouteVariableName constant - it contains the name of the variable which we will use to specify area name  in Routes collection.

In the _apiControllerTypes we will store all the API controllers types, so let's create private property:
        private Dictionary<string, Type> ApiControllerTypes
        {
            get
            {
                if (_apiControllerTypes != null)
                {
                    return _apiControllerTypes;
                }

                var assemblies = AppDomain.CurrentDomain.GetAssemblies();

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

                return _apiControllerTypes;
            }
        }

This code, just 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 the one of our main methods. I will start with ReleaseController method:
        public void ReleaseController(IHttpController controller)
        {
            _defaultFactory.ReleaseController(controller); 
        }
Easy.

The last method will do all the "magic" for us:
        public IHttpController CreateController(HttpControllerContext controllerContext, string controllerName)
        {
            var controller = GetApiController(controllerContext, controllerName);
            return controller ?? _defaultFactory.CreateController(controllerContext, controllerName);
        }
Easy as well. :)
And the method which will find the controller for us:
        private IHttpController GetApiController(HttpControllerContext controllerContext, string controllerName)
        {
            if (!controllerContext.RouteData.Values.ContainsKey(AreaRouteVariableName))
            {
                return null;
            }

            var areaName = controllerContext.RouteData.Values[AreaRouteVariableName].ToString().ToLower();
            if (string.IsNullOrEmpty(areaName))
            {
                return null;
            }

            var type = ApiControllerTypes.Where(t => t.Key.ToLower().Contains(string.Format(".{0}.", areaName)) && t.Key.EndsWith(string.Format(".{0}{1}", controllerName, ControllerSuffix), StringComparison.OrdinalIgnoreCase)).Select(t => t.Value).FirstOrDefault();
            if (type == null)
            {
                return null;
            }

            return CreateControllerInstance(controllerContext, controllerName, type);
        }
So, if an area variable is specifying in RouteData.Values and this variable is not null or not empty, then it 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).
If the controller type is found, then it will calls CreateControllerInstance method. Otherwise, the method will return null.

And the code for CreateControllerInstance:
        private IHttpController CreateControllerInstance(HttpControllerContext controllerContext, string controllerName, Type controllerType)
        {
            var descriptor = new HttpControllerDescriptor(_configuration, controllerName, controllerType);
            controllerContext.ControllerDescriptor = descriptor;
            var controller = descriptor.HttpControllerActivator.Create(controllerContext, controllerType);
            controllerContext.Controller = controller;
            return controller;
        }

Registering AreaHttpControllerFactory


The next thing you have to do is to say to your application to use this controller factory instead of DefaultHttpControllerFactory. 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.ServiceResolver.SetService(typeof(IHttpControllerFactory), new AreaHttpControllerFactory(GlobalConfiguration.Configuration));
        }
That's all.

Using AreaHttpControllerFactory

If you did everything right, now you can forget about that "nightmare" code. 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 = AreaName, id = RouteParameter.Optional }
            );

            // other mappings
        }

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

March 14, 2012

ASP.NET MVC 4 WebAPI authorization

In the examples of ASP.NET MVC 4 WebAPI you can find that authorization is really easy.
You just have to add [Authorize] attribute to your controller or for some actions which need it.

And if you do this you will expect that your WebAPI will return error code 401 (Not authorized) to your client.

But unfortunately it's not happened.
And you can ask: what will happen in the real world?
I can answer: your browser just get the 302 (Found) status code and will redirect you to the login page.

I think it's not expected behavior for you. Because you want to get just 401 status code in the client.

And I can show you how you can achieve it.

1. Please, double sure that you use AuthorizeAttribute from the System.Web.Http library instead of one from the System.Web.Mvc.

2. Add a directory and two classes to your code which should "FIX" it:

- Add App_Start directory to your solution.
       We will create two classes in this directory in a minute.

Add first class into that folder:  
       This class is a HTTP module which do all the 'magic'.
       The 'magic' is simple - just set the marker in PosrReleaseRequestState event if this is an ajax request and if our action returns status code equals to 401 (Unauthorized) or 403 (Forbidden). Then in OnEndRequest we have to check is this marker exists, and if yes, then set the returned status code from an action back.
public class AjaxFormsAuthenticationModule : IHttpModule

    {

        private const string FixupKey = "__WEBAPI:Authentication-Fixup";

        public void Dispose()

        {

        }

        public void Init(HttpApplication context)

        {

            context.PostReleaseRequestState += OnPostReleaseRequestState;

            context.EndRequest += OnEndRequest;

        }

        private void OnPostReleaseRequestState(object source, EventArgs args)

        {

            var context = (HttpApplication)source;

            var response = context.Response;

            var request = context.Request;

            bool isAjax = request.Headers["X-Requested-With"] == "XMLHttpRequest";

            if ((response.StatusCode == 401 || response.StatusCode == 403) && isAjax)

            {

                context.Context.Items[FixupKey] = response.StatusCode;

            }

        }

        private void OnEndRequest(object source, EventArgs args)

        {

            var context = (HttpApplication)source;

            var response = context.Response;

            if (context.Context.Items.Contains("__WEBAPI:Authentication-Fixup"))

            {

                response.StatusCode = (int)context.Context.Items[FixupKey];

                response.RedirectLocation = null;

            }

        }

    }

Add second class into that folder:
       This class will just register our HTTP module for our application..
using Microsoft.Web.Infrastructure.DynamicModuleHelper;

[assembly: PreApplicationStartMethod(typeof(FormsAuthenticationFixer), "Start")]

namespace LoginVS11.App_Start

{

    public static class FormsAuthenticationFixer

    {

        public static void Start()

        {

            DynamicModuleUtility.RegisterModule(typeof(AjaxFormsAuthenticationModule));

        }

    }

}

That's all.

After that all of your ajax requests will get the 401 status code if your client is not authorized yet.

March 5, 2012

ASP.NET MVC 4. Real application. Design, develop, testing.

In the next several posts i will show you how to create a real application in ASP.NET MVC 4.

I will try to cover all the aspects of creating an application.

I will start from design, where i will explain some general patterns.

Then I will show you how you can work with data through Entity Framework Code First, how you can migrate your database via Fluent Migrator.

Then the general principles of jQuery and jQuery UI. How you can create a version of your UI for mobile devices.

The last but not least - unit and integration testing of your application using Moq library and using database migration.


Table of contents:

  1. Design your application in ASP.NET MVC 4. (coming soon)
  2. General patterns - Repository, UnitOfWork. (coming soon)
  3. Entity Framework Code First in action. (coming soon)
  4. Database migrations with Fluent Migrator. (coming soon)
  5. Testing your repositories. (coming soon)
  6. Services via Web API. (coming soon)
  7. Business logic of the application. (coming soon)
  8. Unit testing using Moq library. (coming soon)
  9. Authentication and authorization with jQuery (coming soon)
  10. UI with jQuery. (coming soon)
  11. UI for mobile devices. (coming soon)
  12. Testing your UI. (coming soon)
  13. Create installation with Wix. (coming soon)

March 4, 2012

ASP.NET MVC 4 Beta has been relesed


Top Features

  • ASP.NET Web API
  • Refreshed and modernized default project templates
  • New mobile project template
  • Many new features to support mobile apps
  • Recipes to customize code generation
  • Enhanced support for asynchronous methods

You can read a detailed information at:
ASP.NET MVC official site

Download

You can download ASP.NET MVC 4 Beta for Visual Studio 2010:

Or you can download Visual Studio 11 Beta (includes ASP.NET MVC 4 Beta):