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?

Add Comment
1 Answer(s)

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 { } 
Answered on July 16, 2020.
Add Comment

Your Answer

By posting your answer, you agree to the privacy policy and terms of service.