:::: MENU ::::

Monday, July 4, 2016

If you developed professional Web applications using ASP.NET MVC, you are probably familiar with Dependency Injection. Dependency Injection (DI) is a technique to develop loosely coupled software systems. ASP.NET MVC didn't include any inbuilt DI framework and developers had to resort to some external DI framework. Luckily, ASP.NET Core 1.0 introduces a DI container that can simplify your work. This article introduces you to the DI features of ASP.NET Core 1.0 so that you can quickly use them in your applications.
Note: This article is based on RC2 of ASP.NET Core 1.0. Make sure to install RC2 before you follow the examples discussed in this article. Please follow this link for more details about usingDependency Injection in ASP.NET Core 1.0.
To understand how Dependency Injection works in ASP.NET Core 1.0, you will build a simple application. So, begin by creating a new ASP.NET Core 1.0 Web application by using an Empty project template.
"dependencies": {
   "Microsoft.NETCore.App": {
      "version": "1.0.0-rc2-3002702",
      "type": "platform"
   },

    
   "Microsoft.AspNetCore.Mvc": "1.0.0-rc2-final",
   "Microsoft.AspNetCore.Razor.Tools": {
      "version": "1.0.0-preview1-final",
      "type": "build"
   },
   "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0-rc2-final",
   "Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-final",
   "Microsoft.AspNetCore.StaticFiles": "1.0.0-rc2-final",


   "Microsoft.EntityFrameworkCore.SqlServer": "1.0.0-rc2-final",
   "Microsoft.EntityFrameworkCore.Tools": {
      "version": "1.0.0-preview1-final",
      "type": "build"
   },


   "Microsoft.Extensions.Configuration.EnvironmentVariables":
      "1.0.0-rc2-final",
   "Microsoft.Extensions.Configuration.Json": "1.0.0-rc2-final",


   "Microsoft.VisualStudio.Web.CodeGeneration.Tools": {
      "version": "1.0.0-preview1-final",
      "type": "build"
   },
   "Microsoft.VisualStudio.Web.CodeGenerators.Mvc": {
      "version": "1.0.0-preview1-final",
      "type": "build"
   }
}
Make sure to restore packages by right-clicking the References folder and selecting Restore Packages from the shortcut menu.
Then, create a DIClasses folder under the project root folder. Add an interface named IServiceType to the DIClasses folder. A type that is to be injected is called a service type. The IServiceType interface will be implemented by the service type you create later. The IServiceType interface is shown below:
public interface IServiceType
{
   string GetGuid();
}

The IServiceType interface contains a single method—GetGuid(). As the name suggests, an implementation of this method is supposed to return a GUID to the caller. In a realistic case, you can have any application-specific methods here.
Then, add a MyServiceType class to the Core folder and implement IServiceType in it. The MyServiceType class is shown below:
public class MyServiceType:IServiceType
{
   private string guid;

   public MyServiceType()
   {
      this.guid = Guid.NewGuid().ToString();
   }

   public string GetGuid()
    {
      return this.guid;
   }
}
The MyServiceType class implements an IServiceType interface. The class declares a private variable—guid—that holds a GUID. The constructor generates a new GUID using the Guid structure and assigns it to the guid private variable. The GetGuid() method simply returns the GUID to the caller. So, every object instance of MyServiceType will have its own unique GUID. This GUID will be used to understand the working of the DI framework as you will see later.
Now, open the Startup.cs file and modify it as shown below:
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
   services.AddScoped();
}

public void Configure(IApplicationBuilder app)
{
   app.UseStaticFiles();
   app.UseMvc(routes =>
   {
      routes.MapRoute(
         name: "default",
         template: "{controller=Home}/
            {action=Index}/{id?}");
   });
}
Notice the line shown in bold letters. This is how you register a service type with the ASP.NET Core DI container. The AddScoped() method is a generic method and you mention the interface on which the service type is based (IServiceType) and a concrete type (MyServiceType) whose object instance is to be injected.
A type injected with AddScoped() has a lifetime of the current request. That means each request gets a new object of MyServiceType to work with. Let's test this by injecting MyServiceType into a controller.
Proceed by adding HomeController and Index view to the respective folders. Then, modify the HomeController as shown below:
public class HomeController : Controller
{
       
   private IServiceType obj;

   public HomeController(IServiceType obj)
   {
      this.obj = obj;
   }

   public IActionResult Index()
   {
      ViewBag.Guid = obj.GetGuid();
      return View();
   }
}
The constructor of the HomeController accepts a parameter of IServiceType. This parameter will be injected by the DI framework for you. Remember that, for the DI to work as expected, a type must be registered with the DI container (as discussed earlier).
The IServiceType injected by the DI framework is stored in a private variable—obj—for later use. The Index() action calls the GetGuid() method on MyServiceType object and stores the GUID in ViewBag's Guid property. The Index view simply outputs this GUID as shown below:

@ViewBag.Guid

Now, run the application and you should see something like this:
Refresh the browser window a few times to simulate multiple requests. You will observe that a new GUID is displayed every time. This confirms the working of AddScoped() as discussed previously.
There are two more methods that can be used to control the lifetime of the injected object—AddTransient() and AddSingleton(). A service registered using AddTransient() behaves such that every request for an object gets a new object instance. So, if a single HTTP request requests a service type twice, two separate object instances will be injected. A service registered using AddSingleton() behaves such that all the requests to a service are served by a single object instance. Let's test these two methods, one by one.
Modify Startup.cs as shown below:
public void ConfigureServices(IServiceCollection services)
{
   services.AddMvc();
   services.AddTransient();
}
In this case, you used the AddTransient() method to register the service type. Now, modify the HomeController like this:
public class HomeController : Controller
{
       
   private IServiceType obj1;
   private IServiceType obj2;

   public HomeController(IServiceType obj1,IServiceType obj2)
   {
      this.obj1 = obj1;
      this.obj2 = obj2;
   }

   public IActionResult Index()
   {
      ViewBag.Guid1 = obj1.GetGuid();
      ViewBag.Guid2 = obj2.GetGuid();
      return View();
   }
}
This time, the HomeController has two parameters of IServiceType. This is done just to simulate two requests to the same service type. The GUIDs returned by both the object instances are stored in the ViewBag. If you output the GUIDs on the Index view, you will see this:
As you can see, the GUIDs are different within a single HTTP request, indicating that different object instances are getting injected into the controller. If you refresh the browser window, you will get different GUIDs each time. Now, modify Startup.cs and use AddScoped() again to register the type. Run the application again. Did you notice the difference? Now, both the constructor parameters point to the same object instance, as confirmed by the GUIDs.
Now, change Startup.cs to use the AddSingleton() method:
public void ConfigureServices(IServiceCollection services)
{
   services.AddMvc();
   services.AddSingleton();
}
Also, make corresponding changes to the HomeController (it will now have just one parameter) and the Index view. If you run the application and refresh the browser as before, you will observe that for all the requests the same GUID is displayed, confirming the singleton mode.