注射ASP.NET MVC控制器属性为服务层依赖? [英] Inject ASP.NET MVC Controller property into service layer dependency?

查看:77
本文介绍了注射ASP.NET MVC控制器属性为服务层依赖?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用一个类似于在这个 ASP.NET的方法MVC教程,你绕过控制器的的ModelState 集合包装成一个验证类,以便控制器可以访问错误的信息。

I am using an approach similar to the one in this ASP.NET MVC tutorial where you pass a wrapper around a controller's ModelState collection into a validation class so that the controller can access error information.

下面是一个虚构的例子:

Here is a cooked up example:

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) { }
}

使用温莎城堡为IOC / DI容器的,我怎么创建 IProductService ?通常情况下,我会:

Using the Castle Windsor container for IoC/DI, how do I create the IProductService? Typically, I would have:

MvcApplication.IocContainer.Resolve<IProductService>()

但是这不能够控制器的的ModelState 属性的值注入到构造ProductValidator。我可能这样组装起来使用构造函数的参数,但似乎真难看。

but this isn't able to inject the value of the Controller's ModelState property into the constructor for ProductValidator. I could possibly wire this up using constructor parameters, but that seems really ugly.

推荐答案

我假设你想传递给汽车的ModelState中注入任何错误到模型?恕我直言,ModelState中应该保持它在哪里,你把验证错误吧。下面是我如何处理错误作为一个例子。我并不是说这是最好的方法还是唯一的方法,但它是你的验证层不必有谁或什么消费验证错误知识的一种方式。

I'm assuming you want the modelstate passed in to auto inject any errors into your model? IMHO, ModelState should stay where it is, and you bring the validation errors to it. Here's how I handle errors as an example. I'm not saying this is the best way or the only way, but it is one way where your validation layer doesn't have to have knowledge of who or what consumes validation errors.

首先,在我的POCO,我使用 System.ComponentModel.DataAnnotations 的验证规则。这里是我的账户类,例如。

First, in my poco, I use System.ComponentModel.DataAnnotations for validation rules. Here is my account class, for example.

public class Account : CoreObjectBase<Account>
{
    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; }
}

由于我希望能够发起验证自己(MVC的做它自己以外的),我必须实现我自己的验证。

Because I want to be able to initiate validation myself (outside of MVC doing it on it's own), I had to implement my own validator.

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回传

Here is the ValidationResult I pass back

[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是我的错误信息,一个非常基本的类

ErrorInfo is a very basic class with information about my error

[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类,我从一个基类继承。为了验证,以使它通用那里继承的孩子告诉基类它的类型。这感觉圆形的,但它的作品。

in order to wrap this validation up all nice and neat with my poco classes, I inherit from a base class. For validation to make it generic where the inherited child has to tell the base class it's type. It feels circular, but it works.

[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。这个类是所有错误的包装。

And finally, as you can see, my validation throws a RulesException. This class is a wrapper for all the errors.

[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) } )
    {

    }
}

因此​​,随着中说,我在我的控制器的验证看起来更像这个

So, with that said, my validation in my controller looks more like this

public ActionResult MyAction()
{
   try
   {
      //call validation here
   }
   catch (RulesException ex)
   {
      ModelState.AddModelStateErrors(ex);
   }

   return View();
}

ModelState.AddModelStateErrors(除息);是我写的一个扩展方法。这是很简单的。

ModelState.AddModelStateErrors(ex); is an extension method that I wrote. it is very simple.

    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应用程序 - 决定如何处理这些错误做

This way, I can still use DI for my services/repositories, and let them throw up an error when my model is invalid. Then I let the front end - whether that is an MVC app, web service, or windows app - decide what to do with those errors.

我觉得注射MVC控制器/模型/视图状态恢复到模型/服务/资源库/等违反层与层之间的基本分离。

I feel that injecting MVC controller/model/view state back into the model/services/repositories/etc is a violation of the basic separation between the layers.

这篇关于注射ASP.NET MVC控制器属性为服务层依赖?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