Validating asp.net mvc when using viewmodel

I recently decided to use viewmodels instead of EF EntityObjects. I am sure that there will be no problems with GET, but I want to know what to do with the steps to create and update. I read a lot of discussions and decided that I would act int this way . but there were still questions:

1) when I used EF EntityObjects with annotations, the validation logic was stored in one place, but if I have different viewing modes in different projects, then I will have to duplicate the validation rules. Is this not a violation of the DRY principle?

2) I read several posts about view models and validation, where people suggest checking input in view models and business rules in domain models, but I can’t understand how I can trigger validation defined in domain models if my actions are viewmodels as parameters:

public class MyDomainModel : IValidatableObject { public string Title; // validation of business rules } public class MyViewModel { [Required] public string Title; } public ActionResult Edit(MyViewModel item) { if (ModelState.IsValid) // MyViewModel rules are validated not MyDomainModel's { ... } 
+4
source share
1 answer

If you switch to ViewModels, you must allow the framework to validate through DataAttributes in the ViewModel classes. This is just a formal input check, then you should check in accordance with your business rules (sometimes it’s just impossible to cover all the scenarios with data annotations), and in case of errors add them to the model state.

Example:

 public class MyViewModel { [Required] [StringLength(20)] [RegularExpression("whatever")] public string Foo { get; set; } [Required] public int Bar { get; set; } public bool AFlagNotModifiableButImportant { get; set; } } 

in your post, you can do something like:

 public ActionResult Sample (MyViewModel Obj) { if (!ModelState.IsValid) { return View(Obj); } // Complex business logi checks in here MyBusinessObj BsnObj = new MyBusinessObj(Obj); if (!BsnObj.IsValid()) { ModelState.AddModelError(string.Empty, "A veery bad error"); return View(Obj); } // Perform Heavy Business Logic which creates a new ViewModel (eg. setting the flag property in order to show something important at view level) MyViewModel NewOne = BsnObj.DoIt(); // Return a view with the new Model (can be whatever you want) return View(NewOne); } 

Obviously, I keep it very simple. After this template, be sure to add a bit of overhead from the point of view of the code, but the checks should be performed both on the client side (only formal verification at the input) and on the server side (both formal and semantic verification). I prefer to have all the semantics in the business assembly, leaving formal checks to the unobtrusive MVC check mechanism (only some UI sugars in my views, yes, I hate Javascript).

Typically, my Business Objects use ViewModel properties, viewing them read-only (only useful to prevent bad injections) and do the dirty / hard work.

This may not be the ideal solution for everything, but I noticed that applying this template (and getting another team member to do the same) leads to a good code base. Yes, we are still far from perfect, I would like to write both semantics and formal checks only once, but now how the Internet works.

Let me know if you need further advice or if I don’t fully understand your question.

PS: as soon as you select a template, stick to it no matter what.

EDIT: (long comments - no)

In the constructor, I usually apply mappings in the fields that I need to change, I try to consider the ViewModel properties as read-only, to avoid unwanted changes.

My IsValid() method simply contains business checks (for example, if an identifier is checked for real existence in a certain table or gives a username, checks if it can actually access certain data).

This is just a separation between the ViewModel validation (for me, just syntax => the lines are strings, an integer is integers, positive numbers are → = 0, the length of the lines is respected, ranges are met, etc.) and the actual reality of the business (semantic => user can get access to some data, the object is valid in the application area).

Of course, the level of business verification can also be simple (or does not exist at all), I prefer to store them for reuse (often my business logic is shared between the MVC application and the WPF application). This is a bit of extra work, but in the long run it pays better, I can use all my complex business logic everywhere. (and working with banks is the most important goal. Change the logic in only one assembly, for example, to add a new check for something and make sure that every application using this assembly will be updated).

So definitely this is more work, but I think it’s better to invest a few hours in Dev sooner than spending days lately on maintenance / evolution.

Currently, programming seems to be reduced to “forget-it-yourself” activity (due to reduced time / budget or simply because we perform our task and then change the employee), but each line that is encoded needs some maintenance in in the future, so it’s better to keep things orderly and clean, preferring ease of maintenance over development speed.

+4
source

Source: https://habr.com/ru/post/1386103/


All Articles