- Home
- .NET tutorials
- GetService or GetRequiredService in IServiceProvider?
GetService or GetRequiredService in IServiceProvider?
Published: Monday 14 July 2025
The IServiceProvider
is responsible for resolving types registered for dependency injection. But should you use GetService
or GetRequiredService
to resolve a dependency?
Injecting it into a controller
First, we need to know how to inject it. You inject it into a controller by declaring the IServiceProvider
type in the constructor's parameter and storing the instance in a readonly field.
These are the classes we've set up:
public interface ICategoryService
{
CategoryTypeDto? GetCategoryType(int id);
}
public interface ICategoryStorageService
{
List<CategoryTypeDto> Types { get; }
}
public class CategoryService : ICategoryService
{
private readonly ICategoryStorageService _categoryComputersStorageService;
public CategoryService([FromKeyedServices("computers")]
ICategoryStorageService categoryComputersStorageService)
{
_categoryComputersStorageService = categoryComputersStorageService;
}
public CategoryTypeDto? GetCategoryType(int id) =>
_categoryComputersStorageService.Types.SingleOrDefault(s => s.Id == id);
}
public class CategoryComputersStorageService : ICategoryStorageService
{
public List<CategoryTypeDto> Types { get; } = new()
{
new(2, "Computers"),
new(4, "Software")
};
}
public record MvcServiceProviderModel(
CategoryTypeDto? GetServiceCategory,
CategoryTypeDto? GetRequiredServiceCategory,
CategoryTypeDto? GetKeyedServiceCategory,
CategoryTypeDto? GetRequiredKeyedServiceCategory
);
And this is how we've registered them in Program.cs
:
// Program.cs
builder.Services.AddScoped<ICategoryService, CategoryService>();
builder.Services.AddKeyedSingleton<ICategoryStorageService, CategoryComputersStorageService>("computers");
Both the GetService
and GetRequiredService
methods allow you to resolve a service that has been registered with dependency injection. You can use the GetKeyedService
or the GetRequiredKeyedService
method to do the same thing with keyed services.
// MvcController.cs
[Route("[controller]")]
public class MvcController : Controller
{
private readonly IServiceProvider _serviceProvider;
public MvcController(
IServiceProvider serviceProvider
)
{
_serviceProvider = serviceProvider;
}
[HttpGet("service-provider")]
public IActionResult ServiceProvider()
{
return View(new MvcServiceProviderModel(
type,
_serviceProvider.GetService<ICategoryService>()?.GetCategoryType(2),
_serviceProvider.GetRequiredService<ICategoryService>().GetCategoryType(2),
_serviceProvider.GetKeyedService<ICategoryStorageService>("computers")?.Types.SingleOrDefault(c => c.Id == 2),
_serviceProvider.GetRequiredKeyedService<ICategoryStorageService>("computers").Types.SingleOrDefault(c => c.Id == 2)
));
}
}
Similar story with an MVC view
You use the @inject
directive to inject the IServiceProvider
into an MVC view. From there, you can use the extension methods to inject methods that have been registered with dependency injection using GetService
, GetRequiredService
, GetKeyedService
and GetRequiredKeyedService
.
<!-- ServiceProvider.cshtml -->
@using RoundTheCode.DI.Enums
@using RoundTheCode.DI.Models
@using RoundTheCode.DI.Services.Category
@inject IServiceProvider serviceProvider
@model MvcServiceProviderModel
<h2>View</h2>
<p>GetServiceCategory = @(serviceProvider.GetService<ICategoryService>()?.GetCategoryType(2))</p>
<p>GetRequiredServiceCategory = @(serviceProvider.GetRequiredService<ICategoryService>().GetCategoryType(2))</p>
<p>GetKeyedServiceServiceCategory = @(serviceProvider.GetKeyedService<ICategoryStorageService>("computers")?.Types.SingleOrDefault(c => c.Id == 2))</p>
<p>GetRequiredKeyedServiceCategory = @(serviceProvider.GetRequiredKeyedService<ICategoryStorageService>("computers").Types.SingleOrDefault(c => c.Id == 2))</p>
Another way to get the instance
With either a controller or MVC view, you can also use the HttpContext
to get the IServiceProvider
instance. You do that by calling HttpContext.RequestServices
.
// MvcController.cs
[Route("[controller]")]
public class MvcController : Controller
{
[HttpGet("service-provider")]
public IActionResult ServiceProvider()
{
return View(new MvcServiceProviderModel(
HttpContext.RequestServices.GetService<ICategoryService>()?.GetCategoryType(2),
HttpContext.RequestServices.GetRequiredService<ICategoryService>().GetCategoryType(2),
HttpContext.RequestServices.GetKeyedService<ICategoryStorageService>("computers")?.Types.SingleOrDefault(c => c.Id == 2),
HttpContext.RequestServices.GetRequiredKeyedService<ICategoryStorageService>("computers").Types.SingleOrDefault(c => c.Id == 2)
));
}
}
With an MVC view, you can get the HttpContext
from the ViewContext
instance.
<!-- ServiceProvider.cshtml -->
@using RoundTheCode.DI.Enums
@using RoundTheCode.DI.Models
@using RoundTheCode.DI.Services.Category
@model MvcServiceProviderModel
<h2>View</h2>
<p>GetServiceCategory = @(ViewContext.HttpContext.RequestServices.GetService<ICategoryService>()?.GetCategoryType(2))</p>
<p>GetRequiredServiceCategory = @(ViewContext.HttpContext.RequestServices.GetRequiredService<ICategoryService>().GetCategoryType(2))</p>
<p>GetKeyedServiceServiceCategory = @(ViewContext.HttpContext.RequestServices.GetKeyedService<ICategoryStorageService>("computers")?.Types.SingleOrDefault(c => c.Id == 2))</p>
<p>GetRequiredKeyedServiceCategory = @(ViewContext.HttpContext.RequestServices.GetRequiredKeyedService<ICategoryStorageService>("computers").Types.SingleOrDefault(c => c.Id == 2))</p>
The difference between GetService
and GetRequiredService
Both the GetService
and GetRequiredService
methods in IServiceProvider
resolve a type if it has been registered in dependency injection. But they behave differently if the service hasn't been registered.
The GetService
method will return null
if it has not been registered. Whereas if you use the GetRequiredService
method and the service has not been registered, you'll get the following runtime exception:
System.InvalidOperationException: No service for type '{Type}' has been registered.
It's a similar story if you use the GetKeyedService
method which will return null for a non-registered service and the same exception when using the GetRequiredKeyedService
method.
Using IServiceProvider
in other areas
You can use IServiceProvider
in other areas of ASP.NET Core.
Web API controller
In a Web API controller, you either pass in the IServiceProvider
instance as a constructor parameter and store a reference, or you can pass it in as a parameter in the method endpoint:
// WebApiController.cs
[ApiController]
[Route("api/[controller]")]
public class WebApiController : ControllerBase
{
private readonly IServiceProvider _serviceProvider;
public WebApiController(
IServiceProvider serviceProvider
)
{
_serviceProvider = serviceProvider;
}
[HttpGet("service-provider")]
public IActionResult ServiceProvider()
{
return Ok(new
{
GetServiceCategory = _serviceProvider.GetService<ICategoryService>()?.GetCategoryType(2),
GetRequiredServiceCategory = _serviceProvider.GetRequiredService<ICategoryService>().GetCategoryType(2),
GetKeyedServiceCategory = _serviceProvider.GetKeyedService<ICategoryStorageService>("computers")?.Types.SingleOrDefault(c => c.Id == 2),
GetRequiredKeyedServiceCategory = _serviceProvider.GetRequiredKeyedService<ICategoryStorageService>("computers").Types.SingleOrDefault(c => c.Id == 2)
});
}
[HttpGet("service-provider-parameter")]
public IActionResult ServiceProviderParameter(IServiceProvider sp)
{
return Ok(new
{
GetServiceCategory = sp.GetService<ICategoryService>()?.GetCategoryType(2),
GetRequiredServiceCategory = sp.GetRequiredService<ICategoryService>().GetCategoryType(2),
GetKeyedServiceCategory = sp.GetKeyedService<ICategoryStorageService>("computers")?.Types.SingleOrDefault(c => c.Id == 2),
GetRequiredKeyedServiceCategory = sp.GetRequiredKeyedService<ICategoryStorageService>("computers").Types.SingleOrDefault(c => c.Id == 2)
});
}
}
You can also use HttpContext.RequestServices
to get the instance of the IServiceProvider
.
// WebApiController.cs
[ApiController]
[Route("api/[controller]")]
public class WebApiController : ControllerBase
{
[HttpGet("service-provider")]
public IActionResult ServiceProvider()
{
return Ok(new
{
GetServiceCategory = HttpContext.RequestServices.GetService<ICategoryService>()?.GetCategoryType(2),
GetRequiredServiceCategory = HttpContext.RequestServices.GetRequiredService<ICategoryService>().GetCategoryType(2),
GetKeyedServiceCategory = HttpContext.RequestServices.GetKeyedService<ICategoryStorageService>("computers")?.Types.SingleOrDefault(c => c.Id == 2),
GetRequiredKeyedServiceCategory = HttpContext.RequestServices.GetRequiredKeyedService<ICategoryStorageService>("computers").Types.SingleOrDefault(c => c.Id == 2)
});
}
}
Minimal APIs
With minimal APIs, you can pass in the IServiceProvider
instance as a parameter for each endpoint:
app.MapGet("/minimal/service-provider", (
IServiceProvider serviceProvider
) => {
return new
{
GetServiceCategory = serviceProvider.GetService<ICategoryService>()?.GetCategoryType(2),
GetRequiredServiceCategory = serviceProvider.GetRequiredService<ICategoryService>().GetCategoryType(2),
GetKeyedServiceCategory = serviceProvider.GetKeyedService<ICategoryStorageService>("computers")?.Types.SingleOrDefault(c => c.Id == 2),
GetRequiredKeyedServiceCategory = serviceProvider.GetRequiredKeyedService<ICategoryStorageService>("computers").Types.SingleOrDefault(c => c.Id == 2)
};
});
To use HttpContext.RequestServices
, you'll need to pass in the HttpContext
type as a parameter. You can then use that instance to get the RequestServices
property.
app.MapGet("/minimal/service-provider", (
HttpContext httpContext
) => {
return new
{
GetServiceCategory = httpContext.RequestServices.GetService<ICategoryService>()?.GetCategoryType(2),
GetRequiredServiceCategory = httpContext.RequestServices.GetRequiredService<ICategoryService>().GetCategoryType(2),
GetKeyedServiceCategory = httpContext.RequestServices.GetKeyedService<ICategoryStorageService>("computers")?.Types.SingleOrDefault(c => c.Id == 2),
GetRequiredKeyedServiceCategory = httpContext.RequestServices.GetRequiredKeyedService<ICategoryStorageService>("computers").Types.SingleOrDefault(c => c.Id == 2)
};
});
Middleware
With middleware, you'll have to inject it as a parameter into the InvokeAsync
method:
// ServiceProviderMiddleware.cs
// ServiceProviderMiddleware.cs
public class ServiceProviderMiddleware
{
private readonly RequestDelegate _next;
public ServiceProviderMiddleware(
RequestDelegate next
)
{
_next = next;
}
public async Task InvokeAsync(
HttpContext httpContext,
IServiceProvider serviceProvider
)
{
httpContext.Items.Add("GetService", serviceProvider.GetService<ICategoryService>()?.GetCategoryType(2));
httpContext.Items.Add("GetRequiredService", serviceProvider.GetRequiredService<ICategoryService>().GetCategoryType(2));
httpContext.Items.Add("GetKeyedService", serviceProvider.GetKeyedService<ICategoryStorageService>("computers")?.Types.SingleOrDefault(c => c.Id == 2));
httpContext.Items.Add("GetRequiredKeyedService", serviceProvider.GetRequiredKeyedService<ICategoryStorageService>("computers")?.Types.SingleOrDefault(c => c.Id == 2));
await _next(httpContext);
}
}
The InvokeAsync
method already has a HttpContext
type as a parameter, so you can use that to get the IServiceProvider
instance by calling HttpContext.RequestServices
:
// ServiceProviderMiddleware.cs
public class ServiceProviderMiddleware
{
private readonly RequestDelegate _next;
public ServiceProviderMiddleware(
RequestDelegate next
)
{
_next = next;
}
public async Task InvokeAsync(
HttpContext httpContext
)
{
httpContext.Items.Add("GetService", httpContext.RequestServices.GetService<ICategoryService>()?.GetCategoryType(2));
httpContext.Items.Add("GetRequiredService", httpContext.RequestServices.GetRequiredService<ICategoryService>().GetCategoryType(2));
httpContext.Items.Add("GetKeyedService", httpContext.RequestServices.GetKeyedService<ICategoryStorageService>("computers")?.Types.SingleOrDefault(c => c.Id == 2));
httpContext.Items.Add("GetRequiredKeyedService", httpContext.RequestServices.GetRequiredKeyedService<ICategoryStorageService>("computers")?.Types.SingleOrDefault(c => c.Id == 2));
await _next(httpContext);
}
}
Primary constructors
It's also possible to inject the IServiceProvider
instance with primary constructors:
// CategoryPrimaryService.cs
public class CategoryPrimaryService(IServiceProvider serviceProvider)
{
public CategoryTypeDto? GetService() => serviceProvider.GetService<ICategoryService>()?.GetCategoryType(2);
public CategoryTypeDto? GetRequiredService() => serviceProvider.GetRequiredService<ICategoryService>()?.GetCategoryType(2);
public CategoryTypeDto? GetKeyedService() => serviceProvider.GetKeyedService<ICategoryStorageService>("computers")?.Types.SingleOrDefault(c => c.Id == 2);
public CategoryTypeDto? GetRequiredKeyedService() => serviceProvider.GetRequiredKeyedService<ICategoryStorageService>("computers")?.Types.SingleOrDefault(c => c.Id == 2);
}
When the web application builds
Once the web application builds, services can be resolved before the web application runs.
The WebApplication
type contains a Services
property which has the IServiceProvider
type. From there, you can use the GetService
, GetRequiredService
, GetKeyedService
and GetRequiredKeyedService
.
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<ICategorySingletonService, CategorySingletonService>();
builder.Services.AddKeyedSingleton<ICategoryStorageService, CategoryComputersStorageService>("computers");
var app = builder.Build();
// Get services on start up
var categorySingletonService = app.Services.GetRequiredService<ICategorySingletonService>();
var categoryComputersStorageService = app.Services.GetRequiredKeyedService<ICategoryStorageService>("computers");
app.Run();
You can only resolve singleton and transient service lifetime instances directly with the WebApplication
type. If you need to resolve scoped service lifetime, you would need to resolve the IServiceScopeFactory
instance and then call either the CreateScope
or CreateAsyncScope
methods and resolve the service from the newly created scope:
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<ICategorySingletonService, CategorySingletonService>();
builder.Services.AddScoped<ICategoryService, CategoryService>();
builder.Services.AddKeyedSingleton<ICategoryStorageService, CategoryComputersStorageService>("computers");
var app = builder.Build();
// Get services on start up
var categorySingletonService = app.Services.GetRequiredService<ICategorySingletonService>();
var categoryComputersStorageService = app.Services.GetRequiredKeyedService<ICategoryStorageService>("computers");
var serviceScopeFactory = app.Services.GetRequiredService<IServiceScopeFactory>();
using (var scope = serviceScopeFactory.CreateScope())
{
var categoryService = scope.ServiceProvider.GetRequiredService<ICategoryService>();
}
app.Run();
Watch the video
Watch the video where we show you how to use the IServiceProvider
in many different areas to resolve a service.
And if you want to try out using the IServiceProvider
type, you can download the code example which gives you examples on how to use it in ASP.NET Core.
When should you use IServiceProvider
?
IServiceProvider
is good if you don't know whether the instance will be registered. This might be the case if an instance is only registered if a certain feature flag is enabled.
It's also good if you have many dependencies to resolve in a class. It might be better to inject the IServiceProvider
instance and then resolve them when you want to use them.
But your code would be more readable if you inject the services directly with parameters. So unless you have a reason to use IServiceProvider
type, it's recommended to specify each of the services as parameters.
Latest tutorials

