13

I am learning asp.net mvc and went through a great tutorial that demonstrated it. The tutorial also used Entity Framework.

We have our own data access class which I have to use. I am a little bit confused as to what I need to do to bridge the gap between our class and MVC framework. For example, in the tutorial, inside of MovieController.cs file, there is a Edit method, that looks like this:

[HttpPost]
        public ActionResult Edit(Movie movie)
        {
            if (ModelState.IsValid)
            {
                db.Entry(movie).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(movie);
        }

If I don't use the Entity framework, what would it look like? Will I still need to use ModelState.IsValid and save the state like it's done

db.Entry(movie).State = EntityState.Modified;

Please advise. A clearly written example of using asp.net mvc without the use of Entity framework would be great.

What I need to know is what role does state play here and whether it is mandatory to use or is it just a part of how the Entity framework operates.

I would re-write this as:

[HttpPost]
public ActionResult Edit(Movie movie)
{
    myDBObject.SaveChanges();
    return RedirectToAction("Index");

}

Where myDBObject is my custom database access object.

sarsnake
  • 26,667
  • 58
  • 180
  • 286

4 Answers4

20

The examples you see out there where controllers use directly some data access framework such as Entity Framework are bad examples. The whole internet is polluted with such stuff. I can hardly look at it without having my eyes hurt. I consider those as bad practices. Data access should be separated and abstracted in a repository. So for example:

public interface IMoviesRepository
{
    Movie Get(int id);
    void Save(Movie movie);
}

then you could have some implementation of this interface using plain ADO.NET, EF, NHibernate, a remote web service call, some custom ORM or really whatever:

public class MyCustomFrameworkMoviesRepository: IMoviesRepository
{
    ...
}

and the controller will take this repository interface as constructor argument:

public class MoviesController: Controller
{
    private readonly IMoviesRepository _repository;
    public MoviesController(IMoviesRepository repository)
    {
        _repository = repository;
    }

    public ActionResult Index(int id)
    {
        var movie = _repository.Get(id);
        return View(movie);
    }

    [HttpPost]
    public ActionResult Index(Movie movie)
    {
        if (!ModelState.IsValid)
        {
            return View(movie);
        }

        _repository.Save(movie);
        return RedirectToAction("Success");
    }
}

and the last part is to configure your dependency injection framework to pass the correct implementation of the repository into the controller. Now as you can see the way the data is fetched is completely decoupled from the controller logic. It is the way it should be. Always try to avoid the strong coupling between the different layers of your application.

And to answer your question about the State property : this is something completely specific to EF, seeing something like this in a controller is a really pity.

And to bring this even further and improve it you would introduce view models. View models are classes which are specifically designed to meet the requirements of a given view. So for example Movie is a domain model. Domain models should never be directly passed to views. Controller actions should never take domain models as action arguments. You should define view models which will contain only what is required by the given view and then perform the mapping between the view models and the domain models. Frameworks such as AutoMapper make this very simple.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 2
    While I agree they are bad practices, there are times when not building an abstraction UnitOfWork/ Repository pattern may be practical. A professional developer will follow patterns that allow security, scalability, and testability... the need for the company IT guy or hobbyist may not justify that. – Jeremy Holovacs Oct 12 '11 at 20:58
  • ok, so one little question. I am not using DI framework.....so where do I use the constructor for my controller? – sarsnake Oct 14 '11 at 20:37
  • @sarsnake, you have 2 possibilities, either you use [poor man's dependency injection](http://lostechies.com/jimmybogard/2009/07/03/how-not-to-do-dependency-injection-in-nerddinner/) or you could also write a custom controller factory and manually wire up dependencies. – Darin Dimitrov Oct 14 '11 at 20:42
  • Could you please answer http://stackoverflow.com/questions/9328197/asp-net-mvc-3-automatically-generating-view-while-adding-controller-without-en ? – LCJ Feb 17 '12 at 12:30
  • When you abstract away an ORM you're probably loosing the strengths of specific ORMs in favor of a possible (and very unlikely) ORM switch in the future. It is next to impossible to create another abstraction layer on top of an ORM (a HUGE abstraction layer on itself) and still be able to benefit fully from it. In fact you'll probably level everything to the bare minimum, loosing lazy loading, pre-fetch and many other important features on the way to implement your abstraction). But don't take my word for it, read http://ayende.com/blog/3955/repository-is-the-new-singleton . – Loudenvier Aug 13 '12 at 04:59
  • Let me just add that I don't advocate using domain model objects in the view/controller, I'm all for the view model approach. I just really don't see much value in abstracting the data access logic into repositories when we already have incredible strong "repositories" in modern, well-thought, mature ORM frameworks like nHibernate's session, etc. – Loudenvier Aug 13 '12 at 05:04
  • So then where does MyCustomFrameworkMoviesRepository implementation come into play? Not seeing this. – Mickey Sep 11 '15 at 00:47
2

hmm.

MVC and entity framework really have nothing to do with each other; they just work well together.

the if (ModelState.IsValid) validates your view model. If you are not using view objects with validators, it's a little pointless; if you are, then it's quite valuable.

inside the if (ModelState.IsValid) brackets, you would take the post data from your web page (usually a view model) and apply it to the object that will persist it to the database. EF is often used because once it's set up, it's fairly easy to maintain, and a lot less code to write.

            db.Entry(movie).State = EntityState.Modified;
            db.SaveChanges();

are both EF-related. These would need to be replaced by your repository class methods and objects.

            return RedirectToAction("Index");

is MVC. Upon successful persistence to your data store, return the control to the index page.

        return View(movie);

is used to redirect back to the original view, because something failed validation.

Jeremy Holovacs
  • 22,480
  • 33
  • 117
  • 254
1

You would still check ModelState.IsValid, but otherwise your code would look like what you have.

This assumes that your model has DataAnnotations attributes on it, though, which is what ModelState.IsValid is using to check. Those attributes can be used on any C# class' properties - not just Entity Framework.

You might end up creating specific view models for this purpose.

Andrew Barber
  • 39,603
  • 20
  • 94
  • 123
  • And assuming that I write a custom class that feeds the Model from the database. When googling, I found this: "You can just replace entities with ADO.NET code and return a list object/IEnumerable object from database layer. This can then be passed onto View as a Model." – sarsnake Oct 12 '11 at 20:26
0

You need to make some connection between the Movie object (passed in on the http POST) and your database methods (myDBObject).

Maybe you want to say myDBObject.SaveChanges(movie) and assuming your db code knows how to handle the object Movie then you'll be fine.

K. Bob
  • 2,668
  • 1
  • 18
  • 16