I have a controller with a constructor like so:
Public Sub New(Service As ICategoryService)
The service's constructor looks like this:
Public Sub New(Repository As IRepository(Of Category), IValidationDictionary)
I have a class Named ModelStateWrapper that implements IValidationDictionary:
Public Class ModelStateWrapper
Implements IValidationDictionary
Private ModelState As ModelStateDictionary
Public Sub New(ModelState As ModelStateDictionary)
Me.ModelState = ModelState
End Sub
Public Sub AddError(Key As String, Message As String) Implements Core.Interfaces.IValidationDictionary.AddError
ModelState.AddModelError(Key, Message)
End Sub
Public ReadOnly Property IsValid As Boolean Implements Core.Interfaces.IValidationDictionary.IsValid
Get
Return ModelState.IsValid
End Get
End Property
End Class
I want to inject the ModelState of the controller into the ModelStateWrapper, and inject that into the service. Is this possible?
I have looked at custom providers in Ninject, and have the controllers inherit a BaseController class, but it does not seem to work. Any ideas?
Also, what is the standard way to do validation in the service layer that can be used from the controller?
It seems like you would have a problem trying inject ModelState because of the fact that once in an action method you already have the instance of ModelState that you want to pass into your wrapper.
Not every single object needs to or should be injected. Sometimes, this case potentially being one of those times, it is cleaner and easier and simpler to "inject" or provide the dependency or object as a parameter to the method that requires it. That is, pass IValidationDictionary as a parameter to the methods in your Service. Construct a ModelStateWrapper in the controller (new it up or use a Factory), and pass it in.
Related
I'm new to Rhino, and wondered how to mock a local variable/object inside a method of a class I'd also be mocking. In this case I'd be doing it with an ASP.Net MVC controller & action method.
Here's what the controller looks like, simplified:
public class HomeController : Controller {
public myObjectType myMockedObject; //I want to mock this
public myNonMockedObject; //don't want to mock this
public ViewResult Index() {
//call various methods on the mocked and nonmocked members
return View();
}
}
In other words, I'd like to create a mock home controller and mock some local variables within it and their methods-- but not all of them. Is this possible using Rhino?
You can inject these through constructor parameters. Just write constructor that takes myObjectType as parameter. Within this constructor just initialize your fields.
Note1: in case to run MVC, you will need also parameterless ctro, or modify ConstructorFactory (e.g. here https://www.codeproject.com/Articles/560798/ASP-NET-MVC-Controller-Dependency-Injection-for-Be). Or just think about using some IoC container (e.g. https://www.nuget.org/packages/Unity/) that can inject whatever you want inside the controller (mock or normal class).
Note2: you should extract an interface from myObjectType class and mock that interface instead of concrete class (Rhino handles that better).
Note3: I am usually trying to put all the logic (and test that separately) outside of controller since it is quite tough to test the controller (you need to initialize a lot of stuff there what involves another mocking).
OK, I have a problem where the ModelState errors are not mapping to the correct properties.
Let me see if I can explain this.
I have a ViewModel like so:
public class MyViewModel
{
public string Prop1 {get;set;}
public string Prop2 {get;set;}
....
}
In my view, I have a model that has a collection of this type which I have an EditorTemplate for. So it generates MyViewModels[0].Prop1, MyViewModels[1].Prop1, etc.
Problem is, when I set the error on the ModelState in my service layer via an interface I have made called IValidationDictionary which has a wrapper around model state, it does not attach the error to the correct row in the view, rather to the end of the model as Prop1.
EDIT
Here is the ModelStateWrapper (VB - Sorry!)
Public Class ModelStateWrapper
Implements IValidationDictionary
#Region "Private Members/Properties"
Private modelState As ModelStateDictionary
Public ReadOnly Property IsValid As Boolean Implements IValidationDictionary.IsValid
Get
Return modelState.IsValid
End Get
End Property
#End Region
#Region "Constructor(s)"
Public Sub New(modelState As ModelStateDictionary)
Me.modelState = modelState
End Sub
#End Region
#Region "Methods"
Public Sub AddError(key As String, message As String) Implements IValidationDictionary.AddError
modelState.AddModelError(key, message)
End Sub
#End Region
End Class
Sounds like you may be using Dependency Injection and injecting the ModelStateDictionary into your ModelStateWrapper class, which is again injected into your Service Layer?
I can only guess whatever is getting injected is not using the Controller class ModelState property (ModelStateDictionary) of your current HTTP request.
Are you by any chance initializing a new instance of ModelStateDictionary and passing it into your ModelStateWrapper?
If you are using Dependency Injection, please show me your Injection configuration so I can give you a better answer.
How should I properly implement data access in my custom model binders?
Like in controllers I use IContentRepository and then have it create an instance of its implementing class in constructor. So I have everything ready for incorporating IoC (DI) at a later stage.
Now I need something similar in model binder. I need to make some DB lookups in the binder. I'm thinking of doing it the same way I do it in controllers but I am open to suggestion.
This is a snippet from one of my controllers so you can imagine how I'm doing it in them:
public class WidgetZoneController : BaseController
{
// BaseController has IContentRepository ContentRepository field
public WidgetZoneController() : this(new XmlWidgetZoneRepository())
{
}
public WidgetZoneController(IContentRepository repository)
{
ContentRepository = repository;
}
...
Because the binder typically bind an entity, you don't need a specific repository like IContentRepository, indeed IRepository<T> will be good to get the entity.
To instantiate the IRipository you can use something like that:
var repositoryType = typeof (IRepository<>).MakeGenericType(entityType);
I suggest you take a look on the CodeCampServer implementation of entities binder, over here:
http://code.google.com/p/codecampserver/source/browse/trunk#trunk/src/UI/Binders/Entities
You can use constructor injection to your custom model binder class, and also inherit from the DefaultModelBinder.
public class MyModelBinder : DefaultModelBinder
{
IContentRepository ContentRepository;
public MyModelBinder(IContentRepository contentRepository)
{
this.ContentRepository = contentRepository;
}
With custom model binders, you register them in Application_Start() like this:
protected void Application_Start()
{
System.Web.Mvc.ModelBinders.Binders.Add(
typeof(MyModel), new MyModelBinder(contentRepository)
);
Now when using IoC, you need to keep in mind the lifetime of your objects. When you use IoC with Controllers, they exist per web request. So if you inject the Repository, any data connections or OR/M sessions will exist for only that short time.
With the Model Binder, it is basically a long-lived Singleton ( Application_Start() ). So make sure your Repository works in both cases.
If you don't know what I'm talking about either go through the tutorial and try to add dependency Injection yourself or try your luck with my explanation of the problem.
Note: This problem isn't within the scope of the original tutorial on ASP.NET. The tutorial only suggests that the patterns used are dependency injection friendly.
The problem is basically that there is a dependency loop between the Controller, the ModelStateWrapper and the ContactManagerService.
The ContactController constuctor takes an IContactManagerService.
The ContactManagerService constructor takes an IContactManagerRepository (not important) and an IValidationDictionary (which ModelStateWrapper implements).
The ModelStateWrapper constructor takes a ModelStateDictionary (which is a property called "ModelState" on the controller).
So the dependency cycle goes like this: Controller > Service > ModelStateWrapper > Controller
If you try to add dependency injection to this, it will fail. So my question is; what should I do about it? Others have posted this question, but the answers are few, different, and all seem kinda "hack-ish".
My current solution is to remove the IModelStateWrapper from the IService constructor and add an Initialize method instead like this:
public class ContactController : Controller
{
private readonly IContactService _contactService;
public ContactController(IContactService contactService)
{
_contactService = contactService;
contactService.Initialize(new ModelStateWrapper(ModelState));
}
//Class implementation...
}
public class ContactService : IContactService
{
private IValidationDictionary _validationDictionary;
private readonly IContactRepository _contactRepository;
public ContactService(IContactRepository contactRepository)
{
_contactRepository = contactRepository;
}
private void Initialize(IValidationDictionary validationDictionary)
{
if(validationDictionary == null)
throw new ArgumentNullException("validationDictionary");
_validationDictionary = validationDictionary;
}
//Class implementation...
}
public class ModelStateWrapper : IValidationDictionary
{
private readonly ModelStateDictionary _modelState;
public ModelStateWrapper(ModelStateDictionary modelState)
{
_modelState = modelState;
}
//Class implementation...
}
With this construct I can configure my unity container like this:
public static void ConfigureUnityContainer()
{
IUnityContainer container = new UnityContainer();
// Registrations
container.RegisterTypeInHttpRequestLifetime<IContactRepository, EntityContactRepository>();
container.RegisterTypeInHttpRequestLifetime<IContactService, ContactService>();
ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(container));
}
Unfortunately this means that the "Initialize" method on the service has to be called manually by the controller constructor. Is there a better way? Maybe where I somehow include the IValidationDictionary in my unity configuration? Should I switch to another DI container? Am I missing something?
As a general consideration, circular dependencies indicate a design flaw - I think I can safely say this since you are not the original author of the code :)
I wouldn't consider an Initialize method a good solution. Unless you are dealing with an add-in scenario (which you aren't), Method Injection is not the right solution. You have almost already figured that out, since you find it unsatisfactory that you need to manually invoke it because your DI Container can't.
Unless I am entirely mistaken, the ContactController doesn't need the IValidationDictionary instance before its Action methods are being invoked?
If this is true, the easiest solution would probably be to define an IValidationDictionaryFactory interface and make the ContactController constructor take an instance of this interface.
This interface could be defined like this:
public interface IValidationDictionaryFactory
{
IValidationDictionary Create(Controller controller);
}
Any Action method on the controller that needs an IValidationDictionary instance can then invoke the Create method to get the instance.
The default implementation would look something like this:
public class DefaultValidationDictionaryFactory : IValidationDictionaryFactory
{
public IValidationDictionary Create(Controller controller)
{
return controller.ModelState;
}
}
How about slightly changing/improving the design to something like this: http://forums.asp.net/t/1486130.aspx
Each controller has a virtual method Initialize to do stuff like that.
I think there is no better way because the IValidationDictionary is an abstraction layer between you current request/controller/modelstate and the IContactService. Injecting controllers modelstate into the service and then injecting the service into the controller is simply impossible using constructor injection. One has to be first.
May be there is a way using property injection? But I think this will be complicated too.
i'm just starting out with asp.net mvc. It's a long way before you can really get to a live project. At the moment i'm working to build a blog using the asp.net mvc unleashed book.
However, i don't understand the 2 constructors in the BlogController (see question below)
Thx...
FIRST
The BlogController has a private variable '_repository'
Private _repository As BlogRepositoryBase
Public MustInherit Class BlogRepositoryBase
'blog entry methods
Public MustOverride Function ListBlogEntries() As List(Of BlogEntry)
Public MustOverride Sub CreateBlogEntry(ByVal BlogEntryToCreate As BlogEntry)
Public MustOverride Function QueryBlogEntries() As IQueryable(Of BlogEntry)
End Class
The BlogRepositoryBase gets inherited by EntityFrameworkBlogRepository _
The EntityFrameworkBlogRepository connects with BlogDBEntities
NEXT
The controller has 2 constructors 'new' and 'new with a parameter'
Public Sub New()
Me.New(New EntityFrameworkBlogRepository())
End Sub
Public Sub New(ByVal repository As BlogRepositoryBase)
_repository = repository
End Sub
QUESTIONS
What's going on with the constructors, i don't get that
How can a class of type 'EntityFrameworkBlogRepository' be passed to 'sub new' as BlogRepositoryBase? Isn't that another type?
The default constructor is calling the constructor with a parameter with a new instance of a particular type of BlogRepositoryBase class. EntityFrameworkBlogRepository must derive from this base class. The reason that you specify the base class (I would have used an interface, but I digress) is so in your tests you can specify a different type of repository -- one, perhaps, that doesn't even connect to a database by instantiating it directly via the non-default constructor. The framework wiil always use the default constructor, thus you have to both provide it and provide a suitable implementation of the repository using it.
FWIW -- this is how I would do it (in C# -- my brain isn't working well enough to translate into VB, yet).
protected IBlogRepository Repository { get; set; }
public BlogController() : this( null ) {}
public BlogController( IBlogRepository repository )
{
this.Repository = repository ?? new EntityFrameworkBlogRepository();
...
}
Tested as
public void Test()
{
var repository = MockRepository.GenerateMock<IBlogRepository>();
var controller = new BlogController( repository );
...
repository.VerifyAllExpectations();
}
EntityFrameworkBlogRepository is derived from BlogRepositoryBase
The 'magic' in the constructors is called Dependency Injection. (Wiki has more on that here.) In short, it is a way of making your code more maintainable and testable by passing it it's dependencies ... if you change the repository type you need not rip out most of your code.
Kindness,
Dan
Coding custom IControllerFactory or DefaultControllerFactory inherits class. And SetControllerFactory global.asax.
Haaked becomes reference very much.
TDD and Dependency Injection with ASP.NET MVC