ASP.NET MVC - Validation logic - where to place? - c#

I'm trying to determine where to place my "Validation Models".
My structure is at the moment:
Web (have reference to Business and Objects)
Controllers
Views
CSS
Scripts
Business (have reference to Data and Objects)
Services
Data (have reference to Objects)
Repositories and EF Context(Code First)
Objects
POCOs (for EF)
Now is my question where to place validation things like a LogIn Model? Should the model be placed in my Web layer or Objects layer? - or should I even store validation models like that?
Thanks in advance!

Models should be placed in your business layer. View models should be placed in your web layer because they are tied to a view. You should have a mapping between your models and view models (to facilitate this task you may use a tool like AutoMapper). Views receive view models from controllers. Validation is performed on those view models.
So:
Web
Controllers
Views
Models (here you may place your view models)
CSS
Scripts

Anything that needs to be validated should go in your Business layer. Validation is a business concern that shouldn't be scattered across layers and shouldn't be tied to a specific application type (web, windows, service, etc).
If you expose your domain model to the application then you can also decorate your entities with validation attributes, but note that if your domain model changes then your application breaks.
Let's say you have an AccountService class in the Business layer, which has a Login method. Login accepts a LoginInput class and returns a LoginResult class:
public class LoginInput {
[Required]
public string Username { get; set; }
[Required]
public string Password { get; set; }
}
public class LoginResult {
public bool Success { get; internal set; }
public string Error { get; internal set; }
}
Both of these classes can be used as ViewModels, so you don't need to create any ViewModel in the Web layer, and you certainly shouldn't put validation logic in them.

Related

How to implement n-layer architecture in MVC?

