WCF Service Injection In Controller Using Castle Windsor

Introduction

In this post, we will see how to inject WCF service dependency in the controller in ASP.NET MVC.

Background

When working with web applications, normally we have persistent storage of data like database, xml, files, NoSQL , and we have data access in place in our controller actions to do operations on that data. Sometimes we fetch it for displaying, saving new data, or updating existing records.

Nowadays service oriented applications are very common and there is trend of making service oriented applications so that we can add or remove features from applications easily or alter implementation without messing the things.

WCF is one of the technology used which acts as a communication bridge between client application and persistent storage or database. We will discuss next with code sample how it is done normally.

Ordinary Approach

Normally, we create a WCF service project, create our Service Contracts in form of interfaces which tells what i take as input and what i would return to called and then others can implement those service contracts to tell how to do that. Here is an example of Service Contract:

  1. [ServiceContract]  
  2. public interface IUserService  
  3. {  
  4.     [OperationContract]  
  5.     IList GetUsers();  
  6.   
  7.     [OperationContract]  
  8.     User RegisterUser(User user);  
  9.   
  10.     [OperationContract]  
  11.     User Login(string id,string password);  
  12.   
  13.     [OperationContract]  
  14.     bool UserNameExists(string username, string email);  
  15.   
  16. }  
And we then provide the implementation of contract:
  1. public class UserService : IUserService  
  2. {  
  3.     private IConnectionFactory connectionFactory;  
  4.   
  5.     public IList GetUsers()  
  6.     {  
  7.         connectionFactory = ConnectionHelper.GetConnection();  
  8.   
  9.         var context = new DbContext(connectionFactory);  
  10.   
  11.         var userRep = new UserRepository(context);  
  12.   
  13.         return userRep.GetUsers();  
  14.     }  
  15.   
  16.     public User RegisterUser(User user)  
  17.     {  
  18.         connectionFactory = ConnectionHelper.GetConnection();  
  19.   
  20.         var context = new DbContext(connectionFactory);  
  21.   
  22.         var userRep = new UserRepository(context);  
  23.   
  24.         return userRep.CreateUser(user);  
  25.     }  
  26.   
  27.   
  28.     public User Login(string id, string password)  
  29.     {  
  30.         connectionFactory = ConnectionHelper.GetConnection();  
  31.   
  32.         var context = new DbContext(connectionFactory);  
  33.   
  34.         var userRep = new UserRepository(context);  
  35.   
  36.         return userRep.LoginUser(id,password);  
  37.     }  
  38.   
  39.     public bool UserNameExists(string username,string email)  
  40.     {  
  41.         connectionFactory = ConnectionHelper.GetConnection();  
  42.   
  43.         var context = new DbContext(connectionFactory);  
  44.   
  45.         var userRep = new UserRepository(context);  
  46.   
  47.         var user = userRep.GetUserByUsernameOrEmail(username,email);  
  48.         return !(user != null && user.UserID > 0);  
  49.   
  50.     }  
  51. }  
