.NET MVC Dependency Injection with Ninject - c#

I've just started programming in .NET and I'm having some problems with implementing dependency injection (using Ninject).
I'm creating some sort of catering application where user can browse towns, in towns browse restaurants and in restaurants browse food.
I'm using UnitOfWork and repository pattern where for example I access town by id like this:
_unitOfWork.TownRepository.GetByID(id);
Now I started implementing services into application and I have encountered need for dependency injection.
I have created ITownService, IRestaurantService and IFoodService (since I've TownRepository, RestaurantRepository and FoodRepository in my UnitOfWork).
Sample look of TownService:
public class TownService : ITownService
{
// initialize UnitOfWork
private IUnitOfWork _unitOfWork;
public TownService()
: this(new UnitOfWork())
{
}
public TownService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public Town GetByID(object id)
{
return _unitOfWork.TownRepository.GetByID(id);
}
public IEnumerable<Town> GetAll()
{
return _unitOfWork.TownRepository.Get();
}
public bool Insert(Town town)
{
// validation logic
if (!ValidateTown(town))
return false;
try
{
_unitOfWork.TownRepository.Insert(town);
_unitOfWork.Save();
}
catch
{
return false;
}
return true;
}
public bool Delete(object id)
{
try
{
_unitOfWork.TownRepository.Delete(id);
_unitOfWork.Save();
}
catch
{
return false;
}
return true;
}
public bool Update(Town townToUpdate)
{
// validation logic
if (!ValidateTown(townToUpdate))
return false;
try
{
_unitOfWork.TownRepository.Update(townToUpdate);
_unitOfWork.Save();
}
catch
{
return false;
}
return true;
}
}
I haven't implemented FoodService and RestaurantService yet, but they should be similar with of course some additinal methods exepct this that I have. For example in RestaurantService I might have public Restaurant GetRestaurantsInTown(Town town){} or something like that.
I hope that you got the feel of application a bit. Now lets back to Ninject.
In my TownController I would have something like this:
public class TownController : Controller
{
private ITownService _townService;
public TownController(ITownService townService)
{
_townService = townService;
}
}
Similar would be for RestaurantController and FoodController of course just constructor injecting.
How do I use Ninject in such example? Do I need some global IService and not ITownService, IRestaurantService and IFoodService which I'd inherid in TownService, RestaurantService and FoodService or is it okay like this?
When binding what do I need to bind?
kernel.Bind<IUnitOfWork>().To<UnitOfWork>();
kernel.Bind<ITownService>().To<TownService>();
kernel.Bind<IRestaurantService>().To<RestaurantService>();
kernel.Bind<IFoodService>().To<TownService>();
Something like this?
In short - what I need for adding dependency injection with Ninject?
I'm really having problems with this and would need help.
Thanks a lot in forward.

From the package manager console run this command:
Install-package Ninject.MVC3
This will add a class to App_Start/NinjectWebCommon.cs
If you look near the bottom there is a RegisterServices method.
You simply add the code from your question there i.e.
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUnitOfWork>().To<UnitOfWork>();
kernel.Bind<ITownService>().To<TownService>();
kernel.Bind<IRestaurantService>().To<RestaurantService>();
kernel.Bind<IFoodService>().To<TownService>();
}

Related

How do I use Dependency Injection with Unit of Work and Repositories in C#? (Not a web based App)

