Generally, you want your Controllers to do only a few things:
- Handle the incoming request
- Delegate the processing to some business object
- Pass the result of the business processing to the appropriate view for rendering
There shouldn't be any data access or complex business logic in the controller.
[In the simplest of apps, you can probably get away with basic data CRUD actions in your controller, but once you start adding in more than simple Get and Update calls, you are going to want to break out your processing into a separate class.]
Your controllers will usually depend on a 'Service' to do the actual processing work. In your service class you may work directly with your data source (in your case, the DbContext), but once again, if you find yourself writing a lot of business rules in addition to the data access, you will probably want to separate your business logic from your data access.
At that point, you will probably have a class that does nothing but the data access. Sometimes this is called a Repository, but it doesn't really matter what the name is. The point is that all of the code for getting data into and out of the database is in one place.
For every MVC project I've worked on, I've always ended up with a structure like:
Controller
public class BookController : Controller
{
ILibraryService _libraryService;
public BookController(ILibraryService libraryService)
{
_libraryService = libraryService;
}
public ActionResult Details(String isbn)
{
Book currentBook = _libraryService.RetrieveBookByISBN(isbn);
return View(ConvertToBookViewModel(currentBook));
}
public ActionResult DoSomethingComplexWithBook(ComplexBookActionRequest request)
{
var responseViewModel = _libraryService.ProcessTheComplexStuff(request);
return View(responseViewModel);
}
}
Business Service
public class LibraryService : ILibraryService
{
IBookRepository _bookRepository;
ICustomerRepository _customerRepository;
public LibraryService(IBookRepository bookRepository,
ICustomerRepository _customerRepository )
{
_bookRepository = bookRepository;
_customerRepository = customerRepository;
}
public Book RetrieveBookByISBN(string isbn)
{
return _bookRepository.GetBookByISBN(isbn);
}
public ComplexBookActionResult ProcessTheComplexStuff(ComplexBookActionRequest request)
{
// Possibly some business logic here
Book book = _bookRepository.GetBookByISBN(request.Isbn);
Customer customer = _customerRepository.GetCustomerById(request.CustomerId);
// Probably more business logic here
_libraryRepository.Save(book);
return complexBusinessActionResult;
}
}
Repository
public class BookRepository : IBookRepository
{
LibraryDBContext _db = new LibraryDBContext();
public Book GetBookByIsbn(string isbn)
{
return _db.Books.Single(b => b.ISBN == isbn);
}
// And the rest of the data access
}
Do you have to create the view from the POST
? A nicer pattern might be to use Post/Redirect/Get; this way the data is POSTed
to the action which simply returns a 302
redirect to the GET
action with the appropriate parameters in the query string. The responsibility for rendering then remains with the GET
whilst altering state on the server is kept within the 'POST'.
The additional benefit of doing this is that you solve the problem of user's making duplicate
requests when refreshing the page.
In terms of Best Practice when working with the web, it might be worthwhile learning more about REST and trying to apply RESTful
principles to your MVC application.
Best Answer
Stop. Disconnect from everything server-side. You are dealing with client side functionality, and the solution to your problem will not have anything to do with C#, ASP.NET MVC, or Razor. Instead, JavaScript is what you need. It sounds like the basic user interaction is:
The solution will look something like this:
change
event on one or more form fieldsThis might be a good candidate for a question on StackOverflow, but you'll need to give specifics about your problem.