In a controller, I do the following:
DBContext DB = new DBContext();
var u = DB.Users.Find(1);
u.firstname = "blah";
UpdateModel(u);
DB.SaveChanges();
I want to do the same from within a model...
namespace Project.Models
{
public class User
{
public void resetPassword()
{
// Generate new password, etc.
this.password = "blah";
}
}
}
Any idea how I go about doing this? It seems UpdateModel() is only available from within controllers.
I'm using EntityFramework Code-First CTP5.
I think UpTheCreek is correct but it probably needs some explanation so I'll try to expand on his/her answer. The first step would be to use the repository pattern. You can find many examples of this pattern in MVC with a google search - this is a particularly gentle introduction (about 3/4's down the page).
The walkthrough goes on to mention dependency injection, and that's something that's also worth looking in to. I tend to favor Ninject myself, however there are other dependency injection containers available.
Putting data access concerns in your model is not a good idea.
Update: Yes, you'd usually have a data access layer for this. As Andy says, the currently fashionable way to do this is using a repository. As a rule, you don't want anything in your model that is not core business logic.
Related
I've got an ASP.NET MVC application and am looking at ways to improve readability, testing, etc. Currently, much of the business logic is in the controller and I would like to move this to another location.
Here's one idea I have been looking at using: Entity framework creates entity classes for me (e.g. Product, Customer). Why not just create partial classes to store the business logic? Here is an example:
public partial class Product()
{
public static List<Product> GetGreenProducts()
{
using(MyEntities db = new MyEntities())
{
return db.Product.where(p => p.Color == "green").ToList();
}
}
}
Then, in the controller, I can do this:
public class ProductController : Controller
{
public ActionResult GreenProducts()
{
return View(Product.GetGreenProducts());
}
}
This approach seems 1) Very simple 2) Very clean 3) would allow for easy unit testing.
I think this is a relevant pattern. Can anyone identify any problems with this, or other thoughts?
There are two questions being asked here:
Why not extend EF classes with business log (as opposed to Controllers)?
Simple. Because business logic should not be coupled to EF anymore than it should be coupled to Controllers.
Essentially (and this is my interpretation of the OP's comment), why not put CRUD operations in EF as opposed to Controllers. Sample method given: UpdateLastModified does it belong in EF or a seperate Service?
UpdateLastModified is already far too coupled an example to begin with. You should not create a method to update a column on an entity. Do you also need UpdateCreatedBy, UpdateName, UpdateId? I sure hope not. EF gives you all the tools necessary to perform such trivial tasks.
The ProductService should be concerned with middle tier concerns, whatever they may be. Things like projecting the ProductEntity -> ProductDao and what have you. ProductService.UpdateLastModified should not exist.
I would ask also for best practices and patterns for asp.net MVC, using this example:
I have a project. This is its architecture:
Models
Controler
Views
Tools
In models folder I have every single ViewModel in separate class field. All of table declarations (objects) I put in one file (AccountModels.cs or ForumModels.cs). I have a separate file for EF context (MyAppContext.cs).
Controler - here I have only Controler classes. But maybe part of code will be better example and suggestion what can I improve:
private AppContext db = new AppContext ();
[HttpPost]
[Authorize]
public ActionResult AddGun(GunModel model)
{
if (ModelState.IsValid)
{
Gun gunToAdd = new Gun
{
Tilte = model.Tilte,
AuthorID = UserTools.getUser(User.Identity.Name).UserId,
AddDate = DateTime.UtcNow,
Content = model.Content,
CategoryID = model.CategoryID,
CategoryName = GunsTools.getCategoryName(model.CategoryID)
};
db.Guns.Add(gunToAdd);
db.SaveChanges();
return RedirectToAction("Details", new { ID = gunToAdd.ID });
}
return RedirectToAction("Index");
}
This is a part of controler with AddGun Action. Others ActionResults are similar - generaly I use lambda expression on my db context to get values etc.
Views - Views in separate folder, for Partial Views I set special prefix (for example - _NavigationPartial.cshtml or _CalculatorPartial.cshtml). Is there anything for improve here? Of course Views use ViewModels, not Models.
And at least - Tools. I've put here some classes and methods to prevent from repeating code. Here is some methods witch returns from database some objects or just strings, like GetUser(..) or GetCategoryName(..). Is it a good practise at all?
I think that many young MVC developers have the same project architecture (I personally saw it in a few companies) and many of them perhaps also wants to improve something in theirs projects to be a better programmers.
Regards
As noted in the comments above, it's hard to answer such a broad question, but I will make a couple of observations
It's not a great idea to use your database entities directly in your Controller, because that tightly couples your controller to the database and can lead to data being exposed to your view that really doesn't belong there.
Instead you should have a separate data layer that abstracts away the details of what a Gun entity is (from the perspective of the database) and what a Gun Model is (from the perspective of the View)
A randomly selected but good SO question about this is found here
You could consider using Dependency Injection (DI) for your controller
so that you have a constructor that looks like this:
readonly AppContext _db;
public GunController(AppContext db)
{
if (db==null) {throw new ArgumentNullException("db is null");}
_db=db;
}
You'll need to use a DI Container to this up. A randomly selected (but really good) article can be found here
Above all, keep asking questions, but try to keep them more specific i.e about specific areas of your app - and in no time you will have a really good picture of what is and isn't good practice!
I'm new to ASP.NET MVC, coming from a PHP MVC background. It's been kind of an awkward transition (see my question history, heh.)
One thing I like a lot in theory that's big in the .Net world is the idea of models being persistence agnostic. But in this case, what is the proper way to save changes to a model? In PHP, I'd just call $model->save(); after doing some transformation. In C#, I'm not sure of how to do that.
Is this appropriate?
public class AwesomesauceController
{
//inject!
public AwesomeSauceController(IDataAccess da)
{
DataAccess = da;
}
private readonly IDataAccess DataAccess;
[HttpGet]
public ActionResult Edit(int Id)
{
// PHP equiv: AwesomeSauceModel::find($id); Controller is unaware of DAL
return View(DataAccess.AwesomeSauces.Where( sc => sc.Id == Id).FirstOrDefault());
}
[HttpPost]
public ActionResult Edit(AwesomeSauce sc)
{
//persistence-aware version: model is aware of DAL, but controller is not
if($sc->valid()
$sc->save();
redirect();
}
else { return view(); }
// compare to persistence-agnostic version, controller is aware of DAL, but model is not
if(ModelState.IsValid)
{
da.Persist(sc);
return Redirect();
}
else
{
return View(sc);
}
}
}
I guess the only thing that strikes me as wrong about this is that typically, I wouldn't want a controller to be directly accessing a data access layer in this way. Previously, in PHP land, my controllers would access models and views only, basically.
What you are doing is fine. ActiveRecord vs Repository vs Home Brew DAL is an eternal question that we'll discuss forever.
The repository pattern is very popular in the .NET world right now and you'll probably see a lot of examples of its usage. MVC doesn't care what your data access strategy is though. Using whatever you find comfortable is just fine and a better strategy than using a pattern because everybody else is doing it.
It's OK for a model to have a Save() function, but you would usually want that Save() behavior to be independent of your model -- abstracted away to an interface.
Remember your design principles: design to an interface, not an implementation.
Another caveat is how do you test your pieces individually? If a model doesn't know how it's persisted, it can be tested based on what a model should do, and your persistence mechanism can be tested based on what it should do.
In any case, it looks like your Create() action is doing double duty -- trying to use the model to Save, then trying to use the DataAccess to persist. Are these two objects doing the same thing? Could this be confusing or unreadable/unmaintainable later on?
In the real world, Controllers can potentially need to use data from a variety of database tables and other data stores. For example:
[Authorize]
public class MembersController : Controller
{
ICourseRepository repCourse;
IUserCourseRepository repUserCourse;
IMember member;
public MembersController(ICourseRepository repCourse, IUserCourseRepository repUserCourse, IMember member)
{
this.repCourse = repCourse;
this.repUserCourse = repUserCourse;
this.member = member;
}
So:
Should I use a repository for each table?
I guess this is where the concept of agregates comes into play? Should I have one Repository per aggregate?
Do I just add as many Repositories as I need to the constructor of the Controller?
Is this a sign that my design is wrong?
NOTE:
The IMember interface essentially represents a helper object that puts a nice face on the Membership provider. Ie, it puts all the code in one place. For example:
Guid userId;
public Guid UserId
{
get
{
if (userId == null)
{
try
{
userId = (Guid) Membership.GetUser().ProviderUserKey;
}
catch { }
}
return userId;
}
}
One problem with that is surely caching this kind of output. I can feel another question coming on.
EDIT:
I'm using Ninject for DI and am pretty sold on the whole DI, DDD and TDD thing. Well, sort of. I also try to be a pragmatist...
1. Should I use a repository for each table?
Probably not. If you have a repository per table, you are essentially doing Active Record. I also personally prefer to avoid calling these classes "Repository" because of the confusion that can occur between Domain Driven Design's concept of a "Repository" and the class-per-table "Repository" that seems to have become commonly used with Linq2SQL, SubSonic, etc. and many MVC tutorials.
2. I guess this is where the concept of agregates comes into play? Should I have one Repository per aggregate?
Yes and yes. If you are going to go this route.
'3.' Do I just add as many Repositories as I need to the constructor of the Controller?
I don't let my controllers touch my repositories directly. And I don't let my Views touch my domain classes directly, either.
Instead, my controllers have Query classes that are responsible for returning View Models. The Query classes reference whatever repositories (or other sources of data) they need to compile the View Model.
Well #awrigley, here is my advise:
Q: Should I use a repository for each table?
A: No, as you mentioned on question 2. use a repository per aggregate and perform the operations on aggregate root only.
Q: Do I just add as many Repositories as I need to the constructor of the Controller?
A: I guess you´re using IoC and constructor-injection, well, in this case, make sure you only pass real dependencies. this post may help you decide on this topic.
(pst! that empty catch is not a nice thing!!) ;)
Cheers!
This all depends on how "Domain Driven Design" your going to be. Do you know what an Aggregate Root is? Most of the time a generically typed repository that can do all your basic CRUD will suffice. Its only when you start having thick models with context and boundaries that this starts to matter.
I'm trying to set up NHibernate in an ASP.NET MVC application using a DDD approach. However, I do get an error when trying to lazy load an objects related entity. Heres how I've structured my application:
Infrastructure layer:
Contains mapping files, repository implementations and a NHibernate bootstrapper to configure and build a session factory.
Heres a repository example:
public class CustomerRepository : ICustomerRepository
{
public Customer GetCustomerById(int customerId)
{
using (var session = NHibernateBootstrapper.OpenSession())
return session.Get<Customer>(customerId);
}
}
Domain layer:
Has simple POCO classes, repository and service interfaces
Application layer:
Contains Service implementations.
Heres a service example:
public class CustomerService : ICustomerService
{
private ICustomerRepository _repository;
public CustomerService(ICustomerRepository repository)
{
_repository = repository;
}
public Customer GetCustomerById(int customerId)
{
return _repository.GetCustomerById(customerId);
}
}
Presentation layer:
Contains the ASP.NET MVC application. And this is where I discovered my problem.
Using the MVC approach, I have a controller which, using the CustomerService service, gets a customer and displays the customer in a View (strongly typed). This customer has a related entity Contact, and when I try to access it in my View using Model.Contact, where Model is my Customer object, I get an LazyInitializationException.
I know why I get this. It's because the session used to retrieve the Customer in the CustomerRepository is dead by now. My problem is how I can fix this. I would like if I could avoid getting the related Contact entity for the Customer in my repository, because some views only need the Customer data, not the Contact data. If this is possible at all?
So to the question: is it possible to wait querying the database, until the presentation layer needs the related entity Contact?
I think that what I need is something like what this article describes. I just can't figure out how to implement it in infrastructure layer, or where should it be implemented?
Thanks in advance. Any help will be much appreciated!
As for session management it is common to use single session per request. You can see an example of implementation here. It is an open source project that were designed to setup new asp.net applications with the help of Nhibernate wery easy. source code can be founded here.
Hope it helps.
I also recommend Sharp Architecture.
Another approach, as well as suggestion, is to avoid passing entities to views. There're other problems with it except session management - business rules leaking into views, bloated/spagetti code in there, etc. Use ViewModel approach.
Another problem you'll get is storing your entities in Session. Once you try to get your Customer from Session["customer"] you'll get the same exception. There're several solutions to this, for example storing IDs, or adding repository methods to prevent lazy-loading of objects you're going to store in session - read NHibernate's SetFetchMode - which, of course, you can also use to pass entity to views. But as I said you better stick with ViewModel approach. Google for ViewModel, or refer to ASP.NET MVC In Action book, which uses samples of code from http://code.google.com/p/codecampserver/. Also read this, for example.
Are all your properties and methods in your Customer class marked virtual?
How are you opening and closing your session? I use an ActionFilterAttribute called TransactionPerRequest and decorate all my controllers with it.
Check out this for an implementation.