我假設你想讓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