I see a lot of questions and answers on this topic, however the vast majority are dealing with ASP.Net or other web based applications and something called .InRequestScope. I have yet to find this method in Ninject with a Windows Application.
I have the usual Unit of Work (UoW) and Repository (Repo) classes and Interfaces, but I am wanting to inject the same DbContext into both, each time a UoW is run from the DIContainer. My code looks like this;
public class UnitOfWork : IUnitOfWork, IDisposable
{
private readonly FinancialContext _context;
private IAccountRepository _accountRepository;
public IAccountRepository Accounts
{
get { return _accountRepository; }
}
UnitOfWork(IMyContext context, IAccountRepository accountRepository)
{
_context = context;
_accountRepository = accountRepository;
}
public void SaveChanges()
{
_context.SaveChanges();
}
public void Dispose()
{
_context.Dispose();
}
}
public class AccountRepository : Repository<Account>, IAccountRepository
{
public AccountRepository(IMyContext context) : base(context) { }
}
The DIContainer holds the following associations;
Bind<IUnitOfWork>().To<UnitOfWork>().InTransientScope();
Bind<IUnitOfWorkFactory>().ToFactory();
Bind<IMyContext>().To<MyContext>().InSingletonScope();
Bind<IAccountTypeRepository>().To<AccountTypeRepository>().InTransientScope();
I'll come back to the .InSingletonScope();
The way I have seen people do this normally has been in the UoW Properties for each Repo to have code to this effect;
private IAccountRepository _accountRepository;
public IAccountRepository Accounts
{
get
{
if(_accountRepository = null)
{
_accountRepository = new AccountRepository(_context);
}
return _accountRepository;
}
}
And remove the injected repositories from the Constructor, there by ensuring that each instance of a repository using the same _context.
However in my mind this breaks the Dependency Injection for this class. Is there a way to do this where each creation of a UoW like so;
public TestUnitOfWork(IUnitOfWorkFactory unitOfWork)
{
using (var UoW = unitOfWork.Create())
{
Work done on UoW...
}
}
Currently the .InSingletonScope allows this, but is this keeping an instance of the context always open? Introducing the errors associated with not disposing a context properly?
Or is it better to create a Factory for the Repositories and give them a context parameter, then in the properties initialise it like so;
private IAccountRepository _accountRepository;
public IAccountRepository Accounts
{
get
{
if(_accountRepository = null)
{
_accountRepository = RepositoryFactory.CreateAccountRepository(_context);
}
return _accountRepository;
}
}
Thanks in advance for any help!
The solution is the use Ninject's Extensions.Factory class and pass in an IAccountFactory.Create() to initialise a new object. This then uses the DI Container to resolve its dependencies and doesn't break the DI approach.

How to define a public const string in a repository that implements an interface