Now client application (in our case mvc application) would add Service Reference in the project and call the Service as in the following:
  1. public class AccountController : Controller  
  2. {  
  3.   
  4.     [HttpPost]  
  5.     [AllowAnonymous]  
  6.     public ActionResult SignUp(RegisterViewModel registerVM)  
  7.     {  
  8.         if (ModelState.IsValid)  
  9.         {  
  10.             UserService authenticateService = new UserService();  // this is bad design high coupling of components   
  11.   
  12.             var result = authenticateService.RegisterUser(registerVM);  
  13.   
  14.             RegisterViewModel vm = result;  
  15.   
  16.             return View(vm);  
  17.   
  18.         }  
  19.         return View(registerVM);  
  20.     }  
  21.   
  22.   
  23.     [HttpPost]  
  24.     [AllowAnonymous]  
  25.     [ValidateAntiForgeryToken]  
  26.     public ActionResult SignIn(LoginViewModel loginVm)  
  27.     {  
  28.         if (ModelState.IsValid)  
  29.         {  
  30.             UserService authenticateService = new UserService();  // this is bad design high coupling of components  
  31.   
  32.             var user = authenticateService.Login(loginVm.UserName, loginVm.Password);  
  33.   
  34.             if (user == null)  
  35.                 ModelState.AddModelError("""The user name or password provided is incorrect.");  
  36.   
  37.             Session["User"] = user;  
  38.   
  39.             return RedirectToAction("Index""Home");  
  40.   
  41.         }  
  42.   
  43.         return View(loginVm);  
  44.     }  
  45. }  
What's the Problem

If you note the above two action methods, they look fine but there is one line which is a bad design approach and void Single Responsibility Principle and it also create high coupling between our controller and Service implementation. In future if we have to use some different implementation of IUserService, let's say new implementation which uses Entity Framework or some other Data Access Technique like MongoDB, Azure or Rest Services with JSON, we will have to change our actions to use different class, which is not very pleasant.

Dependency Injection

Here comes the role of dependency injection that is a technique / design pattern which we will be used here. As IUserService is a dependency of our Controller which is needed for the AccountController to do the job successfully.

As the name reflects it is used for injecting dependencies of an implementation, there can be many dependencies or can be only one depends on the scenario, but in this example we have one dependency of our Controller which is IUserService.

Castle Windsor to Help Here

Castle Windsor is a Inversion of Control container, it can instantiate the dependencies right at the place where we need them. Dependency Injection and Inversion of Control are mostly used together, when we want dependencies to be injected, we have to use Inversion of Control as well.

For this, first of all we will have to add the library in our project from Nuget or we can download assemblies and add references to assemblies explicitly. After installing the library we can see reference to Castle.Core and Castle.Windsor in References of project:

jira

Now first step is to implement the installer for CastleWindsor in which we will be telling the dependencies that will be injected by container on runtime when needed.
  1. public class WindsorInstaller : IWindsorInstaller  
  2. {  
  3.     public void Install(IWindsorContainer container, IConfigurationStore store)  
  4.     {  
  5.         // registering all Controllers of the Assembly  
  6.         container.Register(Classes.FromThisAssembly()  
  7.                             .BasedOn()  
  8.                             .LifestyleTransient());  
  9.   
  10.         // registeting our WcfInterceptor to intercept all WCF Service calls  
  11.         container.Register(Component  
  12.           .For()  
  13.           .ImplementedBy()  
  14.           .Named("wcf"));  
  15.   
  16.         // Registering IUserService  
  17.         container.Register(Types  
  18.             .FromAssemblyContaining()  
  19.             .Where(x => x.IsInterface)  
  20.             .LifestyleTransient()  
  21.             .Configure(x =>  
  22.             { var res = x.Interceptors(InterceptorReference.ForKey("wcf")).Anywhere; }));  
  23.   
  24.         // Registering implementation for IClientFactory which is dependency of WCFInterceptor implementation  
  25.         container.Register(Component  
  26.             .For()  
  27.             .ImplementedBy());  
  28.   
  29.     }  
The following is the implementation of registered dependencies above. Firstly, here is the implementation for WcfInterceptor:
  1. public class WcfInterceptor : IInterceptor  
  2. {  
  3.     public IClientFactory ClientFactory { getset; }  
  4.   
  5.     public void Intercept(IInvocation invocation)  
  6.     {  
  7.         var clientProvider = ClientFactory.GetClientProvider(invocation.Method.DeclaringType);  
  8.         try  
  9.         {  
  10.             clientProvider.Open();  
  11.   
  12.             invocation.ReturnValue = CallClientProviderMethod(invocation, clientProvider);  
  13.         }  
  14.         finally  
  15.         {  
  16.             clientProvider.Close();  
  17.         }  
  18.     }  
  19.   
  20.     private object CallClientProviderMethod(IInvocation invocation, IClientProvider clientProvider)  
  21.     {  
  22.         var proxy = clientProvider.GetProxy();  
  23.         return invocation.Method.Invoke(proxy, invocation.Arguments);  
  24.     }  
  25. }  
You can see the property ClientFactory of type IClientFactory, which is a dependency as it is being used in Intercept method, and Intercept will get called when from client side we will execute any method of WCF Service. For example: RegisterUser() method of Sign up action.

Here is the implementation of WcfClientFactory:
  1. public class WcfClientFactory : IClientFactory  
  2. {  
  3.     public IClientProvider GetClientProvider(Type type)  
  4.     {  
  5.         var closedType = typeof(WcfClientProvider<>).MakeGenericType(type);  
  6.         return (IClientProvider)Activator.CreateInstance(closedType);  
  7.     }  
  8. }  
Which just returns instance of WcfClientProvider<T>, the implementation of WcfClientprovide<T> is:
  1. public class WcfClientProvider : IClientProvider  
  2. {  
  3.     private ChannelFactory factory;  
  4.   
  5.     public WcfClientProvider()  
  6.     {  
  7.         factory = new ChannelFactory(string.Empty);  
  8.     }  
  9.   
  10.     public object GetProxy()  
  11.     {  
  12.         return factory.CreateChannel();  
  13.     }  
  14.   
  15.     public void Open()  
  16.     {  
  17.         if (this.factory.State != CommunicationState.Opened)  
  18.         {  
  19.             factory.Open();  
  20.         }  
  21.     }  
  22.   
  23.     public void Close()  
  24.     {  
  25.         factory.Close();  
  26.     }  
  27. }  
Now we have to define Controller Factory as well, because we have Registered IController in container. We now will have to provide our own implementation of Controller Factory whose purpose is to create controller instance passing the instantiated dependencies of it.

Now the last step is to install Castle Windsor on Application start and instantiation of our Controller Factory in Global.asax.

This is how your Global.asax code should look like:
  1. public class MvcApplication : System.Web.HttpApplication  
  2. {  
  3.   
  4.     private static IWindsorContainer container;  
  5.   
  6.     protected void Application_Start()  
  7.     {  
  8.         AreaRegistration.RegisterAllAreas();  
  9.   
  10.         WebApiConfig.Register(GlobalConfiguration.Configuration);  
  11.         FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);  
  12.         RouteConfig.RegisterRoutes(RouteTable.Routes);  
  13.         BootstrapContainer();  
  14.     }  
  15.   
  16.   
  17.     private static void BootstrapContainer()  
  18.     {  
  19.         container = new WindsorContainer()  
  20.             .Install(FromAssembly.This());  
  21.         var controllerFactory = new WindsorControllerFactory(container.Kernel);  
  22.         ControllerBuilder.Current.SetControllerFactory(controllerFactory);  
  23.     }  
  24. }  
Now we will have to change our AccountController code to add a constructor which takes IUserService instance as parameter (dependency) which will be instantiated by our Ioc Container.

Now our controller will look like the following:
  1. public class AccountController : Controller  
  2. {  
  3.     private IUserService authenticateService;  
  4.   
  5.     public AccountController(IUserService authenticateService)  
  6.     {  
  7.         this.authenticateService = authenticateService;  
  8.     }  
  9.   
  10.     [HttpPost]  
  11.     [AllowAnonymous]  
  12.     [ValidateAntiForgeryToken]  
  13.     public ActionResult SignIn(LoginViewModel loginVm)  
  14.     {  
  15.         if (ModelState.IsValid)  
  16.         {  
  17.             var user = authenticateService.Login(loginVm.UserName, loginVm.Password);  
  18.   
  19.             if (user == null)  
  20.                 ModelState.AddModelError("""The user name or password provided is incorrect.");  
  21.   
  22.             Session["User"] = user;  
  23.   
  24.             return RedirectToAction("Index""Home");  
  25.   
  26.         }  
  27.   
  28.         return View(loginVm);  
  29.     }  
  30.   
  31.     [HttpPost]  
  32.     [AllowAnonymous]  
  33.     public ActionResult SignUp(RegisterViewModel registerVM)  
  34.     {  
  35.         if (ModelState.IsValid)  
  36.         {  
  37.   
  38.             var result = authenticateService.RegisterUser(registerVM);  
  39.   
  40.             RegisterViewModel vm = result;  
  41.   
  42.             return View(vm);  
  43.   
  44.         }  
  45.         return View(registerVM);  
  46.     }  
Now our code is much better, it is following single responsibility principle and it is component based. We can also write Unit Tests for our actions as our all dependencies are to be provided via constructor, so unit tests are easy to write and run.

 

Next Recommended Readings