Dependency Injection (DI) is a design pattern that allows for the decoupling of components in an application. In ASP.NET Web API, DI is used to manage dependencies between controllers and their services, making the code more modular, testable, and maintainable. This guide will explain how to implement dependency injection in ASP.NET Web API controllers with sample code.

Why Use Dependency Injection?

Using dependency injection in your Web API controllers offers several benefits:

  • Decoupling: It reduces the coupling between classes, making it easier to change implementations without affecting dependent classes.
  • Testability: DI makes it easier to write unit tests for your controllers by allowing you to inject mock or stub implementations of dependencies.
  • Configuration Management: It centralizes the configuration of dependencies, making it easier to manage and change them as needed.

Step 1: Define Your Services

First, define the service interface and its implementation that you want to inject into your controller. For example, let's create a simple product service:

        
public interface IProductService
{
IEnumerable<Product> GetAllProducts();
Product GetProductById(int id);
void AddProduct(Product product);
}

public class ProductService : IProductService
{
private static List<Product> products = new List<Product>
{
new Product { Id = 1, Name = "Product A", Price = 10.0M },
new Product { Id = 2, Name = "Product B", Price = 20.0M }
};

public IEnumerable<Product> GetAllProducts()
{
return products;
}

public Product GetProductById(int id)
{
return products.FirstOrDefault(p => p.Id == id);
}

public void AddProduct(Product product)
{
products.Add(product);
}
}

public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}

Step 2: Register Your Services with a Dependency Injection Container

You need to register your service with a DI container. ASP.NET Web API does not come with a built-in DI container, but you can use popular containers like Autofac, Ninject, or Unity. Below is an example using the built-in Microsoft.Extensions.DependencyInjection container.

        
using System.Web.Http;
using Microsoft.Extensions.DependencyInjection;

public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Register services
var services = new ServiceCollection();
services.AddScoped<IProductService, ProductService>();
var serviceProvider = services.BuildServiceProvider();
config.DependencyResolver = new DefaultDependencyResolver(serviceProvider);

// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}

public class DefaultDependencyResolver : IDependencyResolver
{
private readonly IServiceProvider _serviceProvider;

public DefaultDependencyResolver(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}

public object GetService(Type serviceType)
{
return _serviceProvider.GetService(serviceType);
}

public IEnumerable<object> GetServices(Type serviceType)
{
return (IEnumerable<object>)_serviceProvider.GetService(serviceType);
}

public IDependencyScope BeginScope()
{
return this;
}

public void Dispose() { }
}

Step 3: Inject the Service into Your Controller

Now that the service is registered, you can inject it into your controller using constructor injection:

        
public class ProductsController : ApiController
{
private readonly IProductService _productService;

public ProductsController(IProductService productService)
{
_productService = productService; // Inject the service
}

// GET api/products
public IEnumerable<Product> Get()
{
return _productService.GetAllProducts(); // Use the injected service to get all products
}

// GET api/products/1
public IHttpActionResult Get(int id)
{
var product = _productService.GetProductById(id);
if (product == null)
{
return NotFound(); // Return 404 if not found
}
return Ok(product); // Return the product
}

// POST api/products
public IHttpActionResult Post([FromBody] Product product)
{
if (product == null)
{
return BadRequest("Invalid data."); // Return 400 for bad request
}
_productService.AddProduct(product); // Use the injected service to add the product
return CreatedAtRoute("DefaultApi", new { id = product.Id }, product); // Return 201
}
}

Conclusion

Implementing dependency injection in ASP.NET Web API controllers enhances the modularity and testability of your application. By defining service interfaces, registering them with a DI container, and injecting them into your controllers, you can create a clean and maintainable codebase. This approach not only simplifies unit testing but also allows for easier management of dependencies, leading to a more robust application architecture.