我正处于这个人(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类实例?
答案 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
}