0

I'm getting my feet wet with C# IoC frameworks. I chose StructureMap.Webapi2 to integrate into an existing api. I have the following scenario which I am not sure what the best way to implement is.

public class MyController : ApiController
{
     public IHttpActionResult MyAction(string clientCode, [FromBody]MyDto bodyData)
    {
        var client = new ClientManager().GetClientByCode(clientCode);

        var someData = new SomeData
        {
            User = bodyData.User,
            ClientCode = clientCode,
            SomeField = client.SomeField
        };

        var myService = new WorkerService(someData);
        myService.DoSomething();

        return Ok();
    }
}

A peek a the WorkerService:

public WorkerService(SomeData someData)
{
    _someData = someData;

    _someCollection = GetSomeData(); // GetSomeData uses _someData
}

public DoSomething()
{
    // some code that uses _someData and _someCollection
}

Approach 1:

  • Make WorkerService's constructor parameterless and add a public SomeData property that can be initialized inside MyController MyAction.
  • Then both ClientManager and WorkerService can be injected by the IoC into a constructor to be added to the controller.

The Action would then look like:

public IHttpActionResult MyAction(string clientCode, [FromBody]MyDto bodyData)
{
    var client = _clientManager.GetClientByCode(clientCode);

    var someData = new SomeData
    {
        User = bodyData.User,
        ClientCode = clientCode,
        SomeField = client.SomeField
    };

    _myService.SomeData = someData;
    _myService.DoSomething();

    return Ok();
}

Approach 2 (the one I'm not sure how to implement)

  • Keep WorkerService constructor as is (with a parameter). Inject the service into the Controller's constructor (requires building and pass the service's argument (SomeData) at runtime, instead of having the MyAction build SomeData).
  • Somehow build SomeData (maybe using a factory) before for each request is handled by the controller. This would mean that ClientManager would have to be injected to that somehow/factory. The output of the somehow/factory would be used by the IoC when building the WorkerService to be injected into the controller, per request.

To me, Approach 1 seems quicker and simple, but Approach 2 seems to be more attractive, more challenging and with more learnings.

Bruno
  • 85
  • 1
  • 10

1 Answers1

0

I ended up finding a solution for the problem:

  1. Create a passive attribute and add to the action
  2. Create an ActionFilter, which checks for the attribute and when found, gets data from the request.
  3. Since I didn't like the approach of reading the request body in the ActionFilter, I changed the request and moved the data I needed from the body (server and data base names) to the url of the request. Then I created a POCO for that data that I inject into the ActionFilter and populate with the data from the url. That POCO isntance is now available in every service down the dependency chain that needs it.
  4. For the rest of the data I needed in my SomeData object, I followed approach 1, made WorkerService's constructor parameterless and passed the data like:

    _myService.DoSomething(someData);
    
  5. One final trick was adding the ActionFilter to config.Filters, because my filter has it's own dependencies, I couldn't just do:

    config.Filters.add(new MyActionFilter(What_About_The_Parametes_???))
    

I had to get the structureMap's container instance and have it return a instance of my filter which will the cause all the dependencies to be injected into it, and then I can add the filter instance to config.Filters:

    var container = StructuremapMvc.StructureMapDependencyScope.Container;
    config.Filters.Add(container.GetInstance<IMyActionFilter>());
Bruno
  • 85
  • 1
  • 10