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?
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!
This is my first attempt, after reading a lot about DDD, TDD and Repository / UnitOfWork paterns, to make my own application.
I'm using Entity Framework, MVC 4 on .NET 4.0 (the server that will be running this application is a Windows 2003)
This is the basic simplified pattern logic (The original one uses a IRepository, IUnitOfWork, GenericRepository and extends the EF POCOs with a IEntity interface to give access to the common ID field. But this simplified example will be enough to ask my question)
View -> ViewModel -> Controller <- UnitOfWork <- Repository <- EntityFramework <- Database
View
Model.Employee.GetSeniority()
EmployeeDetailsViewModel
Employee e { get; set; }
Employee
DateTime dateHired { get; set; }
TimeSpan GetSeniority()
{
return DateTime.Today - dateHired;
}
Controller EmployeeDetails()
using(var unitOfWork = new UnitOfWork) {
return View(EmployeeDetailsViewModel model = new EmployeeDetailsViewModel {
e = unitOfWork.GetEmployeRepository().Find(o=>o.id == id)
});
}
UnitOfWork GetEmployeRepository()
return (_employeeRepository ?? _employeeRepository = new EmployeeRepository(this.dbContext));
Repository Find()
dbContext.Configuration.EnableProxyCreation = false;
Employee e = dbContext.Employees.Where(expression);
dbContext.Configuration.EnableProxyCreation = true;
return e;
Everything actually works properly. The problem is that I feel like something is terribly wrong here, and I'm not sure at which layer it should be fixed.
After getting suggested, by a lot of people (Hi Darin), to always pass ViewModels to views and no models, I started doing this. However, what I'm doing (I think) isn't much better. I'm simply encapsulating my model in a viewmodel. At first, it didn't sound that bad since my Find() method would turn proxy off before getting an object, which would result in a persistance-ignorant POCO. However, now that I want to add some logic in the POCOs, I feel like there is something wrong.
I think the problem resides in where my Business logic is and the fact that my Employee POCO should be mapped to a DTO object. However, where should I transfer the Employee POCO to a EmployeeDTO? Should that be the task of the Repository, the Controller or something else? I'm also unsure of where I should put my business logic (as simple as GetSeniority() displayed in the example). Should that be added to the EF POCO through partial classes or should that be in the DTOs? Or is there another missing step in the Employee -> EmployeeDTO transfer?
This is a great question. It looks like you are trying to find clean separation which is fantastic. I would break the problem up. You have Data Access and you have UI display and in between you have your business logic. If you want to use a Domain model approach here is how I would structure it.
Never expose EntityFramework Entity classes outside of Repository. You can choose to return Dto's (POCO') or Domain objects from your repository. If you want Dto's for more separation, that is fine you will just need another layer such as a service layer to convert the Dto's into Domain Objects.
Put your business logic in your Domain Objects. So Domain.Employee.GetSenority() would be on your domain object.
Any logic that does not fit in your Domain Objects can reside in your UnitOfWork or Service Layer.
Convert Domain objects to ViewModel in controller. At this point map Employee.GetSenority() to MyViewModel.Senority property. Basically your ViewModel is a Dto and only contains view specific logic which typically is not much.
Where do you call the repository. You could use the UnitOfWork pattern as you have it or simply create a Service Layer class. The key here is that these should be useable to other application types. For instance if you were to write a desktop or Windows 8 Style App, you would likely want to reuse either of these along with your Domain Entities.
I'm sure you are having fun with this. Good luck.
I'm developing an application using asp.net mvc, NHibernate and DDD. I have a service layer that are used by controllers of my application. Everything are using Unity to inject dependencies (ISessionFactory in repositories, repositories in services and services in controllers) and works fine.
But, it's very common I need a method in service to get only object in my repository, like this (in service class):
public class ProductService {
private readonly IUnitOfWork _uow;
private readonly IProductRepository _productRepository;
public ProductService(IUnitOfWork unitOfWork, IProductRepository productRepository) {
this._uow = unitOfWork;
this._productRepository = productRepository;
}
/* this method should be exists in DDD ??? It's very common */
public Domain.Product Get(long key) {
return _productRepository.Get(key);
}
/* other common method... is correct by DDD ? */
public bool Delete(long key) {
usign (var tx = _uow.BeginTransaction()) {
try
{
_productRepository.Delete(key);
tx.Commit();
return true;
} catch {
tx.RollBack();
return false;
}
}
}
/* ... others methods ... */
}
This code is correct by DDD ? For each Service class I have a Repository, and for each service class need I do a method "Get" for an entity ?
Thanks guys
Cheers
Your ProductService doesn't look like it followed Domain-Driven Design principles. If I understand it correctly, it is a part of Application layer between Presentation and Domain. If so, the methods on ProductService should have business meaning with regard to products.
Let's talk about deleting products. Is it as simple as executing delete on the database (NHibernate, or whatever?) I think it is not. What about orders which reference the to-be-deleted product? And so on and so forth. Btw, Udi Dahan wrote a great article on deleting entities.
Bottom line is, if your application is so simple that services do really replicate your repositories and contain only CRUD operations, you probably shouldn't do DDD, throw away your repositories and let services operate on entities (which would be simple data containers in that case).
On the other hand, if there is a complicated behavior (like the one with handling 'deleted' products), there is a point in going DDD path and I strongly advocate doing so.
PS. Despite which approach (DDD or not) you will eventually take I would encourage you to use some Aspect Oriented Programming to handle transaction and exception related stuff. You would end up with way to many methods such as DeleteProduct with same TX and exception handling code.
That looks correct from my perspective. I really didn't like repeating service and repository method names over and over in my asp.net MVC project, so I went for a generic repository approach/pattern. This means that I really only need one or two Get() methods in my repository to retrieve my objects. This is possible for me because I am using Entity Framework and I just have my repository's get() method return a IQueryable. Then I can just do the following:
Product product = from p in _productRepository.Get() where p.Id == Id select p;
You can probably replicate this in NHibernate with linq -> NHibernate.
Edit: This works for DDD because this still allows me to interchange my DAL/repositories as long as the data library I am using (Nhibernate, EF, etc..) supports IQueryable.
I am not sure how to do a generic repository without IQueryable, but you might be able to use delegates/lambda functions to incorporate it.
Edit2: And just in case I didn't answer your question correctly, if you are asking if you are supposed to call your repository's Get() method from the service then yes, that is the correct DDD design as well. The reason is that the service layer is supposed to handle all your business logic, so it decides exactly how and what data to retrieve (for example, do you want it in alphabetical order, unordered, etc...). It also means that it can perform validation after loading if needed or validation before deleting and/or saving.
This means that the service layer doesn't care exactly how that data is stored and retrieved, it only decides what data is stored and retrieved. It then calls on the repository to handle the request correctly and retrieve/store the data in the way the service layer tells it to. Thus you have correct separation of concerns.
I need to make a web application and I want to use MVC. However, my Model can't be one of the standard Models -- the data is not stored in a database but instead in an external application accessible only via a API. Since this is the first MVC application I've implemented I'm relying on examples to understand how to go about it. I can't find any examples of a non-DB based Model. An example of a custom Model would be fine too. Can anyone point me to such a beast? Maybe MVC is just to new and none exist.
It seems like I might be able to get away with the DataSet Model, however I've not seen any examples of how to use this object. I expect an example of DataSet could help me also. (Maybe it is the same thing?)
Please note: I've seen countless examples of custom bindings. This is NOT what I want. I need an example of a custom Model which is not tied to a specific database/table.
UPDATE
I found a good example from MS located here:
http://msdn.microsoft.com/en-us/library/dd405231.aspx
While this is the "answer" to my question, I don't really like it because it ties me to MS's view of the world. #Aaronaught, #jeroenh, and #tvanfosson give much better answers from a meta perspective of moving my understanding (and yours?) forward with respect to using MVC.
I'm giving the check to #Aaronaught because he actually has example code (which I asked for.) Thanks all and feel free to add even better answers if you have one.
In most cases it shouldn't matter what the backing source is for the actual application data; the model should be exactly the same. In fact, one of the main reasons for using something like a repository is so that you can easily change the underlying storage.
For example, I have an MVC app that uses a lot of web services - rarely does it have access to a local database, except for simple things like authentication and user profiles. A typical model class might look like this:
[DataContract(Namespace = "http://services.acme.com")]
public class Customer
{
[DataMember(Name = "CustomerID")]
public Guid ID { get; set; }
[DataMember(Name = "CustomerName")]
public string Name { get; set; }
}
Then I will have a repository interface that looks like this:
public interface ICustomerRepository
{
Customer GetCustomerByID(Guid id);
IList<Customer> List();
}
The "API" is all encapsulated within the concrete repository:
public class AcmeWSCustomerRepository : ICustomerRepository, IDisposable
{
private Acme.Services.CrmServiceSoapClient client;
public AcmeWSCustomerRepository()
: this(new Acme.Services.CrmServiceSoapClient())
public AcmeWSCustomerRepository(Acme.Services.CrmServiceSoapClient client)
{
if (client == null)
throw new ArgumentNullException("client");
this.client = client;
}
public void Dispose()
{
client.SafeClose(); // Extension method to close WCF proxies
}
public Customer GetCustomerByID(Guid id)
{
return client.GetCustomerByID(id);
}
public IList<Customer> List()
{
return client.GetAllCustomers();
}
}
Then I'll also probably have a local testing repository with just a few customers that reads from something like an XML file:
public class LocalCustomerRepository : ICustomerRepository, IDisposable
{
private XDocument doc;
public LocalCustomerRepository(string fileName)
{
doc = XDocument.Load(fileName);
}
public void Dispose()
{
}
public Customer GetCustomerByID(Guid id)
{
return
(from c in doc.Descendants("Customer")
select new Customer(c.Element("ID").Value, c.Element("Name").Value))
.FirstOrDefault();
}
// etc.
}
The point I'm trying to make here is, well, this isn't tied to any particular database. One possible source in this case is a WCF service; another is a file on disk. Neither one necessarily has a compatible "model". In this case I've assumed that the WCF service exposes a model that I can map to directly with DataContract attributes, but the Linq-to-XML version is pure API; there is no model, it's all custom mapping.
A really good domain model should actually be completely independent of the true data source. I'm always a bit skeptical when people tell me that a Linq to SQL or Entity Framework model is good enough to use throughout the entire application/site. Very often these simply don't match the "human" model and simply creating a bunch of ViewModel classes isn't necessarily the answer.
In a sense, it's actually better if you're not handed an existing relational model. It forces you to really think about the best domain model for your application, and not necessarily the easiest one to map to some database. So if you don't already have a model from a database - build one! Just use POCO classes and decorate with attributes if necessary, then create repositories or services that map this domain model to/from the API.
I think what you are looking for is really a non-DB service layer. Models, typically, are relatively simple containers for data, though they may also contain business logic. It really sounds like what you have is a service to communicate with and need a layer to mediate between the service and your application, producing the appropriate model classes from the data returned by the service.
This tutorial may be helpful, but you'd need to replace the repository with your class that interacts with the service (instead of the DB).
There is no fixed prescription of what a "Model" in MVC should be, just that it should contain the data that needs to be shown on screen, and probably also manipulated.
In a well-designed MVC application, data access is abstracted away somehow anyway, typically using some form of the Repository pattern: you define an abstraction layer (say, an IRepository interface) that defines the contract needed to get and persist data. The actual implementation will usually call a database, but in your case should call your 'service API'.
Here is an example of an MVC application that calls out to a WCF service.