DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

SBOMs are essential to circumventing software supply chain attacks, and they provide visibility into various software components.

Related

  • Implementing Cache Dependency in ASP.NET Core
  • GDPR Compliance With .NET: Securing Data the Right Way
  • How to Enhance the Performance of .NET Core Applications for Large Responses
  • Developing Minimal APIs Quickly With Open Source ASP.NET Core

Trending

  • How to Build a Real API Gateway With Spring Cloud Gateway and Eureka
  • The Agile Paradox
  • The Battle of the Frameworks: Choosing the Right Tech Stack
  • Micro Frontends to Microservices: Orchestrating a Truly End-to-End Architecture
  1. DZone
  2. Coding
  3. Frameworks
  4. Injecting Services to ASP.NET Core Controller Actions

Injecting Services to ASP.NET Core Controller Actions

In this post, an expert ASP.NET developer introduces controller action injection and shows how to benefit from it. Let's get to it!

By 
Gunnar Peipman user avatar
Gunnar Peipman
·
Jul. 03, 18 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
18.8K Views

Join the DZone community and get the full member experience.

Join For Free

ASP.NET Core comes with a thin but rich and powerful built-in dependency injection mechanism we can use to inject instances to controllers and some other parts of web applications. Although constructor injection is the most famous dependency injection method for controllers, there is also dependency injection to controller actions available. This post introduces controller action injection and shows how to benefit from it.

Constructor Injection With Controllers

Controller action injection is a great feature to use with controllers where most of the actions need some specific service that others don't need. In ASP.NET Core, it's traditional to use constructor injection. Let's take a look at the following controller.

public class HomeController : Controller
{
    private readonly ICustomerDAO _customerDao;
    private readonly ISmsService _smsService;
    private readonly IVehicleTelemetryService _telemetryService;
    private readonly IMailService _mailService;

    public HomeController(ICustomerDAO customerDao, 
                            ISmsService smsService, 
                            IMailService mailService, 
                            IVehicleTelemetryService telemetryService)
    {
        _customerDao = customerDao;
        _smsService = smsService;
        _mailService = mailService;
        _telemetryService = telemetryService;
    }

    public IActionResult Index(int page = 1)
    {
        var customers = _customerDao.ListCustomers(page: 1, pageSize: 25);

        return View(customers);
    }

    public IActionResult SendSms(int id, string text)
    {
        var customer = _customerDao.GetById(id);

        _smsService.Send(customer.Phone, text);
    }

    public IActionResult SendMail(int id, string subject, string body)
    {
        var customer = _customerDao.GetById(id);

        _mailService.Send(customer.Email, subject, body);
    }

    public IActionResult GetCoordinates(int id)
    {
        var coordinates = _telemetryService.GetCoordinates(id);

        return Json(coordinates);
    }
}

It seems all okay but when we think a few steps further we can see that part of this class can easily grow messy, as, over time, we'll probably inject more services into the controller.

public class HomeController : Controller
{
    private readonly ICustomerDAO _customerDao;
    private readonly ISmsService _smsService;
    private readonly IVehicleTelemetryService _telemetryService;
    private readonly IMailService _mailService;
    /*
        More injected services here 
    */

    public HomeController(ICustomerDAO customerDao,
                            ISmsService smsService,
                            IMailService mailService,
                            /* More injected services here */
                            IVehicleTelemetryService telemetryService)
    {
        _customerDao = customerDao;
        _smsService = smsService;
        _mailService = mailService;
        _telemetryService = telemetryService;
        /*
            More injected services here 
        */
    }

    // Controller actions follow
}

But at the same time, we have services used only by one controller action and there is no reason to have these services available in the class scope. The action scope would be enough for us.

Injecting Services to the Controller Action

The solution to our problem is called controller action injection. It means we can inject services into controller actions instead of controller constructors. When we add some service to an action parameters list we confuse the MVC, as it doesn't know, by default, that we want something from the services. We have to apply FromServicesAttribute to the action parameters to tell MVC that this parameter is coming from dependency-injection. As a sample, let's use controller action injection with the SendSms() method of our sample controller.

public IActionResult SendSms(int id, string text, [FromServices]ISmsService smsService)
{
    var customer = _customerDao.GetById(id);

    smsService.Send(customer.Phone, text);
}

ButSendSms() is not the only action that needs an instance of some service that the actions don't use. We also have the SendMail() and GetCoordinates() actions. After moving to the controller action injection, our class looks smaller and cleaner.

public class HomeController : Controller
{
    private readonly ICustomerDAO _customerDao;

    public HomeController(ICustomerDAO customerDao)
    {
        _customerDao = customerDao;
    }

    public IActionResult Index(int page = 1)
    {
        var customers = _customerDao.ListCustomers(page: 1, pageSize: 25);

        return View(customers);
    }

    public IActionResult SendSms(int id, string text, [FromServices]ISmsService smsService)
    {
        var customer = _customerDao.GetById(id);

        smsService.Send(customer.Phone, text);
    }

    public IActionResult SendMail(int id, string subject, string body, [FromServices]IMailService mailService)
    {
        var customer = _customerDao.GetById(id);

        mailService.Send(customer.Email, subject, body);
    }

    public IActionResult GetCoordinates(int id, [FromServices]IVehicleTelemetryService telemetryService)
    {
        var coordinates = telemetryService.GetCoordinates(id);

        return Json(coordinates);
    }
}

We leave ICustomerDAO at the class level and inject it using controller constructor injection because this class is used by multiple controller actions. Our class is now cleaner and we don't have A growing pile of constructor arguments anymore. It also makes it easier to write tests for controllers, as we don't have to initialize controllers with all the dependencies it could possibly be using.

Wrapping Up

Controller action injection is a useful feature that helps us keep services used by one action away from the class scope. This way we don't pile injected services to class level and our controller classes are smaller. If service is used by more than one or few actions it is a good idea to have reference to it at the class level. Otherwise, we can keep controller classes smaller by using controller action injection.

ASP.NET Web Service ASP.NET Core Dependency injection

Published at DZone with permission of Gunnar Peipman, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Implementing Cache Dependency in ASP.NET Core
  • GDPR Compliance With .NET: Securing Data the Right Way
  • How to Enhance the Performance of .NET Core Applications for Large Responses
  • Developing Minimal APIs Quickly With Open Source ASP.NET Core

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • [email protected]

Let's be friends: