How should I call model class which is written in MVC? - asp.net-mvc

Hi I have model class which is written in MVC.I am using Ef database first approach. In model class I have some queries which deals with database. I have following questions :
1) Is it right way to use database related queries in Model and call that in controller or view?
2)If yes where I should call this model? In Controller or in view ??
3)How I should call this model? Say for example I have class called class1.cs in model.How I should call this model?

Your model contains classes that define the different objects troughout your project. This includes properties with their basic information and methods to perform actions on this object.
1)
Do you really need queries? Why not use the Entity Framework to do it for you? Create the mapping for your domain classes (either trough annotations or fluent api) and use the DbContext to retrieve and save the data stored in your database
2)
Ideally people create repositories that are injected into your controllers (Dependency Injection). These repositories can for example contain something like GetPersonById(int id). Inside this method there would be two things:
Perform an action on the domain object
Save it to the DbContext
For example:
public void Subscribe(int userID, Show show) {
var user = GetUserByID(userID);
if (!user.IsSubscribedTo(show.ShowID)) {
user.Subscribe(show);
_dbContext.SaveChanges();
}
}
Controller -> Method call in repository -> Perform action on corresponding domain object -> Save changes to the database
If you need something that doesn't require an object mutation, it's even more simple:
public User GetUserByID(int id) {
return _dbContext.Users.FirstOrDefault(x => x.ID == id);
}
3)
Trough repositories (see above). Your DbContext will have a bunch of DbSets that contain objects that correspond with every data entry in your database. Trough repositories you can work with these objects and manipulate them. When you call the DbContext.SaveChanges() method, it will look at what has changed in these lists and commit the changes to your database.
Repository example:
class User {
public int ID { get; set; }
public string Name { get; set; }
}
class DatabaseContext : DbContext {
public DbSet<User> Users { get; set; }
}
public interface IUserRepository {
User GetUserByID (int id);
bool UsernameExists (string name);
}
public class UserRepository : IUserRepository {
private DatabaseContext _db;
public UserRepository(DatabaseContext db){
_db = db;
}
public User GetUserByID(int id) {
return _db.Users.FirstOrDefault(x => x.ID == id);
}
public User GetUserByUsername(string username) {
return _db.Users.FirstOrDefault(x => x.Name == username);
}
}
public class UserController : Controller {
private IUserRepository _userRepository;
public UserController(IUserRepository userRepository) {
_userRepository = userRepository;
}
public ActionResult Details(int id){
return View(_userRepository.GetUserByID(id);
}
}
// Ninject settings (install this extension, you want it):
private void AddBindings(){
kernel.Bind<DatabaseContext>().ToSelf().InSingletonScope();
kernel.Bind<IUserRepository>().To<UserRepository>().InRequestScope();
}

You could use some sort of Unit Of Work pattern which you inject in your controller constructor using an inversion of control container (IOC), for instance autofac.
Your unit of work class could hold a reference to repositories, where you would query/insert your data.
Roughly;
public class BackendController : Controller
{
private UnitOfWork _worker;
public BackendController(UnitOfWork worker)
{
this._worker = worker;
}
public ActionResult Admin()
{
var items = _worker.MyRepository.GetAll();
return View(items);
}
}
public class UnitOfWork
{
private ContentRepository _contentRepository;
public UnitOfWork()
{
}
public ContentRepository MyRepository
{
get
{
if (_contentRepository != null)
return _contentRepository;
else
return _contentRepository = new ContentRepository();
}
}
}
public class ContentRepository
{
// holds an object context and methods to retrieve and put data (EF or similar)
}
You would have to register your instance with the IOC container in global.asax, application_start for example, something like this (Using autofac as IOC):
UnitOfWork worker = new UnitOfWork();
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterInstance(worker).SingleInstance();
var container = builder.Build();
...

1) Is it right way to use database related queries in Model and call that in controller or view?
I would recommend not directly accessing the database in your model classes, as you have to remember that MVC is strictly a presentation layer pattern. If you do put your database access logic in your model classes, then you will not be able to have any other client use this functionality, such as a web service. Instead have logic that translates your business objects, defined outside of your ASP.NET MVC project, into your ASP.NET MVC model classes.
This is where the power of n-tier architecture shines, if you create a business and data-access layer, then I could write an ASP.NET MVC front-end, WebForms front-end, WPF front-end, WinForms front-end and all of them could access data using the same service. By putting the logic into the ASP.NET MVC model classes, then you are effectively forcing any other client to duplicate that logic again in their classes.

Related

ASP.NET MVC 5: Inject a repository into an IValidatableObject

I have a class that implements the IValidatableObject interface, in order to validate the incoming data introduced by the user. The problem is that in order to validate that data, I need to use a class that implements the data repository pattern, which is in another assembly. Something like this:
public class SelectedFilteringCriteria : IValidatableObject
{
private IFiltersRepository _filtersRepository;
public SelectedFilteringCriteria(IFiltersRepository filtersRepository)
{
_filtersRepository = filtersRepository;
}
public int? SelectedValue { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var results = new List<ValidationResult>();
var valueOk = _filtersRepository.GetFilters().Any(
filter => filter.Value == SelectedValue
);
if (!valueOk)
{
results.Add(new ValidationResult("Not good :("));
}
return results;
}
}
The dependency container I'm using is Ninject. I would like to know if there's a way to tell MVC to inject the repository class into the IValidatableObject when it's going to be created.
Nope, it seems it's not possible because the MutableObjectModelBinder class, which is the one MVC 5 uses to create the corresponding object (SelectedFilteringCriteria in my case) from the action parameters, uses System.Activator instead of resolving the dependencies SelectedFilteringCriteria could have using the current DependencyResolver.
A workaround for this could be to do this inside the constructor of SelectedFilteringCriteria:
public SelectedFilteringCriteria()
{
_filtersRepository = DependencyResolver.Current.GetService<IFiltersRepository>();
}
But that could drive to the Service Locator Antipattern. Your choice.

How to Model one to many relationship with Dapper AND ASP.NET MVC

I'm new to Dapper or even ASP.NET MVC and I'm trying to write what should be a very simple CRUD app. Basically I have two tables User and File. User table stores some details about the User and when you click details it should display some more details and any files that user will upload (there can be none or up to 10).
File table stores the filenames. How do I create a model and then view for something like this using Dapper. It seems simple but I can't seem to figure this out. Can I put both models on my view and then loop through the file model to display the files if any. if so then how?
here is my details controller.
public ActionResult Details(int id)
{
Users user = new Users();
using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myconn"].ConnectionString))
{
user= db.Query<Users>("SELECT * FROM Users As t LEFT JOIN Files AS f ON t.EID = f.EID WHERE t.EID=" +id, new{ id }).SingleOrDefault() ;
}
return View(trade);
}
First of all try to read more about architecture, learn how to organize your code at the first place. For instance calling database directly from controller is a bad idea. I would do something like this:
Move all database calls to separate repository classes according to responsibilities.
public class UsersRepository
{
public User GetUser(int id)
{
User user = new User();
using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myconn"].ConnectionString))
{
user= db.Query<User>("SELECT * FROM Users where EID=#id", new{ id }).SingleOrDefault();
}
return user;
}
public List<File> GetUserFiles(int id)
{
List<File> files = new List<File>();
using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myconn"].ConnectionString))
{
files = db.Query<File>("SELECT * FROM Files where UserID=#id", new{ id });
}
return files;
}
}
Create model to store your data for detail view
public class UserDetails
{
public User User { get; set; }
public List<File> Files { get; set; }
}
Create service or engine to organize you business logic
public class UsersService
{
private UsersRepository _usersRepository;
public UsersService()
{
_usersRepository = new UsersRepository();
}
public UserDetails GetUserDetails(int userId)
{
var details = new UserDetails();
details.User = _usersRepository.GetUser(id);
details.Files = _usersRepository.GetUserFiles(id);
return details;
}
}
Call it in controller
public class UsersController : Controller // or whatever the base class you have
{
private UsersService _usersService;
public UsersController()
{
_usersService = new UsersService();
}
public ActionResult Details(int id)
{
var details = _usersService.GetUserDetails(id);
return View(details);
}
}
But keep in mind that its very simplified example. For instance it is better to use dependency injection rather than initialize services or repositories in constructor. Also in many cases it is not very smart to use same classes for view and repository logic, consider using DTO and domain classes insead. For simple apps and demonstraion it should be ok though.

JavaScriptSerializer circular reference when using ScriptIgnore

I have my Entity Framework Entities split out into a separate class library from my web project and data access layer. In my controller I make a call to my repository to get an IEnumerable<RobotDog.Entities.Movie> and then try to serialize into json using JavaScriptSerializer but I get a circular reference even though I'm using the [ScriptIgnore] attribute.
IMPORTANT: Originally I had my entities, data access and web all under one project and I was able to successfully serialize my entites without a circular reference. When I created separate layers that's when I started having problems. I did not change any of the entities.
An example of one of my entities in the RobotDog.Entities namespace:
namespace RobotDog.Entities {
public class Character {
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[MaxLength(200)]
public string Name { get; set; }
public virtual Person Person { get; set; }
[ScriptIgnore]
public virtual Movie Movie { get; set; }
}
}
My controller:
namespace RobotDog.Web.Controllers {
public class MoviesController : Controller {
private UnitOfWork _unitOfWork = new UnitOfWork();
[HttpGet]
public ActionResult Index() {
var user = Membership.GetUser(User.Identity.Name);
if(user != null) {
var movies = _unitOfWork.UserMovieRepository.Get(u => u.UserId == (Guid) user.ProviderUserKey).Select(m => m.Movie);
var serializer = new JavaScriptSerializer();
var json = serializer.Serialize(movies);
return View(json);
}
return View();
}
}
}
My Repository:
namespace RobotDog.DataAccess.Movies {
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class {
internal MovieContext Context;
internal DbSet<TEntity> DbSet;
public Repository(MovieContext context) {
if (context == null)
throw new ArgumentNullException("context");
Context = context;
DbSet = Context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> predicate = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null ) {
IQueryable<TEntity> query = DbSet;
if (predicate != null)
query = query.Where(predicate);
return orderBy != null ? orderBy(query).ToList() : query.ToList();
}
}
}
Maybe kinda late response, but I had similar problem with POCO Classes for Entity Framework Code-Firts. The problem was that may properties were declared as virtual. In this case EF creates proxy class which overrides the virtual property. It seems that ScriptIgnore attribute is not by default applied on overriden properties, unless you use it like this:
[ScriptIgnore(ApplyToOverrides=true)]
Circular object graphs cannot be JSON serialized. And when you give it a second thought it actually makes sense. The correct way to handle this is to use view models. You should never pass your domain entities directly to your views. Always define a view model containing only the necessary properties that you want to be exposed.
I am sure that the client consuming this JSON doesn't care about having this circular object graph. So simply define a view model breaking this circular dependency and including only the properties you need.
Then all you have to do is map your domain model to the view model and pass this view model to a JsonResult (yeah that's another issue in your code - you are manually JSON serializing and writing plumbing code in your controller action instead of delegating this to the framework).
So:
[HttpGet]
public ActionResult Index()
{
var user = Membership.GetUser(User.Identity.Name);
if(user != null)
{
IEnumerable<Movie> movies = _unitOfWork
.UserMovieRepository.Get(u => u.UserId == (Guid) user.ProviderUserKey)
.Select(m => m.Movie);
IEnumerable<MovieViewModel> moviesVm = ... map the domain model to your view model
return Json(moviesVm, JsonRequestBehavior.AllowGet);
}
// return an empty movies array
var empty = Enumerable.Empty<MovieViewModel>();
return Json(empty, JsonRequestBehavior.AllowGet);
}
The important thing you should be focusing right now on is defining the MovieViewModel class which will contain only the information that you want to expose to the client as JSON. Break all circular references. Feel free to have additional view models that this main view model is referencing in order to map other entities.
And most importantly : never pass your domain models to the view. Always define view models. This way your application is completely independent of the underlying data access technology you are using. You could modify your DAL layer as much as you like without impacting the UI part because this UI is represented by view models.

MVC4 TDD with multiple layers

I am learning about DI, IoC and MOQ so I can TDD my new MVC4 application.
I followed a lot of examples online but there is one thing I cannot get my hands around.
My application consists out of 3 layers (physical projects):
Application layer (controllers / models / standard MVC4 stuff).
Business layer (does all the calculating and processing data).
DAL (EF5).
Now I have a very simple UserController
public class UserController : Controller
{
readonly IUserRepository _repository;
public UserController(IUserRepository rep)
{
_repository = rep;
}
public ActionResult Index()
{
IList<User> users = _repository.Get(10);
return View(users);
}
Dependency is injected with Unity and this works fine.
In the business layer I have the repositories:
public interface IUserRepository
{
IList<User> Get(Int32 count);
}
public class UserRepository : IUserRepository
{
public IList<User> Get(Int32 count)
{
// Here I fetch the data from the Database
// and do some stuff with it, this can be
// quite a big method.
}
}
Now I need to access my DAL which I can do in my UserRepository's Get method.
Only how do I unit test this? There should not be a dependency in the class I think because of the testability.
If I use the actual UserRepository class in my unit test to test it will go to the DAL and use data from there, but I need mock data.
Do I need to make another IUserDataRepository where the actual data is fetched from the database and pass this into the UserRepository constructor or should I use Unity to handle this for me?
Possible answer?
I created a new interface called Users:
public class Users: IUsers
{
private readonly IUserRepository _userRepository;
public Users(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public User Get(String id)
{
// Do all the magic here here
}
}
From this interface IUsers:
public interface IUsers
{
User Get(String id);
}
But I moved my database oriented repositories to the DAL:
public class UserRepository : IUserRepository
{
public User Get(String id)
{
// Retrieve the user from the database with EF5
}
}
public interface IUserRepository
{
User Get(String id);
}
The controller stayed about the same, but now has a dependency to the IUser interface:
public class UserController : Controller
{
readonly IUsers _users;
public UserController(IUsers users)
{
_users = users;
}
public ActionResult Index()
{
User user = _users.Get(10);
return View(users);
}
}
Repositories are the gateway to the database. They contain the smallest amount of code as possible (no business stuff) and just do what it takes to get the data out of the database (or save it into the database).
Since it is directly coupled to your database, you can't unit test it. You could only unit test it when you abstract that logic away, but that is exactly what repositories are for, so that is a useless abstraction.
Instead, write integration tests for them that set up a database transaction and call the real repository and rollback that transaction when done.
Write a mock IUserRepository that returns the appropriate data, although to be honest you can easily mock out the underlying data in EF4 onwards so you can directly test out your EF queries in your controller if you want. In EF4 you replace the ObjectSet with fake ObjectSets that implemented IObjectSet - I'm fairly sure that with EF5 you can do the same with DbSet.
If we are using Unity. we can implement an extension of Unity container in the middle layer and register in the Presentation layer like below.
//Data Layer dependency mapping as extension eg : IUnitOfWork
container.AddNewExtension<DependencyInjectionExtension>();
More details please follow article.
N-tier with DI (Unity)
Thanks

Fluent Validation in ASP.net MVC - Database Validations

I'm using the Fluent Validation framework in my ASP.net MVC 3 project. So far all of my validations have been very simple (make sure string is not empty, only a certain length, etc.) but now I need to verify that something exists in the database or not.
Should Fluent Validation be used in this case?
If the database validation should be done using Fluent Validation, then how do I handle dependencies? The validator classes are created automatically, and I would need to somehow pass it one of my repository instances in order to query my database.
An example of what I'm trying to validate might:
I have a dropdown list on my page with a list of selected items. I want to validate that the item they selected actually exists in the database before trying to save a new record.
Edit
Here is a code example of a regular validation in Fluent Validation framework:
[Validator(typeof(CreateProductViewModelValidator))]
public class CreateProductViewModel
{
public string Name { get; set; }
public decimal Price { get; set; }
}
public class CreateProductViewModelValidator : AbstractValidator<CreateProductViewModel>
{
public CreateProductViewModelValidator()
{
RuleFor(m => m.Name).NotEmpty();
}
}
Controller:
public ActionResult Create(CreateProductViewModel model)
{
if(!ModelState.IsValid)
{
return View(model);
}
var product = new Product { Name = model.Name, Price = model.Price };
repository.AddProduct(product);
return RedirectToAction("Index");
}
As you can see, I never create the Validator myself. This works because of the following line in Global.asax:
FluentValidation.Mvc.FluentValidationModelValidatorProvider.Configure();
The problem is that now I have a validator that needs to interact with my database using a repository, but since I'm not creating the validators I don't know how I would get that dependency passed in, other than hardcoding the concrete type.
Can't you just create your own validation method where in you would kick-off the database validation?
RuleFor(m => m.name)
.Must(BeInDatabase)
private static bool BeInDatabase(string name)
{
// Do database validation and return false if not valid
return false;
}
I'm using FluentValidation for DataBase validations. just pass the Validation class the session in the Ctor. and do the validation inside the action something like:
var validationResult = new ProdcutValidator(session).Validate(product);
Update: Based on your example I add my example...
public class CreateProductViewModel
{
public string Name { get; set; }
public decimal Price { get; set; }
}
public class CreateProductViewModelValidator : abstractValidator<CreateProductViewModel>
{
private readonly ISession _session;
public CreateProductViewModelValidator(ISession session)
{
_session = session;
RuleFor(m => m.Name).NotEmpty();
RuleFor(m => m.Code).Must(m, Code => _session<Product>.Get(Code) == null);
}
}
Controller:
public ActionResult Create(CreateProductViewModel model)
{
var validator = new CreateProductViewModelValidator();
var validationResult =validator.Validate(model);
if(!validationResult.IsValid)
{
// You will have to add the errors by hand to the ModelState's errors so the
// user will be able to know why the post didn't succeeded(It's better writing
// a global function(in your "base controller" That Derived From Controller)
// that migrate the validation result to the
// ModelState so you could use the ModelState Only.
return View(model);
}
var product = new Product { Name = model.Name, Price = model.Price };
repository.AddProduct(product);
return RedirectToAction("Index");
}
Second update:
If you insist using parameterless constructor you will have to use some Inversion Of control container, a static class that is something like the Factory of your objects.
use it like this:
public class CreateProductViewModelValidator : abstractValidator<CreateProductViewModel>
{
private readonly ISession _session;
public CreateProductViewModelValidator()
{
_session = IoC.Container.Reslove<ISession>();
RuleFor(m => m.Name).NotEmpty();
RuleFor(m => m.Code).Must(m, Code => _session<Product>.Get(Code) == null);
}
}
You can find many IoC containers, most famous are Windsor and Ninject,
You will need to register- instruct the container once to resolve all the ISession to return your's session object.
The other way this could work for you is using Constructor injection. While this method isn't as clear cut as using an IoC library, it may help if you have a static way of accessing or fetching your session.
public class CreateProductViewModelValidator
{
private ISession _session;
public CreateProductViewModelValidator()
:this(SessionFactory.GetCurrentSession()) //Or some other way of fetching the repository.
{
}
internal CreateProductViewModelValidator(ISession session)
{
this._session = session;
RuleFor(m => m.Name);//More validation here using ISession...
}
}
I have been spending quite a bit of time thinking about this exact same issue. I am using ninject to inject my repository into my web UI layer so that my web UI only accesses the database through an interface.
I am wanting to be able to validate things that access the database such as checking for duplicate names and hence my validation needs to access the injected repository. I think that the best way to do this is to just setup Fluent Validation via the manual method rather than the MVC integrated way. For Example:
Create your validation Class (can pass in repository Interface):
public class CategoryDataBaseValidation : AbstractValidator<CategoryViewModel>
{
private IRepository repository;
public CategoryDataBaseValidation (IRepository repoParam)
{
repository = repoParam;
RuleFor(Category => Category.Name).Must(NotHaveDuplicateName).WithMessage("Name already exists");
}
private bool NotHaveDuplicateName(string name)
{
List<Category> c = repository.Categories.ToList(); //Just showing that you can access DB here and do what you like.
return false;
}
}
}
Then in your controller you can just create an instance of above class and pass in the repository (that ninject would have injected in the controller constructor)
[HttpPost]
public ActionResult Create(CategoryViewModel _CategoryViewModel )
{
CategoryDataBaseValidation validator = new CategoryDataBaseValidation (repository);
ValidationResult results = validator.Validate(_CategoryViewModel );
if (results.IsValid == false)
{
foreach (var failure in results.Errors)
{
//output error
}
}
return View(category);
}
Both the above files can live in the Web UI project and you can then also just use the standard MVC DataAnnotations for client side validation.
Just thought that I would put this up for comment / help someone.

Resources