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.