Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I refactor my database access code outside my MVC project but keep my viewmodels inside?

I have an asp.net-mvc website with the following folders:

  • Controllers
  • Scripts
  • Views
  • ViewModels
  • Models
  • DomainModel

I now want to access a lot of this business logic and database access code and data in another .net app (a windows console app so not web at all) so i am refactoring to remove as much stuff as possible outside of the MVC project and into other projects in the solution so that code could be shared with this other solutions.

I have 2 main issues;

  1. My main issue is that I am struggling to find a place to put the code that generates the ViewModel because a lot of this code I would like to reuse in my console app as the console app sends email which requires the same data that is in the view.

  2. Another main issue is that i am struggling to see how i can move my database access code out of the MVC project while still having the ViewModels inside when many of my functions that instantiate my viewmodels start with a bunch of database access code.

Here is a bit of the detail and my process so far:

Step 1 - Move DomainModel into another project - success

So moving the DomainModel project was simple (as that was a lot of raw objects with some business logic on top - nothing web about it).

Step 2 - Thin out controllers - success

I have thinned out as much of my controllers as possible and moved any business logic or complicated data access logic into the Models folder. When i tried to move the models folder outside the MVC project a few things broke:

Step 3 - Attempt to move Models folder outside MVC Project - struggle

In thinning out the controllers, I have a number of different controller actions that go to a model class and return my ViewModel that i pass back into the view. Something like this (in my controller class):

 public ActionResult ApplicationDetail(int id)
 {
      AppDetailViewModel applicationViewModel = Model.GenerateAppDetailViewModel(id);
      return View(applicationViewModel);
 }

So files in my Model folder are dependency on the ViewModel classes. I do want to centralize the GenerateAppDetailViewModel() function as that is used in multiple different controllers. Also, in my console app (which sends out email, i often want to get all the data that happens to be on some view so my code "wants" to leverage the viewmodel as well .. if i move it out of the MVC project then I can reuse but i think have the dependency issue (clearly i don't need SelectListItem in my console app but in other cases where they are just container objects of different data needed to generate a view I do want to reuse)

or another thing that broke was the dependency on:

System.Web.Mvc

because I have a lot of code that:

  1. queries a table in a database
  2. Converts that into a collection of objects (i am using nhibernate)
  3. Convert that into either some DTO object (which is sitting in ViewModels folder) or a List of SelectListItem objects (to be used to populate dropdowns in the view) which is part of System.web.mvc.

I wanted to look for suggestions on the best way to break out this dependency so i can move as much code out of the MVC project as possible for reuse.

The issue is that if i try to suck my ViewModel code into the Model folder and into another project then again i get stuck because the ViewModel classes have a lot of dependency on

System.Web.Mvc

due to things like SelectListItem.

Should i have 2 view models folders (one in the MVC project that has specific system.web.mvc references and another one that sits in a different project?). It seems like the dependency on SelectListItem is what keeps causing the contention

In most examples that i have seen ViewModels do have a dependency on System.Web.Mvc such as this tutorial

I have seen these questions:

  • Asp.Net MVC SelectList Refactoring Question?
  • Where should selectlist logic sit in ASP.NET MVC, view, model or controller?

which are sort of related but not sure they answer my specific overall refactoring question stated.

like image 474
leora Avatar asked Jul 03 '13 17:07

leora


People also ask

How can use foreign key in ASP NET MVC?

To create Foreign Key, you need to use ForeignKey attribute with specifying the name of the property as parameter. You also need to specify the name of the table which is going to participate in relationship. I mean to say, define the foreign key table.

How I can save data in SQL using MVC?

Right-click on Model then select New Item > Data template (ADO.NET Entity Data Model). Name your model “MyModel” then select Generate From Database then enter your configuration then select your table. I have created tblStud as in the following: USE [comm]

Should services return view models?

Generally, no. View models are intended to provide information to and from views and should be specific to the application, as opposed to the general domain.


1 Answers

View models are specific to the particular application. I guess that the view models would differ between your web application and your console application. So have each application define its own view models and the corresponding mapping between the domain models and the view models. Don't have your domain models posses methods that convert them to view models because this way you are completely tying your domain layer to the UI layer which is the worst thing to happen. Use a mapping layer (which will be specific to each application type). AutoMapper is a great example of a mapping layer that you could have.

Don't even try to reuse ASP.NET MVC view models in a console application. As you have already found out they will contain references to System.Web.Mvc because for example a dropDownList in ASP.NET MVC is represented with the IEnumerable<SelectListItem> class whereas in a Console Application, god knows, maybe an IEnumerable<SomeItemViewModel>.

Conclusion: View models and mapping back and forth between the domain and view models belong to the UI layer (a.k.a ASP.NET MVC, Console, WPF, ...).

like image 154
Darin Dimitrov Avatar answered Oct 18 '22 11:10

Darin Dimitrov