如何让控制器的ModelState服务于验证

时间:2014-07-07 02:00:38

标签: c# asp.net-mvc asp.net-mvc-4 castle-windsor

我正处于这个人(Controller ModelState with ModelStateWrappper)的情况,除了我正在使用Castle Windsor DI。在保存模型之前,我试图在我的服务中验证我的模型的业务逻辑方面,并将其传递给数据存储。如果验证失败,我想得到模型状态错误并显示在我的视图中。 (我将关注本文作为从服务实施验证的指南:http://www.asp.net/mvc/tutorials/older-versions/models-(data)/validating-with-a-service-layer-cs

以下是我的示例代码

//My controller code
        public class TimeEntryController : TempoBaseController
        {
            public TimeEntryController(TimeService service, UserService userService)
            {
                _service = service;
                _userService = userService;
            }
            [Authorize(Roles = "Worker")]
            public ActionResult Index() 
            {
            return View();
            }
            [AcceptVerbs(HttpVerbs.Post)]
            public ActionResult Index(EntryLogDto entry)
            {
              if(_service.AddEntryLog(entry))
              {
                return ViewSuccess();
              }else
              {
                return ViewFailue();
              }
            }

        }

//My Service class
    public class TimeService : GenericService
    {
        public TimeService(IRepository repository, IValidationDictionary validationDictionary, UserManager<ApplicationUser>     userManager)
            : base(repository, validationDictionary, userManager)
        {
        }

        public bool AddEntryLog(EntryLogDto log)
        {
            if (!ValidateEntryLog(log))
              {
                //return false;

            }
            else
            {
                //insert entry into database and return true
            }
            }
        protected bool ValidateEntryLog(EntryLogDto log)
        {
            //Check if the entry overlaps with any other entries
            bool res = _repository.Find<EntryLogDto>(//my linq logic);
            if (res)
            {
              _validationDictionary.IsValid = true;
            }else
            {
            _validatonDictionary.AddError("Entry", "Entry Overlaps.");
              _validationDictionary.IsValid = false;
            }
            return _validationDictionary.IsValid;
        }
    }

//Validation class

    public class TempoValidation : IValidationDictionary
    {
        private ModelStateDictionary _modelState;
        public TempoValidation(ModelStateDictionary modelState) // Issue is how am I gona give it this as the ModelStateDictiona         ry is controller specific
        {
            _modelState = modelState;
        }

        public void AddError(string key, string error)
        {
            _modelState.AddModelError(key, error);

        }

        public bool IsValid
        {
            get { return _modelState.IsValid; }
        }
    }

//Global.asax castle compnonent registration method
                container
                .Register(Component
                            .For<Tempo.Model.Configuration.TempoDbContext>()
                            .LifestylePerWebRequest()
                            .DependsOn(new { connectionString }))
                .Register(Component
                            .For<DbRepositories.ITempoDataContextFactory>()
                            .AsFactory())
                .Register(Component
                            .For<IRepository>()
                            .ImplementedBy<Tempo.Repositories.EntityFrameworkRepository.Repository>())
                .Register(Component
                            .For<TimeService>().LifestyleTransient())

我在服务类中注入IValidationDictionary,我根据验证结果设置模型状态。当我使用它时,有没有办法可以传递控制器的模型状态?我不知道如何处理这个,我有很多控制器,我不知道我将如何/何时通过相应控制器的模型状态(我想通过DI来做到这一点)如果可能的话......我不知道castle是否可以为每个控制器创建一个单独的TempoValidation类实例?

1 个答案:

答案 0 :(得分:1)

我知道默认情况下无法执行此操作,但您可以使用Fluent Validation来实现此目的。

示例:

<强>视图模型

 [Validator(typeof(VmSysTestValidator))]
    public class VmSysTestModel
    {
        public int Id { get; set; }
        [Required]
        public string FirstName { get; set; }
        [Required]
        public string LastName { get; set; }
    }

流畅的验证实施:

 public class VmSysTestValidator : AbstractValidator<VmSysTestModel>
    {
        public VmSysTestValidator()
        {
            RuleFor(x => x.FirstName).NotNull().WithMessage("First name is required");
            RuleFor(x => x.LastName).NotNull().WithMessage("Last Name is required");
        }
    }

控制器或业务逻辑方:

[HttpPost]
        public ActionResult TestPost(VmSysTestModel obj)
        {

            //Start Validation     From start to end you can call this code everywhere you want  , this will work like server side valdiatin
            //Instead of ModelState.IsValid you will call your fluent validator
            var testValidator = new VmSysTestValidator();
            var validationResult = testValidator.Validate(obj);
            if (validationResult.IsValid)
            {

            }
            else
            {

            }
            //End valdiation 
        }