how to access data structure from web API controller in .NET where the structure needs to be modified by the API controller
What is the best practice for creating local data structure alongside Controller class for .NET core web API.
I have web API written in .NET which injects logger and Kafka producer:
public LoadTestController(ILogger<LoadTestController> logger, IEventBusProducer<string, string> producer) { _logger = logger; _producer = producer; _messages = new Dictionary<int, Sample>(); }
I need to use the dictionary to determine if a previous message of certain size was sent. However, for every POST request the constructor is called again for LoadTestController.
What is best practice to achieve that?
Is it best to inject that dictionary somehow (pass by reference from Startup and modify per request) ? or create new singelton service that owns this data structure?
In your case, the best practice, would be to add a singleton service, serving as a repository.
Singleton service registration
You can add a singleton service by either
providing a class
services.AddSingleton<ISingletonService, SingletonService>();
or an instance
services.AddSingleton<ISingletonService>(new SingletonService());
or an delegate
services.AddSingleton<ISingletonService>(sp => new SingletonService());
wich go into ConfigureServices
public void ConfigureServices(IServiceCollection services) { // other registrations services.AddSingleton<ISingletonService, SingletonService>(); // or services.AddSingleton<ISingletonService>(new SingletonService()); // or services.AddSingleton<ISingletonService>(sp => new SingletonService()); }
Design services for dependency injection
Best practices are to:
- Design services to use dependency injection to obtain their dependencies.
- Avoid stateful, static classes and members. Design apps to use singleton services instead, which avoid creating global state.
- Avoid direct instantiation of dependent classes within services.
- Direct instantiation couples the code to a particular implementation. Make app classes small, well-factored, and easily tested.
Also, in your case, you may want to guard your Dictionary
, against concurrent requests, if the use of the service, is simple enough, a ConcurrentDictionary
might serve you well.
If the service acts as an repository, it should at least have methods to set and get data. Otherwise, you might find a more advanced example of the repository pattern here
Dependency injection into controllers
You can simply inject services, by adding them as parameters, to the constructor
public class MyController { private readonly ISingletonService _service; public MyController(ISingletonService service) { _service = service; } public IActionResult About() { return Content( $"Current value: {_service.Get(111)}"); } }
or into actions using the FromServices attribute
public IActionResult About([FromServices] ISingletonService service) { return Content( $"Current value: {service.Get(111)}"); }
Minimal implementation
Using best practice, you should give semantic value to your implementation, but keep in mind it’s completely OK, to provide functionality by inheritance!
So if you really, only need the functionality of a Dictionary
, a minimal service implementation for you, could look like this:
public interface IMessageRepository : IDictionary<int, Sample> { } public class MessageRepository : ConcurrentDictionary<int, Sample>, IMessageRepository { }