我假设你想让modelstate传入来自动将任何错误注入到模型中?恕我直言,ModelState应该保持它的位置,并且将验证错误带给它。以下是我如何处理错误的例子。我并不是说这是最好的方法或唯一的方法,但它是验证层不需要了解谁或什么会消耗验证错误的一种方法。
首先,在我的poco中,我使用System.ComponentModel.DataAnnotations
作为验证规则。例如,这是我的帐户类。因为我想自己发起验证(除了MVC自己做)之外,我不得不实现我自己的验证器。
public class Validator<T> where T : CoreObjectBase<T>
{
public ValidationResponse Validate(T entity)
{
var validationResults = new List<ValidationResult>();
var context = new ValidationContext(entity, null, null);
var isValid = Validator.TryValidateObject(entity, context, validationResults);
return new ValidationResponse(validationResults.ToArray());
}
}
这里是为ValidationResult我传回
[Serializable]
public class ValidationResponse
{
public IList<ValidationResult> Violations { get; private set; }
public IList<ErrorInfo> Errors { get; private set; }
public bool HasViolations
{
get { return Violations.Count > 0; }
}
public ValidationResponse(params ValidationResult[] violations)
{
Violations = new List<ValidationResult>(violations);
var errors = from v in Violations
from n in v.MemberNames
select new ErrorInfo(n, v.ErrorMessage);
Errors = errors.ToList();
}
}
ERRORINFO是有关我的错误
[Serializable]
public class ErrorInfo
{
public string ErrorMessage { get; private set; }
public object Object { get; private set; }
public string PropertyName { get; private set; }
public ErrorInfo(string propertyName, string errorMessage)
: this(propertyName, errorMessage, null)
{
}
public ErrorInfo(string propertyName, string errorMessage, object onObject)
{
PropertyName = propertyName;
ErrorMessage = errorMessage;
Object = onObject;
}
}
为了包装这验证了一个非常基本的类的所有漂亮和整洁用我的poco类,我从一个基类继承。为了验证,通用的地方是继承的孩子必须告诉基类是类型的。它感觉是圆形的,但它起作用。
[Serializable]
public class CoreObjectBase<T> : IValidatable where T : CoreObjectBase<T>
{
#region IValidatable Members
public virtual bool IsValid
{
get
{
// First, check rules that always apply to this type
var result = new Validator<T>().Validate((T)this);
// return false if any violations occurred
return !result.HasViolations;
}
}
public virtual ValidationResponse ValidationResults
{
get
{
var result = new Validator<T>().Validate((T)this);
return result;
}
}
public virtual void Validate()
{
// First, check rules that always apply to this type
var result = new Validator<T>().Validate((T)this);
// throw error if any violations were detected
if (result.HasViolations)
throw new RulesException(result.Errors);
}
#endregion
}
最后,正如你所看到的,我的验证抛出了一个RulesException。这个类是所有错误的包装。
[Serializable]
public class RulesException : Exception
{
public IEnumerable<ErrorInfo> Errors { get; private set; }
public RulesException(IEnumerable<ErrorInfo> errors)
{
Errors = errors != null ? errors : new List<ErrorInfo>();
}
public RulesException(string propertyName, string errorMessage) :
this(propertyName, errorMessage, null)
{
}
public RulesException(string propertyName, string errorMessage, object onObject) :
this (new ErrorInfo[] { new ErrorInfo(propertyName, errorMessage, onObject) })
{
}
}
因此,随着中说,我在我的控制器的验证看起来更像这个
public ActionResult MyAction()
{
try
{
//call validation here
}
catch (RulesException ex)
{
ModelState.AddModelStateErrors(ex);
}
return View();
}
ModelState.AddModelStateErrors(除息);是我写的一个扩展方法。这很简单。
public static void AddModelStateErrors(this System.Web.Mvc.ModelStateDictionary modelState, RulesException exception)
{
foreach (ErrorInfo info in exception.Errors)
{
modelState.AddModelError(info.PropertyName, info.ErrorMessage);
}
}
这样,我仍然可以使用DI为我服务/存储库,并让我的时候模型是无效的他们抛出了一个错误。然后,我让前端(无论是MVC应用程序,Web服务还是Windows应用程序)决定如何处理这些错误。我觉得注入MVC控制器/模型/视图状态返回到模型/服务/存储库/等是违反层之间的基本分离。
您退房: http://stackoverflow.com/questions/2077055/ioc-on-ivalidationdictionary-with-castle-windsor – bzarah 2010-10-06 15:56:28
这是一个非常类似的问题:在我的情况下,我甚至不尝试实例化验证器 - 我希望容器解决它。无论如何,你链接的问题对我来说没有任何答案。我会让这个立场,并希望有一些额外的见解。 – user403830 2010-10-06 16:23:11
我希望有一些方法来静态获取当前的ControllerContext,就像你可以通过HttpContext.Current获取当前的HttpContext一样。不幸的是,我找不到一个。另一个想法是在IProductValidator上有一个额外的方法,它会接受一个“ModelStateWrapper”,并将验证错误复制到那里。不如依赖注入好,但它应该很容易工作。 – PatrickSteele 2010-10-07 13:13:57