I wonder if there is a way to validate just one of my models in the viewmodel send it to my action? I use the DataAnnotations as validate rules.
Like the if (!ModelState.IsValid)
let me know if the question is unclear and I will edit for a better explination
EDIT
my viewmodel looks like this
public class CompaniesViewModel
{
public Core.Model.Customer Company { get; set; }
public IEnumerable<SelectListItem> Items { get; set; }
public Core.Model.Meeting Meeting { get; set; }
}
What I want to do in this particular situation is to validate just Customer. I cant do the ModelState.IsValid then all get validated. So how can I do to just validate one of them like customer in this case. Hope this was more clear
There are a number of different ways you can do this. The first is to add a property called IsValid that checks the property. So something like:
public class Company
{
public bool IsValid
{
get { return GetValid() }
}
private bool IsValid()
{
if ( Some check here )
return false;
}
}
[HttpPost]
public ActionResult SomeAction(CompaniesViewModel model)
{
if (model.Company.IsValid)
{
}
}
However a better solution IMO would be just to post the Company to your controller rather than your entire view model. Just because your passing a view model to a view it doesn't mean that you need to post the entire view model back. When you create your HTML form specify only the properties you want to post back to your controller. So for example your controller would become:
[HttpPost]
public ActionResult SomeAction(Company company)
{
if (Model.IsValid)
{
}
}
Now when you check if Model.IsValid it just check company as that is all you've passed back to the controller.
At server side, you can try the ValidateModel(object) method, like in TryValidateModel(CompaniesViewModel.Company).
If you have enabled client sided validation, you need to post only the relevant entity. If you want to post all entities, but you need to validate only one, you can consider the following:
either removing the rules, using javascript ASP .NET MVC Disable Client Side Validation at Per-Field Level
or creating a Data-Transfer-Object, ie a View Model which has NO link to the Model, but reproduces the entities you want with the validation rules you want having applied in this scenario. Of course, then, you'll need in your controller or a model binder some way to bind from your ViewModel to your Model entities.
You can separate Customer Model to another class in your ViewModel and map that in Controller to a existing/new Customer:
public class CompaniesViewModel
{
public Company Company { get; set; }
public IEnumerable<SelectListItem> Items { get; set; }
public Core.Model.Meeting Meeting { get; set; }
}
//Validations for Company go here:
public class Company
{
public string CompanyId { get; set; }
[Required]
public string CompanyName { get; set; }
}
Related
I have a viewmodel which consists of three models which are all displayed on the screen as one single form.
public class ViewModel
{
public PersonVM person { get; set; }
public DepartmentVM department { get; set; }
public EmploymentVM employment { get; set; }
}
When users fill in the form, they can fill one model details (example:- Person) and leave the other models details empty.
How do I implement model validation in my action method for all three models. I want to do model validation only if the model is populated (not null) for each of them.
How do I implement model validation depending on whether the individual model is populated or not ?
You could implement IValidatableObject on your models
public class ViewModel : IValidatableObject
{
public PersonVM person { get; set; }
public DepartmentVM department { get; set; }
public EmploymentVM employment { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
// Add custom logic to validate each object
}
}
If you add IValidatableObject to each of your form VMs then you could then call each of them from the ViewModel class
What you need is a custom model validation. You can create a custom action filter by inheriting from ActionFilterAttribute, IActionFilter.
http://www.asp.net/mvc/overview/older-versions/hands-on-labs/aspnet-mvc-4-custom-action-filters
I have 3 domain models - Item, ItemProductLine, and ProductLine. Each of these map to already existing database tables. I also have a view model that I use in my view.
Domain models:
public class Item
{
public string itemId { get; set; }
public string itemDescription { get; set; }
public float unitPrice { get; set; }
// more fields
public virtual ItemProductLine itemProductLine { get; set; }
}
public class ItemProductLine
{
public string itemId { get; set; }
public String productLineId { get; set; }
// more fields
public virtual ProductLine productLine { get; set; }
}
public class ProductLine
{
public string productLineId { get; set; }
public string productLine { get; set; }
// more fields
}
View model:
public class ItemViewModel
{
public string itemNumber { get; set; }
public String itemDescription { get; set; }
public Double unitPrice { get; set; }
public string productLine { get; set; }
}
My current query is:
from item in dbContext.Items
where unitPrice > 10
select new ItemViewModel()
{
itemNumber = item.itemNumber
itemDescription = item.itemDescription
unitPrice = item.unitPrice
productLine = item.itemProductLine.productLine.productLine
}
I currently have this query in the controller, but I am refactoring the code. I want to put the query code in a repository class in a data access layer. From what I've read, I should not reference any view models in that layer. If I change select new ItemViewModel() to select new Item(), it will return the error:
The entity or complex type 'proj.DAL.Item' cannot be constructed in a LINQ to Entities query.
A solution I have seen is to create a data transfer object (DTO) to transfer data from my domain model to my view model.
However, by doing this, I would have 3 copies of the data. If I need to add another database field and display it, I need to update 3 files. I believe I am violating the DRY principle. Is it inevitable to violate the DRY principle when using DTOs and view models? If not, can you provide an example of how to refactor this to have DRY code?
Having multiple models is not a DRY violation however your code breaks the Separation of Concerns principle because the domain model is the same with (or built upon, read: coupled to) persistence model. You should keep your models separated for each layer and use a tool like automapper to map them. This prevents the model to serve more than one purpose.
It looks like repeating yourself, but in fact you are keeping your layers decoupled and ensuring code maintainability.
Unlike ramiramulu, I would refrain from introducing too many abstractions.
If you use EF, your DAL is actually Entity Framework, no need to abstract that. A lot of people attempts to do this but this only complicates your code a lot, for no gain. If you were doing SQL requests and calling stored procedures directly, then a DAL would be helpful, but building an abstraction on top of EF (which is another abstraction, or over NHibernate) is a bad idea.
Also, pure DTOs as an abstraction are more and more frown upon, but they can be used if you have a middleware and do not directly access the database - for example, a message bus like NServiceBus: messages would be considered DTOs in that case.
Unless you do very simple and pure CRUD (in which case, go ahead, put the logic in controllers - no reason to add complexity for pretty straightforward business), you should move business logic outside of your controllers for sure. For this you have many options, but 2 of the most popular are : a rich domain model with domain driven design or rich business services with service oriented design. They are a lot of ways to do this, but these 2 illustrates very different approaches.
Rich Domain (Controller per Aggregate)
In the first case, your controller would be responsible for acquiring the domain object, calling the logic, and returning a View Model. They do the bridge between the View world and the Model world. How to acquire the domain object(s) needs to be somewhat abstracted, often simple virtual methods works great - keep it simple.
Aggregate Root:
public class Item
{
public string itemId { get; set; }
public string itemDescription { get; set; }
public float unitPrice { get; set; }
// more fields
public virtual ItemProductLine itemProductLine { get; set; }
// Example of logic, should always be in your aggregate and not in ItemProductLine for example
public void UpdatePrice(float newPrice)
{
// ... Implement logic
}
}
View Model:
public class ItemViewModel
{
public int id { get; set; }
public string itemNumber { get; set; }
public String itemDescription { get; set; }
public Double unitPrice { get; set; }
public string productLine { get; set; }
}
Controller:
public class ItemController : Controller
{
[HttpGet]
public ActionResult Edit(int id)
{
var item = GetById(id);
// Some logic to map to the VM, maybe automapper, valueinjector, etc.
var model = item.MapTo<ItemViewModel>();
return View(model);
}
[HttpPost]
public ActionResult Update(int id, ItemViewModel model)
{
// Do some validation
if (!model.IsValid)
{
View("Edit", model); // return edit view
}
var item = GetById(model.id);
// Execute logic
item.UpdatePrice(model.unitPrice);
// ... maybe more logic calls
Save(item);
return RedirectToAction("Edit");
}
public virtual Item GetById(int id)
{
return dbContext.Items.Find(id);
}
public virtual bool Save(Item item)
{
// probably could/should be abstracted in a Unit of Work
dbContext.Items.Update(item);
dbContext.Save();
}
}
This works great with logic that trickles down and are very model specific. It is also great when you do not use CRUD and are very action-based (e.g. a button to update only the price compared to an edit page where you can change all item values). It is pretty decoupled and the separation of concerns is there - you can edit and test business logic on their own, you can test controllers without a backend (by overriding the virtual functions), and you do not have hundreds of abstractions built on one another. You might roll out the virtual function in a repository class, but by experience you always have very specific filters and concerns that are controller/view dependent, and often you end up with one controller per aggregate root, so controllers are a good place for them (e.g. .GetAllItemsWithAPriceGreaterThan(10.0))
In an architecture like that, you have to be careful about boundaries. For example, you could have a Product controller/aggregate and want to list all Items related to that product, but it should be read-only - you couldn't call any business on Items from Products - you need to navigate to the Item controller for that. The best way to do this is to automatically map to the ViewModel :
public class ProductController : Controller
{
// ...
public virtual IEnumerable<ItemViewModel> GetItemsByProductId(int id)
{
return dbContext.Items
.Where(x => ...)
.Select(x => x.MapTo<ItemViewModel>())
.ToList();
// No risks of editing Items
}
}
Rich Services (Controller per Service)
With rich services, you build a more service oriented abstraction. This is great when business logic spawns multiple boundaries and models. Services play the role of the bridge between the View and the Model. They should NEVER expose the underlying Models, only specific ViewModels (which play the role of DTO in that case). This is very good when you have a MVC site and some REST WebApi working on the same dataset for example, they can reuse the same services.
Model:
public class Item
{
public string itemId { get; set; }
public string itemDescription { get; set; }
public float unitPrice { get; set; }
// more fields
public virtual ItemProductLine itemProductLine { get; set; }
}
View Model:
public class ItemViewModel
{
public int id { get; set; }
public string itemNumber { get; set; }
public String itemDescription { get; set; }
public Double unitPrice { get; set; }
public string productLine { get; set; }
}
Service:
public class ItemService
{
public ItemViewModel Load(int id)
{
return dbContext.Items.Find(id).MapTo<ItemViewModel>();
}
public bool Update(ItemViewModel model)
{
var item = dbContext.Items.Find(model.id);
// update item with model and check rules/validate
// ...
if (valid)
{
dbContext.Items.Update(item);
dbContext.Save();
return true;
}
return false;
}
}
Controller:
public class ItemController : Controller
{
public ItemService Service { get; private set; }
public ItemController(ItemService service)
{
this.Service = service;
}
[HttpGet]
public ActionResult Edit(int id)
{
return View(Service.Load(id));
}
[HttpPost]
public ActionResult Update(int id, ItemViewModel model)
{
// Do some validation and update
if (!model.IsValid || !Service.Update(model))
{
View("Edit", model); // return edit view
}
return RedirectToAction("Edit");
}
}
Controllers are only there to call the Service(s) and compose the results for the Views. They are "dumb" compared to domain oriented controllers, but if you have a lot of views complexities (tons of composed views, ajax, complex validation, json/xml processing along side html, etc.), this is the preferred approach.
Also, in this case, services do not have to related to only one model. The same service could manipulate multiple model types if they share business logic. So an OrderService could access the inventory and make adjustments there, etc. They are more process-based than model-based.
I would do it this way -
My Domain Model -
public class Item
{
// more fields
public virtual ItemProductLine itemProductLine { get; set; }
}
public class ItemProductLine : ProductLine
{
// more fields
}
public class ProductLine
{
// more fields
}
DAL Would be -
public class ItemRepository
{
public Item Fetch(int id)
{
// Get Data from Database into Item Model
}
}
BAL would be -
public class ItemBusinessLayer
{
public Item GetItem(int id)
{
// Do business logic here
DAL.Fetch(10);
}
}
Controller would be -
public class ItemController : Controller
{
public ActionResult Index(int id)
{
Item _item = BAL.GetItem(10);
ItemViewModel _itemViewModel = AutomapperExt.Convert(_item); // something where automapper will be invoked for conversion process
return View(_itemViewModel);
}
}
Automapper will be maintained in a separate class library.
The main reason why I choose this way is that, for a particular business there can be any number of applications/frontends, but their business domain models shouldn't change. So my BAL is not going to change. It returns business domains itself. Thats doesn't mean everytime I need to return Item model, instead I will have MainItemModel, MiniItemModel etc., all these models will server business requirements.
Now it is the responsibility of frontend (probably controllers) to decide which BAL method to be invoked and how much data to be used on frontend.
Now some devs might argue, that UI shouldn't be having that judgement capacity to decide how much data to use and what data to see, instead BAL should have that power to make decision. I agree and that happens in BAL itself if our domain model is strong and flexible. If security is main constraint and domain models are very rugged, then we can have the automapper conversion at BAL itself. Or else simply have it on UI side. End of the day, MVC is all about making code more manageable, cleaner, reusable and comfortable.
I have a scenario where I need to update an object from information that was posted to the action. As long as the information is in the page this works fine. However, it requires that I put information into hidden fields if I don't want the modelstate to complain.
As an example, lets say I am using the class below as the model:
public class Client
{
[Required]
public string Name { get; set; }
public string Email { get; set; }
public int Id { get; set; }
}
If I don't want the user to edit the name, I need to include it in a hidden field so that it get bound to the model and the validation passes.
The problem I have is that is obviously not secure if used with more sensitive information. So I tried this:
public virtual ActionResult Save(Client model, int clientId)
{
var client = datasource.LoadEntity(adapter, clientId); // clientId is passed as a querystring to the action
if (!TryUpdateModel(client))
return new RedirectResult('The edit page URL');
}
The problem is that the modelstate still complains about the "Name" value not being available even though it was loaded to the client object from the database.
Obviously I am doing something wrong but I can't figure out what.
The view model is just for information coming from the client.
So you have to remove the Name property and get it from somewhere else.
If this is a view model also used by the administrator for example (who is able to enter/change the name) then the best would be a derived view model like this:
public class Client
{
public string Email { get; set; }
public int Id { get; set; }
}
public class ClientWithName : Client
{
[Required]
public string Name { get; set; }
}
You can use the overload TryUpdateModel(TModel, string\[\]); if my understanding is correct, this should allow to specify the property to include in the update, like this:
public virtual ActionResult Save(Client model, int clientId)
{
var client = datasource.LoadEntity(adapter, clientId);
if (!TryUpdateModel(client, new string[] { "Email" }))
return new RedirectResult('The edit page URL');
}
I never tried it though, can you let us know if it works as expected?
I've gone with the solution outlined here: Asp.net MVC 3 Validation exclude some field validation in TryUpdateModel
Essentially, it removes the validation from the Modelstate if those fields aren't present which works for me as those values are retrieved from the database.
I'm trying to understand and figure good practices for designing your app/domain models (POCOs/DTOs).
Let's say I have the following database table, Account:
UserID int
Email varchar(50)
PasswordHash varchar(250)
PasswordSalt varchar(250)
Of course, EF4 would build the entity like so:
public class Account
{
public int UserID { get; set; }
public string Email { get; set; }
public string PasswordHash { get; set; }
public string PasswordSalt { get; set; }
}
Now, let's say I have a view model for registering a new user, which may look something like so:
public class RegistrationViewModel
{
public string Email { get; set; }
public string Password { get; set; }
}
Lastly, I have a service which needs to register the user:
public class RegistrationService
{
public void RegisterUser(??? registration)
{
// Do stuff to register user
}
}
I'm trying to figure out what to pass into the RegisterUser method. The view model is, of course, located under my web app (presentation layer), so I do not want this getting passed to my service.
So, I'm thinking one of four possibilities:
1) Set up a service model that is similar, if not identical, to the RegistrationViewModel, and use this:
public class RegistrationServiceModel
{
public string Email { get; set; }
public string Password { get; set; }
}
public class RegistrationService
{
public void RegisterUser(RegistrationServiceModel registration)
{
// Do stuff to register user
}
}
2) Set up an interface of the model, and inherit this in my view model, and set up my method to accept the interface:
public interface IRegistrationModel
{
string Email;
string Password;
}
public class RegistrationServiceModel : IRegistrationModel
{
public string Email { get; set; }
public string Password { get; set; }
}
public class RegistrationService
{
public void RegisterUser(IRegistrationModel registration)
{
// Do stuff to register user
}
}
3) Pass in the Account entity, doing the RegistrationViewModel-to-Account mapping in my controller:
public class RegistrationService
{
public void RegisterUser(Account account)
{
// Do stuff to register user
}
}
4) Move my view model out of the presentation into a domain/service layer, and pass that into the service method:
public class RegistrationService
{
public void RegisterUser(RegistrationViewModel account)
{
// Do stuff to register user
}
}
None of these three scenarios seem ideal, as I see problems in each of them. So I'm wondering if there's another method I can't think of.
What are good practices for this?
Thanks in advance.
You never pass a view model to the service. A service doesn't even know about the existence of a view model that you might have defined in your presentation tier. A service works with domain models.
Use Auto mapper to map between view model and domain model and vice versa.
Personally, I've never heard of service models in DDD (view models for services).
Use 3rd option, for sure. As Å¡ljaker said, Service should be unaware of presentation part of application (which your ViewModel is a part of).
Sure, as well, don't overcomplicate things around by including tons of transition models like RegistrationServiceModel or - even worse - IRegistrationModel (last one will lead to "interface explosion" one day).
So:
Have a Domain entity (POCO entity that is persisted with Entity Framework or NHibernate or NoRM or whatever).
Have a ViewModel that represents your domain model in given context. Don't hesitate to make a ViewModel per Controller Action if necessary. The side-effect benefit of strict ViewModels (those which are 1:1 with your View) is complete absence of over-posting and under-posting problems. It depends on your concrete situation/taste though.
Use DataAnnotation attributes with your ViewModels to provide basic validation (remember to validate business rules too but it should sit behind the wire - inside Services/Repositories layer).
Don't let App Service ever know about ViewModels. Create a domain entity instance and feed it to the Service instead (to validate/persist).
Use AutoMapper as an option to quicky map from your domain entities to ViewModels.
Map from incoming ViewModel or FormCollection to your entity in either Controller action or custom IModelBinder.
(Optionally) I'd recommend to follow the Thunderdome Principle. It's a really really convenient usage of ViewModels.
In this case it makes perfect sense to use a DTO (Data Transfer Object). You can create an AccountDto class at the service layer and use it to pass the registration data down to the service. It might be similar to the ViewModel in some cases, but generally you can show much more in your View than is required to create a user. To further illustrate the point, your ViewModel will probably at least look something like this:
public class RegistrationViewModel
{
[Required]
public string Email { get; set; }
[Required]
public string Password { get; set; }
[Required]
[Compare("Password")]
public string RepeatPassword { get; set; }
}
While your DTO will only require the Email and Password properties.
public class AccountDto
{
public string Email { get; set; }
public string Password { get; set; }
}
So as you see, the ViewModel only contains data needed for the View. The email validation and password comparison logic happens in your Web layer. You use the DTO to get get only email and password to the Service. And then at the service layer you hash the password, populate your Entity object and persist the values to the database.
I am creating this MVC model and trying to understand best way to do it.How should I get related data when I have relationships between tables.For example in code below I have created a formviewmodel and I am calling function to get all images in Images table for a user. Should I instead keep images property of Users model and fill that within LINQ query in repository instead of calling a method from the Model? Is there a way in LINQ to autofill all images for the contact?
public class UserFormViewModel {
UucsrRepository repository = new UucsrRepository();
public User User { get; set; }
public SelectList States { get; private set; }
public SelectList Genders { get; private set; }
public List<Images> UserImages { get; set; }
public UserFormViewModel(User User) {
User = User;
UserImages = repository.GetUserImages(User.Id).ToList();
States = new SelectList(repository.GetAllStates(), "ShortName", "Name");
Genders = new SelectList(repository.GetAllGenders(), "Gender", "Description");
}
}
Thanks !
First it typically does not make sense to store the actual repository object in the viewmodel. That violates the tenent that you should only send the view exactly what it needs and nothing more. They way i typically create the viewmodels is to ahve a very basic wrapper with almost no code in it. Most of the logic to fill the VM is done in the controller using the repository pattern.
Your example is clear enough to understand how you should or should not be using view models.
Kevin correctly noted, that the ViewModel should only contain the data you use in the view for presentational purposes. In your case, depending on what the view does, you might only send a subset of your User properties. For example, if you just show some user information, but not modify it, you don't need to send the user ID. I would go with smth like:
public class UserFormViewModel
{
public string UserName { get; set; }
public string Email { get; set; }
...
public SelectList States { get; private set; }
public SelectList Genders { get; private set; }
public List<Images> UserImages { get; set; }
}
To populate (prepare) the ViewModel it's rather convenient to use a separate helper method:
private UserFormViewModel PopulateUserFormViewModel(int userId)
{
var model = new UserFormViewModel();
var user = repository.GetUser(userId);
model.UserName = user.Name;
model.Email = user.Email;
...
model.UserImages = repository.GetUserImages(userId).ToList();
...
return model;
}
And in your action you call:
public ActionResult ShowUser(int userId)
{
// maybe do something else
var userFormViewModel = PopulateUserFormViewModel(userId);
return View(userFormViewModel);
}
That's just one of the possible ways, but the general principles are pretty clear: keep your ViewModel simple (just the data you need in the view) and preferably create a reusable method for converting your domain object into your ViewModel.