I'm having some confusion deciding where to store my data classes (models) in my MVC projects. My solutions generally follow the following format:
SolutionName
ProjectName.Web (project)
Controllers
Models
Scripts
Views
ProjectName.Core (project)
Services
Interfaces
Models
ProjectName.Repositories (project) - contains repositories (databases, XML storage).
ProjectName.Test (project)- contains unit tests.
My question is- where should the data classes be stored? In the traditional MVC project, the models are obviously stored in the models folder in the web project. But as I try to keep my solution loosely coupled by separating concerns into multiple projects, should the data models be stored in a different project, like my Core project?
View model classes that are designed simply to provide data to MVC views should be in the ProjectName.Web project Models folder according to standard ASP .NET MVC conventions.
That is not a requirement though and you can easily keep them in a separate assembly.
If you are talking about domain models, ORM entities or any type of non-UI classes that contain data; those probably belong in a separate project.
Generally speaking, I would keep everything in your core library that would be necessary if you wanted to re-use the core library in another project. Using this approach, you would isolate your "domain" model (http://en.wikipedia.org/wiki/Domain_model) to just the core layer and only the web-specific functionality would be in your website.
Let's say on the website you want a user to be logged in, but on a winforms app, the authentication would be handled by the user logging into the pc.
You could put that in your website only, and handle authentication completely separately in different applications, without putting it in your domain model.
Then you would keep only domain-specific models in the core library.
You would then create data models that either wrap the core entities, or or their own representations of combined entities. Then you could have the view models that utilize the data in the models to control the output.
Edit: Here is an example setup (though lengthy, I kept it as brief as possible to illustrate the separation).
//--------------- In your domain library:
public class DataRepository : IDataRepository {
public DataRepository() {
} // end constructor
public DataEntity GetData(DataRequest request) {
//get data based on DataRequest
return new DataEntity();
} // end function GetData
} // end class DataRepository
public class DataRequest {
public String RequestingUser {get; set;}
public Dictionary<String, object> Parameters {get;}
} // end class DataRequest
public class DataEntity {
public string Name {get; set;}
public Guid Id {get; set;}
public string SomeData {get; set;}
} // end class DataEntity
//--------------- In your web library:
public class UserRequest {
public string UserName {get; set;}
} // end class UserRequest
public class LandingPageViewModel {
public LandingPageViewModel() {
Data = new DataItemViewModel();
} // end constructor
public void FillData(DataEntity entity) {
Data.Name = entity.Name;
Data.DataValue = entity.SomeValue;
Data.ShowValue = !String.IsNullOrWhiteSpace(UserName);
} // end method FillData
public string UserName {get; set;}
public List<string> Messages {get; set;}
public DataItemViewModel Data {get; set;}
} // end class LandingPageViewModel
public class DataItemViewModel {
public string Name {get; set;}
public string DataValue {get; set;}
public bool ShowValue {get; set;}
} // end class DataItemViewModel
public class MyController : Controller {
private IDataRepository _repository;
public MyController(IDataRepository repository) {
_repository = repository;
} // end constructor
public ActionResult LandingPage(UserRequest user) {
ActionResult result = null;
DataRequest itemRequest = new DataRequest();
itemRequest.RequestingUser = user.UserName;
DataEntity myEntity = null;
myEntity = _repository.GetData(itemRequest);
if(myEntity != null) {
LandingPageViewModel viewModel = new LandingPageViewModel();
viewModel.UserName = user.UserName;
viewModel.FillData(myEntity);
result = View("LandingPage", viewModel);
} else {
result = View("Error");
} // end if/else
return result;
} // end action LandingPage
} // end class MyController
// In a view
<%# Page Title="" Language="VB" MasterPageFile="~/Views/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of LandingPageViewModel)" %>
<div>
<%:Model.Name;%>
<%
if(Model.ShowValue) {
%>
<%:Model.DataValue;%>
<%
} // end if
%>
</div>
Related
We are working on a Mvc application, where we want to use dependency injection using nInject. Currently we are maintaining entities in different class library "ShopEntities" and in our mvc application we are using this entities.
Let's consider a class in ShopEntities.
namespace ShopEntities
{
public class Customers
{
public int custId {get;set;}
public string custName {get;set;}
public string Address {get;set;}
public string ShippingAddress {get;set;}
}
}
Now when we want to use it in our mvc application, we create an instance and set the properties like below,
public ActionResult Index()
{
ShopEntities.Customers cust = new ShopEntities.Customers();
cust.CustName = "Sam";
cust.IAddress = "xyz";
cust.ShippingAddress = "xyz xyx xyz";
}
How to use nInject here to avoid dependency? Further we don't want to create interfaces as this is limited in scope. Thanks in advance.
The way to abstract away the use of the Customer entity from the presentation layer is not to hide the entity itself behind an ICustomer of some sort, nor to let a DI container build it up. Hiding data objects behind an interfaces is typically not useful; interfaces are meant to abstract behavior, not data.
As NightOwl already stated, your Customer entity is runtime data and you should not use a container to build up object graphs containing runtime data.
Instead, you should hide specific business operations behind an abstraction. Such abstraction can be consumed by the presentation layer and implemented by the business layer. For instance:
public interface ICustomerServices
{
void CreateCustomer(string customerName, string homeAddress,
string shippingAddress);
void ChangeShippingAddress(Guid customerId, string shippingAddress);
}
Your controller can depend on this abstraction:
private readonly ICustomerServices customerServices;
public CustomerController(ICustomerServices customerServices) {
this.customerServices = customerServices;
}
public ActionResult Index()
{
this.customerServices.CreateCustomer("Sam", "xyz", "xyz xyz xyz");
}
Now your business layer can create an implementation for this abstraction that uses the entities internally:
public class CustomerServices : ICustomerServices
{
private readonly EntitiesContext context;
public CustomerServices(EntitiesContext context) {
this.context = context;
}
public void CreateCustomer(string customerName, string homeAddress,
string shippingAddress)
{
// NOTE that I renamed 'Customers' to 'Customer', since it holds information
// to only one customer. 'Customers' implies a collection.
Customer cust = new ShopEntities.Customer();
cust.CustName = "Sam";
cust.IAddress = "xyz";
cust.ShippingAddress = "xyz xyx xyz";
this.context.Customers.Add(cust);
this.context.SubmitChanges();
}
public void ChangeShippingAddress(...) { ... }
}
Doing this has the advantage that you can keep your presentation layer thin, but there are still quite some down sides to the shown approach, compared to alternatives. One of such alternatives is using a message based approach with SOLID design, as explained here.
If i understand you question, you should create middle business layer to convert ShopEntities to your own Entities:
namespace MyShopEntities
{
public class MyCustomers
{
public int custId {get;set;}
public string custName {get;set;}
public string Address {get;set;}
public string ShippingAddress {get;set;}
}
}
public ActionResult Index()
{
ShopEntities.Customers cust = new MyShopEntities.MyCustomers();
cust.CustName = "Sam";
cust.IAddress = "xyz";
cust.ShippingAddress = "xyz xyx xyz";
}
class BussinesModel
{
void Insert(ShopEntities.Customer customer)
{
// use ShopEntities.Customer only in wrapper
// if you later switch to another Customer dependency,
// you just change this wrapper
MyShopEntities.MyCustomers cust = new MyShopEntities.MyCustomers();
cust.CustName = customer.CustName;
cust.IAddress = customerIAddress;
cust.ShippingAddress = customer.ShippingAddress;
InsertInternal(cust);
}
void InsertInternal(MyShopEntities.MyCustomer customer)
{
// use MyCustomer for all your bussines logic
}
}
Is it considered a good practice to pass the model class from e.g. the DAL to a threaded service class as 'information model'?
Example:
public class CarModel {
public string Name { get; set; }
public int AmountOfWheels { get; set; }
public Engine EngineDescription { get; set; }
}
public class Car {
public CarModel CarModel { get; set; }
public Car(CarModel model) {
this.CarModel = model;
Thread.Start(BrummBrumm);
}
private void BrummBrumm() {
// start the car
}
}
This example is made under the assumption that CarModel is a entity (e.g. to use with Entity Framework or any other repository/DAL) or a model class to use with UI, WebApi, WCF.. and Car is a class that resides as implementation in e.g. a Windows service.
Edit further code
public class CarManager {
public List<Car> Cars = new List<Car>();
public void Add(CarModel model) {
this.Cars.Add(new Car(model));
}
public void Remove(int id) {
...
}
}
... then what's with the example above? What if I don't just have cars, but also motorcycles? Wouldn't the example above create a lot of boilerplate code?
Best practice is to use DTOs while transfering data from/to services. There are also tools to reduce code required to map DTO's from/to business objects. Personally I use Automapper.
There's a good article just in case you want to read up on DTO's - Pros and Cons of Data Transfer Objects
However if your solution is small and is not supposed to grow and your services are not publicly exposed you are good to go with just your business objects to avoid overdesign.
Hope it helps!
I am new to IoC and Repository Pattern. I was able to do some test project and it works. But, I am not so sure if what I implemented is a good practice. The test project I have created have all the repositories in place as well as a working interface with a dummy data. But what I want is that my project should not be able to know the concrete types of my models because the initial version should be implemented using MSSQL, and the second version would be a mix of MSSQL and NoSQL(for reads and logging). The models might have different properties or structures from MSSQL to NoSQL (or whatever i might use in the future)
So I tried to create an interface for each model:
public interface ISearchResult
{
string Id { get; set; }
string Name { get; set; }
string Description { get; set; }
string Url { get; set; }
}
And here's the repository:
public interface ISearchRepository<T> where T: class, ISearchResult
{
IEnumerable<T> Search<T>(string keyword, IEnumerable<string> regions, IEnumerable<string> industries,IEnumerable<string> countries, IEnumerable<string> cities, int offset);
}
And here's the service:
public interface ISearchService
{
IEnumerable<T> Search<T>(string keyword, IEnumerable<string> regions, IEnumerable<string> industries,IEnumerable<string> countries, IEnumerable<string> cities, int offset);
}
Because I want to have a working GUI even without MSSQL or NoSQL entities, I have created a View Model that inherited the ISearchResult:
public class SearchResultViewModel : ISearchResult
{
[Display(Name="Reference Id")]
public string Id { get; set; }
[Display(Name = "Company")]
public string Name { get; set; }
[Display(Name = "Description")]
public string Description { get; set; }
[Display(Name = "Website")]
public string Url { get; set; }
}
And here's how it looks on my controller:
[SearchQueryFilter]
[GeoTargetFilter]
public ActionResult Query(SearchQueryModel searchQuery)
{
searchQuery.Results = this._searchService.Search<SearchResultViewModel>(searchQuery.Keyword,searchQuery.Region, new List<string>() { searchQuery.Industries }, new List<string>() { searchQuery.Countries}, new List<string>() {searchQuery.City}, searchQuery.Offset)
.ToList<ISearchResult>();
return View(searchQuery);
}
And my view would look like this:
#foreach (SearchResultViewModel result in Model.Results)
{
//code to display
}
My question is: Is it fine to use this approach? I don't want my web application to be dependent on my data entities so that's why I came up of making my view models inherit an interface. And because I was new to IoC and Repository Pattern and only have a test project, I don't know if my solution would be more of a problem in the long run.
Any advise is highly appreciated.
You shouldn't need to implement an interface in your view model in order to create a separation between your web application and your data entities. Your view model should belong to your web application and should itself be independent of your data entity.
So, instead of:
_searchService.Search<SearchResultViewModel>(x);
You should have, in your controller:
var result = _searchService.Search<SomeEntity>(x);
var model = new SearchResultsViewModel
{
Name = result.Name,
Desc = result.Desc,
Url = result.Url
};
return View(model);
The view model belongs to the web application and is responsible for containing the data passed from controller to view (and back) - it should have nothing to do with your service layer (or any other layer of your application).
SomeEntity is a concrete class, in the form of whatever your search service exposes. Your controller will consume this in the same way as any other application would and then compile a view model for passing to and from views. You might even find that SomeEntity is more or less identical to SearchResultsViewModel initially; however, they are still distinct entities as the requirements of the view might change independently of the search service.
I am new to MVC programming. In normal OOP, where I have my class, I would just initiliaze and load data from database. In MVC, we have modules, how do I load up records from it?
Here is my current code for type UserAcount:
[Table("UserAccount")]
public class UserAccount {
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public string userName { get; set; }
public string email { get; set; }
public int companyID { get; set; }
}
Say that I have an user with name "testUser", how do I initialize on this record and get it's information? How do I do this:
UserAccount user = new UserAccount("tesetUser");
How and where shoulud I use this?
user = user.SingleOrDefault(u => u.userName.ToLower() == User.Identity.Name.ToLower());
You need to read up on Entity Framework. This is the default ORM that MVC uses. Simply:
If you don't have a project context, yet, create one:
public class MyProjectContext : DbContext
{
public MyProjectContext()
: base("name=ConnectionStringNameHere")
{
}
}
Add your models to your project context:
public class MyProjectContext : DbContext
{
...
public DbSet<SomeModel> SomeModels { get; set; }
public DbSet<SomeOtherModel> SomeOtherModels { get; set; }
# etc.
}
Update your database using Package Manager Console (TOOLS > Library Package Manager > Package Manager Console):
> update-database
(hit ENTER after typing that)
Now, to use your context in your controllers:
public class MyAwesomeController : Controller
{
private MyProjectContext db = new MyProjectContext();
public ActionResult Index()
{
var someModels = db.SomeModels;
return View(someModels);
}
public ActionResult GetSomeModel(int id)
{
var someModel = db.SomeModels.Find(id);
return View(someModel);
}
# other actions
}
In the simplest case, you should do this logic in your controller, which will pass the data to the view. However, MVC is meant for UI separation of concerns, so theoretically you should be doing this in your domain layer, which is called from your controller.
Here is a decent article from Jeff Atwood, however I disagree that the controller is the brains of the application. It is more of the brains of the UI...but that depends on how complex your code is. Dont create a domain layer if it is stupidly simple
In the MVC model, Controllers are responsible for processing HTTP requests.
Typically you would load your entity (e.g. UserAccount) in a controller action.
If you want to edit / update an entity, typically you would map the relevant fields to a model that reflects the UserAccount. A separate model is suggested because the needs of the UI are often somewhat different than the needs of the entity model. Having separate classes for each concern avoids polluting the entity model to satisfy the needs of the view.
Introduction
I'm using ASP.Net MVC3. My Controllers talk to a service layer, and the service layer talks to a Data Acces layer which uses Entity Framework.
I get a specific entity using Entity Framework. This entity is converted into a DTO. Then I deliver this DTO to a MVC controller. Something like this:
pseudo code:
// This is inside my Service Layer
var entity = DataAccess.GetById(id);
var dto = createDtoWithValuesFrom(entity);
return dto; // Return dto to MVC controller
In this DTO I would like to use a dependency, to for example a Calculator. Let's say my DTO looks like this:
public class Customer
{
private ICalculator Calculator;
public class Customer(ICalculator calculator)
{
Calculator = calculator;
}
public string Name { get; set; }
public decimal Discount
{
get
{
return Calculator.Discount();
}
}
}
Problem
How do I instanciate my DTO, and let Autofac inject a calculator?
I can think of a way to do this:
var calculator = DependencyResolver.Current.GetService<ICalculator>;
var dto = new DTO(calculator );
But I don't know if this is the best way to do it, since it smells of ServiceLocator, and I've read that it's not prefered to use that.
DTOs normally have some properties and do not contain any logic.
You should consider a design where your MVC-Controller does something like this:
Get the customer from the service/dataaccess
Calculate the discount by invoking the ICalculator which could be passed to the Controller using constructor injection (or call an extra service which does the calculation)
Create a new model class which contains the customer and the calculated discount and pass this model to the view.
public class Model
{
public Customer Customer { get; set; }
public double Discount { get; set; }
}
public class SomeController : Controller
{
private readonly DataAccess dataAccess;
private readonly ICalculator calculator;
public SomeController(DataAccess dataAccess, ICalculator calculator)
{
this.dataAccess = dataAccess;
this.calculator = calculator;
}
public ActionResult Index(int id)
{
var model = new Model();
model.Customer = this.dataAccess.Get(id);
model.Discount = this.calculator.Calculate(customer);
return View(model);
}
}
First of all: A DTO is not a View Model.
A DTO (Data Transfer Object) is a dummy class (it's really not a first class (OOP) citizen). It's purpose is only to flatten hierarchies and transport information between different layers/tiers.
A View Model is used to adapt a model (as in MVC) so that it fits a view better. It's purpose is simply to remove logic from the view and hide details regarding the Model that should not be used/available in the View.
Neither a DTO or a ViewModel should be used for anything else unless you want to violate Single Responsibility Principle.
What you are asking for should be done in your Controller (since it's the glue between the Model and the View). Hence add the ICalculator to the constructor of your controller.