2

Im very new to Ninject. I want to find a way to pass Modelstate of a controller further to service layer.

what i have right now:

       private readonly IAccountService service; 

       public AccountController(ILanguageService ls, ISessionHelper sh)
        {
            this.service = new AccountService(new ModelStateWrapper(this.ModelState));
            this.languageService = ls;
            this.sessionHelper = sh;

        }

    public AccountService(IValidationDictionary validationDictionary)
    {
        this.validationDictionary = validationDictionary;
    }

want i want to get to in some way:

       private readonly IAccountService service; 

       public AccountController(ILanguageService ls, ISessionHelper sh, IAccountService as)
        {
            this.service = as;
            this.languageService = ls;
            this.sessionHelper = sh;

        }

    public AccountService(IValidationDictionary validationDictionary)
    {
        this.validationDictionary = validationDictionary;
    }

But like you see AccountService will never be able to receive IValidationDictionary because it was never sent from AccountController as a prameter.

Is it possible to achieve that? or is this just one of the things i have to live with?

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
Timsen
  • 4,066
  • 10
  • 59
  • 117

1 Answers1

2

ModelState is part of the application's runtime state. Therefore, it is not available at the point in time when you compose the application with Ninject.

You could work around this limitation by creating an Abstract Factory to create your AccountService and also make it a part of your application's runtime state.

public interface IAccountServiceFactory
{
    IAccountService Create(IValidationDictionary validationDictionary);
}

public class AccountServiceFactory
{
    public IAccountService Create(IValidationDictionary validationDictionary)
    {
        return new AccountService(validationDictionary);
    }
}

And then in your AccountController, inject an AccountServiceFactory instead of an AccountService.

   private readonly IAccountServiceFactory serviceFactory; 

   public AccountController(ILanguageService ls, ISessionHelper sh, IAccountServiceFactory asf)
    {
        this.serviceFactory = asf;
        this.languageService = ls;
        this.sessionHelper = sh;

    }

    public void DoSomething()
    {
        var accountService = this.serviceFactory.Create(new ModelStateWrapper(this.ModelState));

        // Do something with account service
    }

Alternatively, you could pass the runtime dependency directly to the account service through each public method call where it is required.

this.service.DoSomething(new ModelStateWrapper(this.ModelState));
NightOwl888
  • 55,572
  • 24
  • 139
  • 212
  • I think the last sentence in your answer is the correct solution. Since ModelState is runtime data (and not really contextual information), it should just passed along. Using a factory to construct the account service is just ugly in this case, because it would still break the dependency graph by delaying the creation of the account service and complicates the code unneedlessly. So +1 for your last sentence. – Steven Mar 19 '15 at 22:09