Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>In an ASP.NET MVC architecture, you should try to do most of your validation in the Model, but with low-level validation rules like these, it's sometimes impossible. What you should look to for answers then is Domain-driven Design (DDD) where <a href="http://lostechies.com/jimmybogard/2008/08/21/services-in-domain-driven-design/" rel="nofollow">Application Services</a> can solve such low-level needs.</p> <p>Application Services will have access to the database (either directly, or better yet; indirectly through <a href="http://lostechies.com/jimmybogard/2009/09/03/ddd-repository-implementation-patterns/" rel="nofollow">repositories</a>) and can perform low-level validation and throw <code>ValidationException</code> or something similar (with detailed information the <code>Controller</code> can act upon and respond to the user) when a prerequisite or business rule isn't met.</p> <p><a href="http://www.sharparchitecture.net/" rel="nofollow">S#arp Architecture</a> implementes all of this in a best-practice framework that you can use as a basis for your ASP.NET MVC applications. It is highly opinionated towards DDD principles and NHibernate, and it will sometimes force your hand on how you do stuff, which is kind of the point. The most important part about it is that it learns you how to deal with these kinds of problems.</p> <p>To answer your question more concretely and in the spirit of DDD, this is how I would solve it:</p> <pre><code>public class UserController { private readonly IUserService userService; public UserController(IUserService userService) { // The IUserService will be injected into the controller with // an "Inversion of Control" container like NInject, Castle Windsor // or StructureMap: this.userService = userService; } public ActionResult Save(UserFormModel userFormModel) { if (userFormModel.IsValid) { try { // Mapping can be performed by AutoMapper or some similar library UserDto userDto = Mapper.Map&lt;UserDto&gt;(userFormModel); this.userService.Save(userDto); } catch (ValidationException ve) { ViewBag.Error = ve.Detail; } } // Show validation errors or redirect to a "user saved" page. } } public class UserService : IUserService { private readonly IUserRepository userRepository; public UserService(IUserRepository userRepository) { // The IUserRepository will be injected into the service with // an "Inversion of Control" container like NInject, Castle Windsor // or StructureMap: this.userRepository = userReposityr; } public UserDto Save(UserDto userDto) { using (this.userRepository.BeginTransaction()) { if (!this.userRepository.IsUnique(userDto.UserName)) { // The UserNameNotUniqueValidationException will inherit from ValidationException // and build a Detail object that contains information that can be presented to // a user. throw new UserNameNotUniqueValidationException(userDto.UserName); } userDto = this.userRepository.Save(userDto); this.userRepository.CommitTransaction(); return userDto; } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload