I'm building an MVC3 application using the Entity Framework. In the application my controllers talk to a service layer. One of the controllers is a TournamentController which uses the TournamentService. This service has some standard methods such as CreateTournament, UpdateTournament etc.
When I want to insert a new tournament I want the view to have a dropdownlist of possible sports for which the tournament can be organised. So in the TournamentController's Create method I fill the ViewBag.Sports with a list of possible sports. Now to obtain this list of sports I use _tournamentService.GetAllSports(). In this GetAllSports() method of the TournamentService I want to create an instance of the SportService so I can 'forward' the question to the right service.
All services use dependency injection in the constructor to inject their own repository, like so:
private ITournamentRepository _repo;
public TournamentService(ITournamentRepository repo) {
_repo = repo;
}
My GetAllSports() method in the TournamentService looks like this:
public IEnumerable<Sport> GetAllSports() {
ISportService sportService = new SportService();
return sportService.GetSports();
}
The problem is that by calling the new SportService() it expects me to hand it an ISportRepository like in the TournamentService, where ninject creates the TournamentRepository. Now I could do the following:
public IEnumerable<Sport> GetAllSports() {
ISportService sportService = new SportService(new SportRepository());
return sportService.GetSports();
}
But the problem with that is that each repository expects an IContext, which is normally handled by ninject as well. Furthermore, I don't want two separate contexts to be instantiated.
A possible solution I found myself is to do this:
private ITournamentRepository _repo;
private ISportService _sportService;
public TournamentService(ITournamentRepository repo, ISportService sportService) {
_repo = repo;
_sportService = sportService
}
But there's only one method in my TournamentService class that would actually use the _sportService so I figure this is a bit overkill to make it a class attribute.
Keep it simple, inject ISportService to your controller and call sportService.GetSports() directly from the controller!
Your last solution valid. Inject the necessary service as part of the constructor.
And if you're worried about multiple contexts, don't let two separate contexts be created then.
In your Ninject binding:
Bind<ITournamentRepository>().To<TournamentRepository>().InRequestScope();
See https://github.com/ninject/Ninject.Web.Common/wiki/InRequestScope
The last piece is the important part. It will only create one instance of TournamentRepository for the current request. Any other requesters of TournamentRepository will get this instance.
If you're already doing this, you're set, otherwise, just add InRequestScope and you're done. (keeping in mind you'll need a reference to Ninject.Web.Common)
Hope that helps.
EDIT:
Remo is correct, I wouldn't call this from a service either. Just call for your lookup data from the controller and populate your view model. The InRequestScope advice still holds.
Related
The code seems straightforward for an adapter provider, something like this:
public class KittensMustBeCuteAttributeAdapterProvider : IValidationAttributeAdapterProvider
{
private readonly IValidationAttributeAdapterProvider _baseProvider = new ValidationAttributeAdapterProvider();
public IAttributeAdapter GetAttributeAdapter(ValidationAttribute attribute, IStringLocalizer stringLocalizer)
{
if (attribute is KittensMustBeCuteAttribute)
{
return new KittensMustBeCuteAttributeAdapter(attribute as KittensMustBeCuteAttribute, stringLocalizer);
}
else
{
return _baseProvider.GetAttributeAdapter(attribute, stringLocalizer);
}
}
}
Looks to me like I could rename this adapter provider to be generic and use it for all of my custom attributes, as I have several (not just KittensMustBeCuteAttribute).
However I can't find anything indicating on whether or not this is OK or if you need one each. All of the examples I've seen have it named like I have, specific to the attribute.
Can I just re-use one AdapterProvider by expanding my if statement?
Seems I should have just kept going, it became apparent afterwards that the adapter provider is registered as a singleton to be resolved through DI, therefore you have to have a single one containing all your custom attributes.
This test is to check that I can return a ViewModel object by creating a customer and calling the Details() controller method.
[TestMethod()]
public void Can_View_AccountDetails()
{
AccountController target = new AccountController(null, null, null, null);
target.customer = new Customer { Id = 4, Active = true, BillingAddress_Id=1, ShippingAddress_Id=2 };
// Act
ActionResult result = target.Details();
// Assert
var resultData = ((ViewResult)result).ViewData.Model as AccountViewModel;
Assert.IsInstanceOfType(resultData, (typeof(AccountViewModel)));
}
'customer' is a member of the controller base class, which is then assigned in Initialize(). Initially I couldn't assign anything to it, but by setting it to 'public' rather than 'protected' I was able to use it in my test and avoided trying to call the base class Initialize() method.
EDIT: 'customer' is populate from a Repository object injected into the base class constructor.
Is this the right way to do this? It seems somehow wrong to change the accessibility level in order to get the test to work.
Also, although I'm trying to use Moq to create my tests, I'm not actually doing any mocking at all here which again, doesn't seem right.
I think your real problem is that the customer information "magically" shows up within the AccountController. The Customer instance should be injected into the AccountController from the outside since it is an external dependency. That being the case you would not have to make the customer property public because you pass it into the AccountController yourself.
Protected means it can only access from derived classes, so the test class would need to inherit the protected class.
Also you stubbed this as being Moq, but i don't see any Mock testing. You should be using interfaces that represent the Customer class so you can Mock the ICustomer interface.
You need to stub your Repository object and set it up so that it returns customer. Then, you don't need to expose .customer property as public (or internal) - you simply tell repository stub to return the one you'd like:
var repositoryStub = new Mock<IRepository>();
var customer = new Customer { /* ... */ };
repositoryStub.Setup(r => r.GetCustomer()).Returns(customer);
And naturally, you need to initialize your AccountContoller with stubbed dependency to repository (and other ones aswell, if needed):
var accountController = new AccountController(repositoryStub, ...);
This of course assumes your AccountController can take repository dependency.
So now, when you call Initialize() on base class, it should use stubbed repository and set your private .customer field to the one you specified it to return during stub setup.
Right now, I have a domain entity named StyleBundle. This StyleBundle takes a list of Styles:
public class StyleBundle
{
public StyleBundle(List<Style> styles)
{
this.Styles = styles;
}
public IEnumerable<Style> Styles { get; private set;}
}
So, in my original design, a StyleBundle should never be created with an empty Style list. This was a rule that the domain experts basically said was good.
I wrote this using a guard clause in the constructor:
if (styles.Count() == 0)
throw new Exception("You must have at least one Style in a StyleBundle.");
which made sure I could not create StyleBundle in an invalid state. I thought an exception made sense here b/c a StyleBundle being created without at least one Style was exceptional in the system.
Of course, change came down the road during the rest of the project, and now it should be possible for a user to create a StyleBundle without Styles, but they should not be allowed to PERSIST a StyleBundle without Styles.
So now I'm looking at my guard clause and realizing that I can't have the exception thrown from the constructor anymore.
Moving forward, I have a Service/Application layer that my code-behinds interact with when they're working with StyleBundles. In my Service Layer, I have a StyleBundleService class, and that class exposes basic functionality to the UI... among them is "CreateStyleBundle".
It seems as if I'll have to have my Service Layer check to see if the StyleBundle does or does not have any Styles before it's persisted to the database, but something about this decision feels "wrong" to me.
Anyone run into a similar thing? Basically, the different between the state of an object being valid when "new'ed up" vs. the state of the same object when it comes to persistence?
Thanks!
Mike
I would add an IsValid method to your entity. This would check if the entity is currently in a valid state (in your case, check if there are styles).
This method can be called from your Repository to check if an entity may be persisted. You can add more rules to the IsValid method for specific entities and you can implement something like a collection of Validation errors is you want to throw a meaningful exception.
Expanding what Wouter said, plus handy BeforeSaving and BeforeDeleting methods:
public interface IDomainObject<T>
{
bool IsValid();
}
public interface IEntity<T> : IDomainObject<T>
{
}
public interface IAggregateRoot<T> : IEntity<T>
{
void BeforeSaving();
void BeforeDeleting();
}
public interface IAggregateRoot { //or simply IEntity depending on the model
bool IsValid();
}
public class StyleBundle : IAggregateRoot<T> {
return styles.Count() > 0
}
public class StyleBundleRepository : Repository<StyleBundle> {
}
public abstract class Repository<T> : IRepository<T> where T : class, IAggregateRoot<T> {
public T Save(T t)
{
t.BeforeSaving(); //for all AggregateRoots, maybe logging what the aggregate was like before the changes
if(!t.IsValid())
throw Exeception("Entity invalid");
EntityStore.Current.SaveChanges();
// "AfterSaving" here, i.e.: log how the entity looks after the update
}
}
Edit: I dont personally use the IsValid idea, I go with a full class of EntityValidationErrors where I can report back to the client what was wrong before attempting to save, things that shouldnt be null, shouldnt be empty (like your Styles etc)
There are multiple strategies:
Some developers prefer to create 2 methods in the entity itself, one called IsValid() which validates the entity in terms of business rules (general validation) and another one called IsValidForPersistence() which validates the entity for persistence.
Regarding IsValid() I prefer instead not to allow invalid state in the first place by validating all inputs, and to support invariants I use factory or builder.
you may check the link http://www.codethinked.com/thoughts-on-domain-validation-part-1
for some thoughts.
I know, this question is three years old, but seeing the current answer is something I like to respond to. We are talking about the domain data. Hence, there can't be a valid StyleBundle with 0 objects. I imagine, you have a frontend editor somewhere, were you create a "new" StyleBundle and have to add at least one style, before hitting the "save" button.
At this point in the frontend, you won't have a domain object. You may have a data transfer object, that will be send with a "CreateNewStyleBundle" command.
In my opinion, the domain object must be agnostic to persitance and should always be in a valid state. If you have to call a "IsValid" method, you circumvent the whole idea of having domain objects in the first place.
That's just my humble opinion.
I'm currently working on an MVC 3 project using Ninject as my DI, the business objects are stored in a separate assembly. I'm running into an issue with the controller parameters, when posting back for CRUD operations I'm getting the error "Cannot create an instance of an interface". I am aware that you can't create an instance of an interface, but it seems like the only way I can get around this is to use a custom model binder and pass the FormCollection through. This seems really messy and I want to keep as much type specific code out of the project as I can - hence interfaces everywhere and Ninject to DI the concretes. Not only does custom model binding seem messy - won't I also lose my DataAnnotations?
Some code to describe what I have:
public ActionResult Create()
{
// I'm thinking of using a factory pattern for this part
var objectToCreate = new ConcereteType();
return (objectToEdit);
}
[HttpPost]
public ActionResult Create(IRecord record)
{
// check model and pass to repository
if (ModelState.IsValue)
{
_repository.Create(record);
return View();
}
return View(record);
}
Has anyone run into this before? How did you get over it?
Thanks!
but it seems like the only way I can get around this is to use a custom model binder
A custom model binder is the correct way to go. And by the way you should use view models as action arguments, not domain models or interfaces.
Not only does custom model binding seem messy - won't I also lose my DataAnnotations?
I don't know why you think that a custom model binder would make things messy. For me it's a great way to separate mapping logic into a reusable class. And, no you will not lose DataAnnotations. They will work perfectly fine on the concrete instance that the custom model binder would return.
Data passed to controllers action are simply holders for values. There shouldn't be any logic in them so there is nothing to decouple from. You can use concrete types (e.g Record) instead of interface (IRecord)
I made the same simple mistake. Ninject injects parameters into your constructor, but you added parameters to the Index Controller action.
It should look like this:
public class HomeController : Controller
{
private IRecord _record;
public HomeController(IRecord record)
{
_record = record;
}
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application. " +
_record .HelloWorld();
return View();
}
}
Make sense?
I am attempting to create the the business and data layers for my big ASP.NET MVC application. As this is the first time for me attempting a project of this scale I am reading some books and trying to take good care at separating things out properly. Usually my applications mix the business logic and data access layers, and multiple business entities are intertwined in the single class (which has confused me a few times when I was trying to figure out where to add things).
Most of what I have been reading is to separate out the business and data layers. This seems all fine and dandy, but I am having trouble visualizing exactly how to do this in some scenarios. For example, let's say I am creating a system that allows admins to add a new product to the system:
public class Product
{
public int Id { get; private set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
Then I separate out the data access by creating a repository
public class ProductRepository
{
public bool Add(Product product);
}
Let's say I want to require a product's name to have at least 4 characters. I can't see how to do this cleanly.
One idea I had was to expand the Name's set property and only set it if it's 4 characters long. However, there is no way for a method that is creating the product to know the name didn't get set except that Product.Name != whatever they passed in.
Another idea I had is to put it in the Add() method in the repository, but then I have my business logic right there with the data logic, which also means if the Add call fails I don't know if it failed for the business logic or because the DAL failed (and it also means I can't test it using mock frameworks).
The only thing I can think of is to put my DAL stuff in a 3rd layer that gets called from the Add() method in the repository, but I don't see this in any of the domain modelling examples in my book or on the web (that I've seen at least). It also adds to the complexity of the domain models when I am not sure it is needed.
Another example is wanting to make sure that a Name is only used by one product. Would this go in the Product class, ProductRepository Add() method, or where?
As a side note, I plan to use NHibernate as my ORM however, to accomplish what I want it (theoretically) shouldn't matter what ORM I am using since TDD should be able to isolate it all.
Thanks in advance!
I usually approach this by using a layered architecture. How to do this? You basically have the following (ideally) VS projects:
Presentation layer (where the UI stuff resides)
Business layer (where the actual business logic resides)
Data access layer (where you communicate with your underlying DBMS)
For decoupling all of them I use so-called interface layers s.t. in the end I have
Presentation layer (where the UI
stuff resides)
IBusiness layer (containing the interfaces for the
business layer)
Business layer (where
the actual business logic resides)
IDataAccess layer (containing the
interfaces for the DAO layer)
Data access layer (where you communicate
with your underlying DBMS)
This is extremely handy and creates a nicely decoupled architecture. Basically your presentation layer just accesses the interfaces and not the implementations itself. For creating the according instances you should use a Factory or preferably some dependency injection library (Unity is good for .Net apps or alternatively Spring.Net).
How does this impact on your business logic / testability of your app?
It is probably too long to write everything in detail, but if you're concerned about having a well testable design you should absolutely consider dependency injection libraries.
Using NHibernate,...whatever ORM
Having a DAO layer completely separated through the interfaces from the other layers you can use whatever technology behind for accessing your underlying DB. You could directly issue SQL queries or use NHibernate, as you wish. The nice thing is that it is totally independent from the rest of your app. You could event start today by writing SQLs manually and tomorrow exchange your DAO dll with one that uses NHibernate without a single change in your BL or presentation layer.
Moreover testing your BL logic is simple. You may have a class like:
public class ProductsBl : IProductsBL
{
//this gets injected by some framework
public IProductsDao ProductsDao { get; set; }
public void SaveProduct(Product product)
{
//do validation against the product object and react appropriately
...
//persist it down if valid
ProductsDao.PersistProduct(product);
}
...
}
Now you can easily test the validation logic in your SaveProduct(...) method by mocking out the ProductDao in your test case.
Put things like the product name restriction in the domain object, Product, unless you want to allow products with fewer than 4 characters in some scenarios (in this case, you'd apply the 4-character rule at the level of the controller and/or client-side). Remember, your domain objects may be reused by other controllers, actions, internal methods, or even other applications if you share the library. Your validation should be appropriate to the abstraction you are modeling, regardless of application or use case.
Since you are using ASP .NET MVC, you should take advantage of the rich and highly extensible validation APIs included in the framework (search with keywords IDataErrorInfo MVC Validation Application Block DataAnnotations for more). There are lots of ways for the calling method to know that your domain object rejected an argument -- for example, throwing the ArgumentOutOfRangeException.
For the example of ensuring that product names are unique, you would absolutely not put that in Product class, because this requires knowledge of all other Products. This logically belongs at the persistence layer and optionally, the repository. Depending on your use case may warrant a separate service method that verifies that the name does not already exist, but you shouldn't assume that it will still be unique when you later try to persist it (it has to be checked again, because if you validate uniqueness and then keep it around a while longer before persisting, someone else could still persist a record with the same name).
This is the way I do it:
I keep the validation code in the entity class, which inherits some general Item Interface.
Interface Item {
bool Validate();
}
Then, in the repository's CRUD functions i call the appropriate Validate function.
This way all the logic paths are validating my values, but i need to look only in one place to see what that validation really is.
Plus, sometimes you use the entities outside the repository scope, for example in a View. So if the validation is separated, each action path can test for validation without asking the repository.
For restrictions I utilize the partial classes on the DAL and implement the data annotation validators. Quite often, that involves creating custom validators but that works great as it's completely flexible. I've been able to create very complex dependent validations that even hit the database as part of their validity checks.
http://www.asp.net/(S(ywiyuluxr3qb2dfva1z5lgeg))/learn/mvc/tutorial-39-cs.aspx
In keeping with the SRP (single responsibility principle), you might be better served if the validation is separate from the product's domain logic. Since it's required for data integrity, it should probably be closer to the repository - you just want to be sure that validation is always run without having to give it thought.
In this case you might have a generic interface (e.g. IValidationProvider<T>) that is wired to a concrete implementation through an IoC container or whatever your preference may be.
public abstract Repository<T> {
IValidationProvider<T> _validationProvider;
public ValidationResult Validate( T entity ) {
return _validationProvider.Validate( entity );
}
}
This way you can test your validation separately.
Your repository might look like this:
public ProductRepository : Repository<Product> {
// ...
public RepositoryActionResult Add( Product p ) {
var result = RepositoryResult.Success;
if( Validate( p ) == ValidationResult.Success ) {
// Do add..
return RepositoryActionResult.Success;
}
return RepositoryActionResult.Failure;
}
}
You could go a step further, if you intend on exposing this functionality via an external API, and add a service layer to mediate between the domain objects and the data access. In this case, you move the validation to the service layer and delegate data access to the repository. You may have, IProductService.Add( p ). But this can become a pain to maintain due to all of the thin layers.
My $0.02.
Another way to accomplish this with loose coupling would be to create validator classes for your entity types, and register them in your IoC, like so:
public interface ValidatorFor<EntityType>
{
IEnumerable<IDataErrorInfo> errors { get; }
bool IsValid(EntityType entity);
}
public class ProductValidator : ValidatorFor<Product>
{
List<IDataErrorInfo> _errors;
public IEnumerable<IDataErrorInfo> errors
{
get
{
foreach(IDataErrorInfo error in _errors)
yield return error;
}
}
void AddError(IDataErrorInfo error)
{
_errors.Add(error);
}
public ProductValidator()
{
_errors = new List<IDataErrorInfo>();
}
public bool IsValid(Product entity)
{
// validate that the name is at least 4 characters;
// if so, return true;
// if not, add the error with AddError() and return false
}
}
Now when it comes time to validate, ask your IoC for a ValidatorFor<Product> and call IsValid().
What happens when you need to change the validation logic, though? Well, you can create a new implementation of ValidatorFor<Product>, and register that in your IoC instead of the old one. If you are adding another criterion, however, you can use a decorator:
public class ProductNameMaxLengthValidatorDecorator : ValidatorFor<Person>
{
List<IDataErrorInfo> _errors;
public IEnumerable<IDataErrorInfo> errors
{
get
{
foreach(IDataErrorInfo error in _errors)
yield return error;
}
}
void AddError(IDataErrorInfo error)
{
if(!_errors.Contains(error)) _errors.Add(error);
}
ValidatorFor<Person> _inner;
public ProductNameMaxLengthValidatorDecorator(ValidatorFor<Person> validator)
{
_errors = new List<IDataErrorInfo>();
_inner = validator;
}
bool ExceedsMaxLength()
{
// validate that the name doesn't exceed the max length;
// if it does, return false
}
public bool IsValid(Product entity)
{
var inner_is_valid = _inner.IsValid();
var inner_errors = _inner.errors;
if(inner_errors.Count() > 0)
{
foreach(var error in inner_errors) AddError(error);
}
bool this_is_valid = ExceedsMaxLength();
if(!this_is_valid)
{
// add the appropriate error using AddError()
}
return inner_is_valid && this_is_valid;
}
}
Update your IoC configuration and you now have a minimum and maximum length validation without opening up any classes for modification. You can chain an arbitrary number of decorators in this way.
Alternatively, you can create many ValidatorFor<Product> implementations for the various properties, and then ask the IoC for all such implementations and run them in a loop.
Alright, here is my third answer, because there are so very many ways to skin this cat:
public class Product
{
... // normal Product stuff
IList<Action<string, Predicate<StaffInfoViewModel>>> _validations;
IList<string> _errors; // make sure to initialize
IEnumerable<string> Errors { get; }
public void AddValidation(Predicate<Product> test, string message)
{
_validations.Add(
(message,test) => { if(!test(this)) _errors.Add(message); };
}
public bool IsValid()
{
foreach(var validation in _validations)
{
validation();
}
return _errors.Count() == 0;
}
}
With this implementation, you are able to add an arbitrary number of validators to the object without hardcoding the logic into the domain entity. You really need to be using IoC or at least a basic factory for this to make sense, though.
Usage is like:
var product = new Product();
product.AddValidation(p => p.Name.Length >= 4 && p.Name.Length <=20, "Name must be between 4 and 20 characters.");
product.AddValidation(p => !p.Name.Contains("widget"), "Name must not include the word 'widget'.");
product.AddValidation(p => p.Price < 0, "Price must be nonnegative.");
product.AddValidation(p => p.Price > 1, "This is a dollar store, for crying out loud!");
U can use a other validation system. you can add a method to IService in service layer such as:
IEnumerable<IIssue> Validate(T entity)
{
if(entity.Id == null)
yield return new Issue("error message");
}