将ASP.NET MVC Controller属性注入服务层依赖项?
我正在使用类似于ASP.NET MVC教程中的方法 ,您将控制器的ModelState
集合中的包装器传递给validation类,以便控制器可以访问错误信息。
这是一个熟练的例子:
interface IProductValidator { void Validate(Product item); } class ProductValidator { // constructor public ProductValidator(ModelStateWrapper validationDictionary) { } } interface IProductService { void AddProduct(); } public class ProductService : IProductService { // constructor public ProductService(IProductValidator validator) { } }
使用Castle Windsor容器进行IoC / DI,如何创建IProductService
? 通常,我会:
MvcApplication.IocContainer.Resolve()
但是这不能将Controller的ModelState
属性的值注入到ProductValidator的构造函数中。 我可以使用构造函数参数来连接它,但这看起来真的很难看。
我假设您希望传递的模型状态自动将任何错误注入您的模型中? 恕我直言,ModelState应该保持原样,并将validation错误带到它。 以下是我如何处理错误的例子。 我不是说这是最好的方式或唯一的方法,但它是一种方法,您的validation层不必知道谁或什么消耗validation错误。
首先,在我的poco中,我使用System.ComponentModel.DataAnnotations
作为validation规则。 例如,这是我的帐户类。
public class Account : CoreObjectBase { public virtual int AccountId { get; set; } [Required(ErrorMessage = "Email address is required.")] public virtual string EmailAddress { get; set; } [Required(ErrorMessage = "A password is required.")] public virtual string Password { get; set; } }
因为我希望能够自己启动validation(在MVC之外自己做),我必须实现自己的validation器。
public class Validator where T : CoreObjectBase { public ValidationResponse Validate(T entity) { var validationResults = new List(); 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 Violations { get; private set; } public IList Errors { get; private set; } public bool HasViolations { get { return Violations.Count > 0; } } public ValidationResponse(params ValidationResult[] violations) { Violations = new List(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; } }
为了将这个validation包装好我的poco类,我inheritance了一个基类。 对于validation,使其成为通用的inheritance子必须告诉基类的类型。 它感觉循环,但它的工作原理。
[Serializable] public class CoreObjectBase : IValidatable where T : CoreObjectBase { #region IValidatable Members public virtual bool IsValid { get { // First, check rules that always apply to this type var result = new Validator ().Validate((T)this); // return false if any violations occurred return !result.HasViolations; } } public virtual ValidationResponse ValidationResults { get { var result = new Validator ().Validate((T)this); return result; } } public virtual void Validate() { // First, check rules that always apply to this type var result = new Validator ().Validate((T)this); // throw error if any violations were detected if (result.HasViolations) throw new RulesException(result.Errors); } #endregion }
最后,正如您所看到的,我的validation会抛出一个RulesException。 此类是所有错误的包装器。
[Serializable] public class RulesException : Exception { public IEnumerable Errors { get; private set; } public RulesException(IEnumerable errors) { Errors = errors != null ? errors : new List (); } 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) } ) { } }
所以,说到这一点,我在控制器中的validation看起来更像是这样
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控制器/模型/视图状态注入模型/ services / repositories / etc是违反了层之间的基本分离。
上述就是C#学习教程:将ASP.NET MVC Controller属性注入服务层依赖项?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/957713.html