I have a Controllerclass which makes use of a TodoRepositoryclass via DI that implements an interface ITodoRepository.
The interface:
public interface ITodoRepository
{
public bool ValidateTodo(Todo todo);
}
The repository class:
public class TodoRepository : ITodoRepository
{
public bool ValidateTodo(Todo todo)
{
//some validation
return false;
}
}
The Controller:
public TodoController : BaseController
{
private readonly ITodoRepository _todoRepository;
private const string INVALID_TODO_MESSAGE = "Invalid todo.";
public TodoController(ITodoRepository todoRepository)
{
_todoRepository = todoRepository;
}
public IActionResult Post(Todo todo)
{
if(!_todoRepository.ValidateTodo(todo))
{
return new JsonResult(INVALID_TODO_MESSAGE);
}
}
}
To be able to use INVALID_TODO_MESSAGE in every Controller that makes use of TodoRepository I want to move it to TodoRepository, but that doesn't seem to be possible. Some other solution is to create a readonly property in ITodoRepository, and implement it in TodoRepository, but I am not sure if that is the best way to go.
You could create a helper class, next to the interface:
public static class TodoConstants
{
public const string INVALID_TODO_MESSAGE = "Invalid todo.";
}
You can use it everywhere as TodoConstants.INVALID_TODO_MESSAGE.
DISCLAIMER: This is not a direct answer to the question, but rather a design suggestion for error handling in web applications.
I would implement such a validation using Exceptions. Typically you could throw business exceptions from your application layer (possibly including repository too). Then at the web layer (aka. controllers, filters, etc.) you could implement an ExceptionFilter to handle business exceptions, for example turning them into a special JsonResult.
This way you'll have a good separation of concerns and centralized error handling through the application.
See this documentation for ASP.NET WebApi (it's almost the same for MVC too) https://learn.microsoft.com/en-us/aspnet/web-api/overview/error-handling/exception-handling
Some untested pseudo code would look like this.
public class TodoRepository : ITodoRepository
{
public bool ValidateTodo(Todo todo)
{
//some validation
throw new ValidationException("Invalid todo");
}
}
public class MyBusinessExceptionFilterAttribute : ExceptionFilterAttribute
{
public void OnException(ExceptionContext filterContext)
{
...
filterContext.Result = new JsonResult(filterContext.Exception.Message);
...
}
}
public static void ApplicationStartup() {
...
GlobalFilters.Filters.Add(new MyBusinessExceptionFilterAttribute());
...
}
public IActionResult Post(Todo todo)
{
// Just let the exception to be thrown in case of business errors
_todoRepository.ValidateTodo(todo);
}

How to unit test DBService which uses the Servicestack Funq IOC

I am new to a project which I should extend so I decided to use TDD to quickly recognize any problems of a system I do not fully understand.
There is one class called DBService which "encapsulates" all the db access. For example there is one method called getAllCustomers which returns a list of Customers. This would look something like this (this is just an example for a better understanding):
public class DBService
{
public IDbConnectionFactory DBFactory {
get { return DI.Container.Resolve<IDbConnectionFactory>(); }
}
public List<Customer> GetAllCustomers()
{
try
{
using (var connection = DBFactory.OpenDbConnection())
{
var dbResult = connection.Select<Customer>();
// code ommitted
}
}
catch (Exception e)
{
// code ommitted
}
}
}
Another problem is that at start (in the ServiceStack AppHost.Configure) all tables are created if they do not exist, and for some tables if they exists some columns etc are added (which are probably changes which were added later)
When I now for example have to extend the customer and add another field, addresses I would like to do that in TDD style but I have no idea how.
I cannot inject any DBFactory since the getter is private
Afaik I cannot use the :memory: connection string for the OrmLiteConnectionFactory because I am using ServiceStack 3.9.74
So what are my options here?
Avoid the Service Locator anti-pattern and use constructor injection instead. Try to stay away from using DI containers directly in dependent classes. It tightly couples your classes to concerns that don't belong there and make it difficult to test classes in isolation.
public class DBService {
private readonly IDbConnectionFactory connectionFactory;
public DBService(IDbConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
public IDbConnectionFactory DBFactory { get { return connectionFactory; } }
public List<Customer> GetAllCustomers() {
try {
using (var connection = DBFactory.OpenDbConnection()) {
var dbResult = connection.Select<Customer>();
//... code omitted for brevity
}
} catch (Exception e) {
//... code omitted for brevity
}
}
}
Both Select<T> and OpenDbConnection look like extension methods. I would suggest checking what their expectatiosn are and mock those behaviors as well.
If DbService is itself to be used as a dependency for other class then that class should be abstracted as well.
public interface IDbService {
IDbConnectionFactory DBFactory { get; }
List<Customer> GetAllCustomers();
}
and have the implementation inherit
public class DbService : IDbService {
//... code removed for brevity
}
and make sure to register everything with the IoC container.

Apply DI with Unity in Custom Attribute

Hi i am new to DI with unity. I am developing a custom Attribute. In that attribute I want to inject a dependency with help of Unity. But when use of that attribute in a class it shows exception. The code is:
public interface ITest
{
}
public class AAttrib : Attribute
{
ITest _test;
public AAttrib(ITest test)
{
_test = test;
}
}
public class Test : ITest
{
}
[AAttrib]
public class Example
{
// to do
}
the exception is:
There is no argument given that corresponds to the required formal
parameter 'test' of 'AAttrib.AAttrib(ITest)
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<ITest, Test>(new HierarchicalLifetimeManager());
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
the Unity resolver class is:
public class UnityResolver: IDependencyResolver
{
protected IUnityContainer _container;
public UnityResolver(IUnityContainer container)
{
if(container == null)
throw new ArgumentNullException("container");
this._container = container;
}
public void Dispose()
{
_container.Dispose();
}
public object GetService(Type serviceType)
{
try
{
return _container.Resolve(serviceType);
}
catch (ResolutionFailedException r)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return _container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = _container.CreateChildContainer();
return new UnityResolver(child);
}
}
You cannot use Dependency Injection on Attributes, cause Attributes are Metainformation that extend the meta information of classes. And these meta information are generated during compile time
It is indeed not possible to use DI in attributes. There is however a nice clean workaround by using a decorator.
See this blog: https://blogs.cuttingedge.it/steven/posts/2014/dependency-injection-in-attributes-dont-do-it/
I tried this and I've been using it for quite some time now. You will be able to do exactly what you need with this.
(Blog has .net framework & .net core solutions)
Apologies for late entry.
Not sure if unity can let you do that. But PostSharp has a way of achieving this. I've never tried this as PostSharp wasn't an approved DI framework in my project. But I liked the solution.
Auto data contract
This doesn't answer your question but gives a different perspective to the solution that you are thinking.
You should avoid attributes. Attributes are good starting point but get in the way of application extension.
Attributes are hardcoding and is violation of at least two SOLID principles, Single Responsibility and Open/Closed principles. It should rather be done using Fluent APIs
I would rather replace AAttrib with a Fluent API.
Attribute Example
public class Person {
[StringLength(100)]
[RegularExpression("^([a-zA-Z0-9 .&'-]+)$", ErrorMessage = "Invalid First Name")]
public string FirstName { get; set; }
}
FluentValidation Example:
public class Person {
public string FirstName { get; set; }
}
public class PersonValidator : AbstractValidator<Person> {
public PersonValidator() {
RuleFor(x => x.FirstName).NotNull().WithMessage("Can't be null");
RuleFor(x => x.FirstName).Length(1, 100).WithMessage("Too short or long");
RuleFor(x => x.FirstName).Matches("^([a-zA-Z0-9 .&'-]+)$").WithMessage("Invalid First Name"));
}
}
This will essentially do the same thing that attribute is doing. With the right DI wiring in place. This can introduce great flexibility. Read other articles on wiring attributes with members.

ASP.NET: dependency injection and roles

I have a page using an injected BLL service: a simple service returning a set of objects with a function like this:
public IMyService { List<Foo> All(); }
There is a default implementation for normal users.
Now, i need that users in administrative role can view more objects, with another implementation of the service.
Where can i configure my page to use the second implementation?
My first solution is to put the dependency to the IUnityContainer in the page, and use it to resolve the dependency:
[Dependency]
public IUnityContainer Container { get; set;}
Page_Init(..)
{
_myService = User.IsInRole(MyRoles.Administrators)
? Container.Resolve<IMyService>("forAdmins")
: Container.Resolve<IMyService>();
}
But it's very ugly: it's a ServiceLocator and it's neither scalable neither testable.
How can i handle this situation? Maybe creating a child container for every role?
You could implement it as a combination of Decorator and Composite:
public SelectiveService : IMyService
{
private readonly IMyService normalService;
private readonly IMyService adminService;
public SelectiveService(IMyService normalService, IMyService adminService)
{
if (normalService == null)
{
throw new ArgumentNullException("normalService");
}
if (adminService == null)
{
throw new ArgumentNullException("adminService");
}
this.normalService = normalService;
this.adminService = adminService;
}
public List<Foo> All()
{
if(Thread.CurrentPrincipal.IsInRole(MyRoles.Administrators))
{
return this.adminService.All();
}
return this.normalService.All();
}
}
This follows the Single Responsibility Principle since each implementation does only one thing.
I agree with you that your current design is ugly. What I personally dislike about this approach is that you are setting up the security configuration inside a page. You will have a security bug when anyone forgets this and how are you testing that this page configuration is correct?
Here are two ideas:
First:
Use a factory that is able to resolve the correct implementation of that service based on the user roles:
public static class MyServiceFactory
{
public static IMyService GetServiceForCurrentUser()
{
var highestRoleForUser = GetHighestRoleForUser();
Container.Resolve<IMyService>(highestRoleForUser);
}
private static string GetHighestRoleForUser()
{
var roles = Roles.GetRolesForUser().ToList();
roles.Sort();
return roles.Last();
}
}
Second:
Have multiple methods on that interface, one for normal users, one for administrators. The implementation of that interface can have the PrincipalPermissionAttribute defined on the restricted methods:
class MyServiceImpl : IMyService
{
public List<Foo> All()
{
// TODO
}
[PrincipalPermission(SecurityAction.Demand, Role ="Administrator")]
public List<Foo> AllAdmin()
{
// TODO
}
}
I hope this helps.

Categories

Resources