Andrew Andrew - 1 month ago 16
C# Question

Create instance of interface with dependency injection

I have a base controller and before every page load I want to get the current user. I originally had a constructor in my

BaseController
that looked like this

public BaseController(ISystemUserCommand command)
{
_systemUserCommand = command
}


The problem with this then is that every controller that inherits from the
BaseController
would have to contain the
ISystemUserCommand
in its constructor, which I don't think would be good.

Instead I tried to create just an instance of the service class (shown below - it's the commented line under var sid...) but I need to pass in user service. How would I pass in the user service here or is this a bad way of doing it?

public abstract class BaseController : Controller
{
public SystemUserViewModel CurrentUser { get; set; }

private readonly ISystemUserCommand _systemUserCommand;

public SystemUserViewModel GetCurrentUser()
{
if (HttpContext == null || HttpContext.User == null) return null;
if (CurrentUser != null) return CurrentUser;

var sid = System.Web.HttpContext.Current.Request.LogonUserIdentity.User.ToString();

//var command = new SystemUserCommand();

CurrentUser = _systemUserCommand.GetUser(sid);

return CurrentUser;
}

public void SetUserInformation(SystemUserViewModel currentUser)
{
ViewBag.UserId = currentUser.SystemUserId;
ViewBag.FullName = string.Format("{0} {1}", currentUser.FirstName, currentUser.LastName);
ViewBag.FirstName = currentUser.FirstName;
ViewBag.LastName = currentUser.LastName;
ViewBag.CurrentUser = currentUser;
}

protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
var currentUser = GetCurrentUser();

if (currentUser != null)
{
if (currentUser.IsActive)
{
SetUserInformation(currentUser);
}
else
filterContext.Result = RedirectToAction("denied", "unauthorized");
}
else
filterContext.Result = RedirectToAction("denied", "unauthorized");

base.OnActionExecuting(filterContext);
}
}

public class SystemUserCommand : ISystemUserCommand
{
private readonly ISystemUserBusiness _systemUserBusiness;

public SystemUserCommand(ISystemUserBusiness systemUserBusiness)
{
_systemUserBusiness = systemUserBusiness;
}

...
}

Answer

First of all, it does not seem a good idea to have OnActionExecuting override in the controller. You can use filters, that are specially designed for this purpose. And it seems that is the main reason you created the BaseController at all.

Regarding the problem with injecting the system command in all the required service, I would do so, but without inheriting from a base class, since I generally prefer aggregation to inheritance. That would mean that each controller that needs to work with the service will get it.

Another option that I have used few times to abstract some operations is to create a UserSerivce that will provide the required operations to the controllers. It will have ISystemUserCommand and HttpContext injected inside so that all of your controllers won't have to do the job. You can either use HttpContext.Current as static or abstract it away if you need testability.

Moreover I would not recommend property injection since it is more obscure than constructor injection that should be preferred if possible.

You can read more about filters here. Unfortunately if you use filters it's not that easy to inject in filters themselves and mostly done with property injection or ServiceLocator pattern (which is not good usually). It's possible to do better with some amount of voodoo though. I think that SimpleInjector has a lot of examples and tutorials on how to apply DI to filters in MVC, maybe they even have a nuget package now to ahieve that.