I know this question has been asked before. I am only asking so that I can get a better explanation. In my webforms applications, this is how I implemented my projects. The solution had two projects. The first project contains Data Access and Business Logic. The first project is referenced in the second project. The aspx.cs files call the business logic class and the business logic class calls the data access class.
I am trying to follow the same approach in my MVC applicaiton. How would I implement that? Controller calls Model which in turn calls Business logic? This approach would add overhead right?
In reference to the direction the comments are taking this thread (this doesn't fit neatly into a comment):
The models folder that is created with a new MVC project is for View Models - they are classes to support views. These are not your business models or data models.
For instance, in a ViewModel that supports a view, you might have a enum property that renders to a dropdown:
public enum CustomerTypes
{
INDIVIDUAL = 0,
COMPANY
}
public class CustomerViewModel
{
public CustomerTypes Type { get; set; }
public string[] CustomerTypesSelectList { get; set; }
}
public class CustomerController : Controller
{
public ActionResult Edit()
{
var model = new CustomerViewModel();
model.CustomerTypesSelectList =
Enum.GetNames(typeof(CustomerTypesSelectList));
return View(model);
}
}
And with this you have some javascript in your view to populate a fancy drop down list with the items in CustomerTypesSelectList.
The UI-specific string[] property is a common construct of a ViewModel that gets stripped away when it gets converted to the business model or data model. The Controller would control the conversion (a.k.a. mapping), but probably rely on another class to implement the mapping that ties together the ViewModel and the business model.
To sum up, in an n-layer architecture:
The MVC Controller is not your business logic. Your business logic resides inside of various services and components that are called by the controller.
The Models folder contains ViewModels - classes that are meant to support the operation of the UI only.
The Controller calls a mapper to translate between ViewModels and business models when calling into the business layer.
Have your architecture with following things
Data access project - add ORM/ADO.net with repository and unit of work pattern. Repositories can be generated using T4 template from ORM
ViewModel project - have a separate project for Viewmodels (containing properties to be used by view).
Business layer - have classes which contains functions that access repositories from data access layer, join them if needed using LINQ and populate in Viewmodel and return view model object or view model collection to controller.
WEB Project -
Controller - access business layer functions using dependency injection and return view model to view
View - Access view mode returned by controller

Entities VS Domain Models VS View Models

There are hundreds of similar questions on this topic. But I am still confused and I would like to get experts advise on this.
We are developing an application using ASP.NET MVC 4 and EF5 and ours is DB first approach.
We have Data layer in a separate project which is a class library and holds all the Entities defined in it. And then Business Layer defined with all the repositories and domain models(is that right term to be used). And then comes presentation layer.
At present we have not defined any view models, we are using the same domain models from BL as view models. In this approach one mapping can be enough.
ENTITY <=> DOMAIN MODEL
But for me it's not looking like a good design. I prefer to have view models defined in my presentation layer and use domain models to communicate between presentation layer and business layer. And at BL, convert domain objects to data entities and communicate with DAL. Using this approach I have to use mapping twice.
View Model <=> DOMAIN MODEL <=> ENTITY
Is my domain model really necessary? Can't I use my entity to communicate with Presentation layer. Are there any impacts if I am referencing Entities in my presentation layer? If there are what kind of impacts?
I think you're just having issues with defining what each layer is and what role it is playing in your solution.
Data Tier
Your data tier is simply your database / SharePoint list / .csv file / excel sheet... you get the idea, it's simply where your data is stored, and it can be in any format. So remember that the data tier is nothing more than just data.
// ----------------------------
// Data tier
// - MySQL
// - MS SQL
// - SharePoint list
// - Excel
// - CSV
// - NoSQL
// ----------------------------
Data Access Layer
This layer abstracts away your data source, and provides an API in which the rest of your application can interact with the data source.
Consider that our data source is an MS SQL Database and that we're using Entity Framework to access the data. What you'll be attempting to abstract away, is the database and Entity Framework, and have a Data Repository for each Entity.
Example...
We have a Customers table in a MS SQL Database. Each customer in the customers table is an Entity , and is represented as such in your C# code.
By using the repository pattern, we can abstract away the implementation of the data access code, so that in future, if our data source changes, the rest of our application wont be affected. Next we would need a CustomersRepository in our Data Access Layer, which would include methods such as Add, Remove and FindById. To abstract away any data access code. The example below is how you would achieve this.
public interface IEntity
{
int Id { get; set; }
}
public class Customer : IEntity
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime RegistrationDate { get; set; }
}
public interface IRepository<TEntity> where TEntity : class, IEntity
{
TEntity FindById(int id);
void Add(TEntity entity);
void Remove(TEntity entity);
}
public class CustomerRepository : IRepository<Customer>
{
public Customer FindById(int id)
{
// find the customer using their id
return null;
}
public void Add(Customer customer)
{
// add the specified customer to the db
}
public void Remove(Customer customer)
{
// remove the specified customer from the db
}
}
The data access layer belongs in between the data layer and business logic.
// ----------------------------
// Business logic
// ----------------------------
// ----------------------------
// Data access layer
// - Repository
// - Domain models / Business models / Entities
// ----------------------------
// ----------------------------
// Data tier
// - MySQL
// - MS SQL
// - SharePoint list
// - Excel
// - CSV
// - NoSQL
// ----------------------------
Business layer
The business layer is built on top of the data access layer, and does not deal with any data access concerns, but strictly business logic. If one of the business requirements was to prevent orders being made from outside of the UK, then the business logic layer would handle this.
Presentation tier
The presentation tier simply presents your data, but if you're not careful about what data you present, and what data you allow to be posted, you'll set your self up for a lot of headaches down the line, which is why it's important to use view models, as view models are a presentation tier concern, the presentation tier doesn't need to know anything about your domain models, it only needs to know about view models.
So what are View Models... They're simply data models which are tailored for each view, for example a registration form would include a RegistrationViewModel, exposing these typical properties.
public class RegistrationViewModel
{
public string Email { get; set; }
public string Password { get; set; }
public string ConfirmPassword { get; set; }
}
The presentation tier also handles input validation, so for instance validating whether an email address typed has the correct format, or that the passwords entered match is a presentation tier concern, not a business concern, and can be handled by using Data Annotations.
public class RegistrationViewModel
{
[Required]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
[Compare("ConfirmPassword")
public string Password { get; set; }
[Required]
[DataType(DataType.Password)]
public string ConfirmPassword { get; set; }
}
The reason it's important to use View Models is because the Business Models belong to the business layer, and they include data which should remain private. For instance, if you were to expose the Domain Model in a JSON response, it would expose the users entire data, their name their address as you're not being selective about what is being exposed and what isn't, but using whatever that seems to be working.
I should also point out here that there is a difference between domain models and entity models. There's already an answer that goes into a lot more detail here
Cross cutting concerns
I'll keep this brief:
Exception management
Mapping of View Models to Domain Models.
AutoMapper
I'm not an expert, but I will share my 50 cents on the topic.
View Model
I would like to share your concern about ignoring the View Model.
Using view model you can:
Select only the data you need from the domain model
Format the data you need in the right way to the presentation (e.g. format price decimal (100.00) to string (€100.00))
You can use DataAnnotation on your view model.
So, I also consider it a bad design, but others might have a different opinion.
Remember, the business layer doesn't know anything about the view model, so you should map it in the controller.
Entities vs domain model
I would start it simple, using a POCO as domain model that can be persisted with an ORM or a NoRM. For most of software developed in the world, it will not hurt your system much and it's also simple.
In the future, if you start using web services for some reason, you might need to consider the use of DTOs (Data Transfer Objects) for remote calls.
When there, what you can do is to have another layer, responsible for mapping your domain model to the desired DTO. This layer would be used only in the remote call (web service), keeping the view model for the presentation.
The main benefit of introducing additional classes is separation of concerns:
Presentation layer: display information and data entry, including any pre- and postprocessing to achieve this, e.g. formatting.
Domain / Business / Application logic: here the actual work is done
Persistence layer: store and retrieve data
This can be achieved with only two model classes for ViewModels and Domain Entities. Instead of modelling the domain logic with separate model classes that are similar to the persisted entities, implement it in service classes that consume the domain entities. The domain entities should at most have logic that deals with their own properties (e.g. to keep the combined values of two properties in a valid state). If more than one domain entity is affected by an usecase, model this usecase in a service class. If you put logic to manage the relationship between entities directly in the entity classes, the code becomes unmaintainable very quickly (trust me, I tried).
I do not recommend using the persistable entities as ViewModels, because this would mix display concerns (e.g. [DisplayName]) with persistence concerns (e.g. [ForeignKey]).

ViewModel for a model with a lot of properties?

I plan to create a Asp.Net MVC app which contains edit/create pages for a large model with many-to-many relationship with other models. I found the Saving Many to Many relationship data on MVC Create view and plan to use it.
In the example, the create page uses the following ViewModel.
public class UserProfileViewModel
{
public int UserProfileID { get; set; }
public string Name { get; set; }
public virtual ICollection<AssignedCourseData> Courses { get; set; }
}
And the UserProfile model has only two properties so the ViewModel just duplicates all the properties.
public class UserProfile
{
public UserProfile()
{
Courses = new List<Course>();
}
public int UserProfileID { get; set; }
public string Name { get; set; }
public virtual ICollection<Course> Courses { get; set; }
}
However, in my case, there will be a lot of properties (with data annotations), say 50 properties. Should the ViewModel duplicate all these properties (with data annotations too)? (looks ugly?) Or is there a better way?
Update
Is it a good practice to define ViewModel as
public class UserProfileViewModel
{
public UserProfile UserProfile { get; set; }
.... // Other properties needed by the view.
}
One shortcoming of this way is it expose all the properties in the Model even it's not needed in the view.
The thing with View Models is very simple: the View Model should consist only from data needed by the View. That is, the view model design is driven by the (static) view. Static because you can updates parts of the view via ajax in the browser so it makes no sense for your model to contain that info (except if it's required as init values for the JavaScript).
How the data is stored or how it's used by the business layer (if any) is not the view model concern.
Updated
The cleanest and safest way is to define the view models with the properties you need (you can copy paste them from the other model it's ok in this scenario) then use AutoMapper to map the business object to the view model. This way you can evolve both models differently. Personally, very rarely my view model is identical to a business model, they resembles a lot but there those tiny differences that complicate the things.
From a Separation of Concerns point of view, the busines model is for business usages, persistence model is for persistence usage while view model is for the view usage. Don't mix them or you'll have one model serving too many masters, which leads to complications down the road.
Taken from: This excellent explanation of ViewBag, ViewData and TempData
The type of data that suits ViewModels well is as follows:
Master-detail data
Larger sets of data
Complex relational data
Reporting and aggregate data
Dashboards
Data from disparate sources
So in summary, yes the ViewModel is what to use when the view requires a lot of complexity, it suits your needs. As for using and populating every property that should be determined by what the particular view requires. ViewModels are not necessarily one to one representations of a model / entity. That should be dictated by your view requirements, e.g. UserCourseViewModel could aggregate the UserProfile and Course entities, but not necessarily all of both of their properties, unless of course all properties are required by the view.
Rachels summary:
The ViewData and ViewBag objects give you ways to access those extra pieces of data that go alongside your model, however for more complex data, you can move up to the ViewModel. TempData, on the other hand, is geared specifically for working with data on HTTP redirects, so remember to be cautious when using TempData.

Where to keep business logics in MVC architecture?

In my company we have recently started developing MVC application. Our task is to write the business logic layer and in future it should be with less maintenance.
We have couple of web services to add/update/delete user information.
Now we have to add the business logics like:
If Field1 on the page is 'xxxx' then field2 should be in the range of 1000 to 2000
If field3 is some department then field4 should be only in some sub departments.
So we have to design the layer so that in future our admin(who don't have programming knowledge) can go in and change the logics so that it will work. Please give me some suggestions.
So far what i have got is: Write all these conditions in Model and validate them when user click save button.
Thanks in advance.
Business logic should kept inside the model. You should aim to have a big Model and a small controller.
You may find this interesting to read this.
Also check Where does the “business logic layer” fit in to an MVC application?
Keep it in a separate assembly which doesn't know about your ui layer. Your models can go here and enforce business rules. I personally like building the business layer on top of the Csla framework, which lets you build rich models with powerful rules. Its geared toward ntier development but I believe its also compatible with ddd.
When you are talking about layering, your Business layer should be separated from Presentation Layer. ASP.NET MVC is a presentation technology; so, your Business Layer would be in different assembly. Additionally, your Business Model wouldn't be used directly in your views; you can use ViewModel to validate user input and when everything was OK, transfer ViewModel data into Business Entity.
If you are interested to obtain more information about layering in enterprise level applications I recommend you Microsoft Spain - Domain Oriented N-Layered .NET 4.0 Sample App.
I like to use Entity Framework and Fluent Validation to create a domain layer that contains both models and validators. The set up looks like this:
public abstract class DomainEntity
{
private IValidator validator;
protected DomainEntity(IValidator validator)
{
this.validator = validator;
}
public bool IsValid
{
get { return validator.IsValid; }
}
public ValidationResult Validate()
{
return validator.Validate();
}
}
public class Person : DomainEntity
{
public int Id { get; set; }
public string Name { get; set; }
public Person() : base(new PersonValidator())
}
public class PersonValidator() : AbstractValidator<Person>
{
public PersonValidator()
{
... validation logic
}
}
Using this set up, my models and validators live in the same layer but I don't muddy up my model classes with busines logic.
Business Logic should be in Model layer, and I don't think that anyone without programming knowledge can change business logic, he must have basic programming knowledge at least
You can use DataAnnotations to do this - in fact data annotations enable more than just server side enforcing of model validity. They can also give hints to Entity Framework and client side scripts in order for database/client side validation, and add metadata to methods and properties that MVC can inspect
e.g. for a model:
class PersonDetailsModel
{
[Required("Please enter a name")] // Don't allow no value, show the message when the rule is broken (if client side validation is enabled it shows when you tab off the control)
[DisplayName("Full Name")] // Hint for MVC - show this when using the helper methods e.g. in MVC4 Razor syntax #Html.LabelFor(model => model.Name)
public string Name { get; set; }
}
And yes, keep as much business logic in the business layer (model). Cross-cutting concerns aside, your components should be as loosely coupled as possible. This way there is a central place to make changes, your code is more testable and maintainable and it also helps you to keep your programming consistent (which helps newbies to your project get up to speed quickly)
If you have more complex rules, you can write EF validators.
http://msdn.microsoft.com/en-gb/data/gg193959.aspx
If you aren't using Entity Framework then you might want to consider it - if you are using another ORM then obviously use the tools that support that. If you aren't using an ORM, then there are alternatives but you'll have to write some plumbing code

Data Transfer Objects in Asp.net MVC

I've been assigned to work on a site that uses MVC for the presentation layer and that talks to a WCF service. The two use DTO's to pass information back and forth.
Currently, DTO's are used throughout the MVC portion (User, Address, Account Information). For example, the User class in MVC has a PersonDTO that contains all the information about the user as well as methods specific to the web (Login):
public class User
{
public PersonDTO Person { get; set; }
public void Login { /* Login */ }
}
So to get the users first name, you would do:
var CurrentUser = new User();
var firstName = CurrentUser.Person.First;
Is there a better way of doing this? (It seems like it should be CurrentUser.First)
Other than being wordy, are there any pitfalls of doing this?
Are DTO's meant to bleed into Controller Actions in MVC?
I wrap my DTOs in an additional "ViewModel" class only if there is value added. I don't see a problem having your views bind directly to your DTOs if they contain all the data needed to power the views.
An example of when the "viewModel" makes sense is when you have additional UI concerns like combining multiple fields into one etc.
I normally find that DTOs contain more data than I need, or not enough data. Because of this, I get my DTOs from the service and then map them through Automapper to the view models.

Categories