简单的ASP.Net MVC 1.0验证

时间:2010-04-14 17:35:34

标签: c# asp.net-mvc validation

在我们正在开发的当前项目上,我们还没有升级到MVC 2.0,所以我正在使用1.0中提供的工具实现一些简单的验证。

我正在寻找有关我这样做的反馈。

我有一个代表用户个人资料的模型。在该模型中,我有一个方法可以验证所有字段等。我想要做的是将控制器传递给验证方法,以便模型可以在控制器中设置模型验证属性。目标是将控制器的验证转化为模型。

这是一个简单的例子

public FooController : Controller
{
     public ActionResult Edit(User user)
     {
          user.ValidateModel(this);

          if (ModelState.IsValid)
               .......
               .......
      }
}

我的模型验证签名就像

public void ValidateModel(Controller currentState)

您可以看到哪些问题?我可以出去吃午餐吗?

2 个答案:

答案 0 :(得分:1)

我可以通过这种方法看到的问题是您的验证逻辑耦合到控制器。实际上验证器不需要控制器,只需要IDictionary<string, ModelState>来设置错误。

我建议您查看fluent validation library,它允许您将验证逻辑与控制器完全分离。它使用模型绑定器,它可以访问控制器以设置错误。

因此,您的操作代码将如下所示:

public FooController : Controller
{
     public ActionResult Edit(User user)
     {
         if (ModelState.IsValid)
         {

         }
         return View();
     }
}

在绑定期间添加模型错误。 Here's a nice article演示了此库与ASP.NET MVC的集成。 Unit testing您的验证逻辑也非常简单易读。

答案 1 :(得分:0)

对于MVC 1.0项目,我们执行以下操作:

/* In model class */

public void Validate(string dealerId)
{
    ExceptionList exceptions = new ExceptionList();

    if (String.IsNullOrEmpty(this.UserName))
    {
        exceptions.Exceptions.Add(new InvalidFieldException("Error message", "ContractType"));
    }

    ... other validations ...

    if (exceptions.Exceptions.Count > 0)
    {
        throw exceptions;
    }
}


/* In controller */

public virtual ActionResult UpdateProfile(User user)
{

    try
    {
        user.Validate();
    }
    catch (ExceptionList ex)
    {
        ex.CopyToModelState(ModelState);
    }
}


/* Custom types (ExceptionList / InvalidFieldException) */

[Serializable]
public class ExceptionList : Exception
{
    private List<Exception> exceptions;
    public List<Exception> Exceptions
    {
        get { return exceptions; }
        set { exceptions = value; }
    }

    public ExceptionList() { Init(); }
    public ExceptionList(string message) : base(message) { Init(); }
    public ExceptionList(string message,
        System.Exception inner)
        : base(message, inner) { Init(); }
    protected ExceptionList(
        System.Runtime.Serialization.SerializationInfo info,
        System.Runtime.Serialization.StreamingContext context)
        : base(info, context) { Init(); }


    private void Init()
    {
        Exceptions = new List<Exception>();
    }
}

[Serializable]
public class InvalidFieldException : Exception
{
    private string fieldName;
    public string FieldName
    {
        get
        {
            return fieldName;
        }
        set
        {
            fieldName = value;
        }
    }

    private string fieldId;
    public string FieldId
    {
        get
        {
            return fieldId;
        }
        set
        {
            fieldId = value;
        }
    }

    public InvalidFieldException() { }
    public InvalidFieldException(string message) : base(message) { }
    public InvalidFieldException(string message, string fieldName)
        : base(message)
    {
        this.fieldName = fieldName;
    }
    public InvalidFieldException(string message, string fieldName, string fieldId)
        : base(message)
    {
        this.fieldName = fieldName;
        this.fieldId = fieldId;
    }
    public InvalidFieldException(string message, System.Exception inner)
        : base(message, inner) { }
    public InvalidFieldException(string message, string fieldName,
        System.Exception inner)
        : base(message, inner)
    {
        this.fieldName = fieldName;
    }
    public InvalidFieldException(string message, string fieldName, string fieldId,
         System.Exception inner)
        : base(message, inner)
    {
        this.fieldName = fieldName;
        this.fieldId = fieldId;
    }


    protected InvalidFieldException(
        System.Runtime.Serialization.SerializationInfo info,
        System.Runtime.Serialization.StreamingContext context)
        : base(info, context) { }
}


/* Extension method (to copy ExceptionList exceptions to ModelState) */

/// <summary>
/// Copies an ExceptionList to ModelState for MVC
/// </summary>
/// <param name="exList">List of exceptions</param>
/// <param name="modelState">Model state to populate</param>
/// <param name="collection">Form collection of data posted to the action</param>
/// <param name="prefix">Prefix used in view (if any)</param>
/// <param name="isCollection">Indicates whether a collection of objects are being returned from the view (requires prefix)</param>
[CLSCompliant(false)]
public static void CopyToModelState(this ExceptionList exList, ModelStateDictionary modelState, FormCollection collection, string prefix, bool isCollection)
{
    foreach (InvalidFieldException ex in exList.Exceptions)
        if (String.IsNullOrEmpty(prefix))
        {
            modelState.AddModelError(ex.FieldName, ex.Message);
            modelState.SetModelValue(ex.FieldName, collection.ToValueProvider()[ex.FieldName]);
        }
        else
        {
            if (isCollection)
            {
                modelState.AddModelError(prefix + "[" + ex.FieldId + "]." + ex.FieldName, ex.Message);
                modelState.SetModelValue(prefix + "[" + ex.FieldId + "]." + ex.FieldName, collection.ToValueProvider()[ex.FieldName]);
            }
            else
            {
                modelState.AddModelError(prefix + "." + ex.FieldName, ex.Message);
                modelState.SetModelValue(prefix + "." + ex.FieldName, collection.ToValueProvider()[ex.FieldName]);
            }
        }
}

    /// <summary>
    /// Copies an ExceptionList to ModelState for MVC
    /// </summary>
    /// <param name="exList">List of exceptions</param>
    /// <param name="modelState">Model state to populate</param>
    [CLSCompliant(false)]
    public static void CopyToModelState(this ExceptionList exList, ModelStateDictionary modelState)
    {
        CopyToModelState(exList, modelState, null, false);
    }

    /// <summary>
    /// Copies an ExceptionList to ModelState for MVC
    /// </summary>
    /// <param name="exList">List of exceptions</param>
    /// <param name="modelState">Model state to populate</param>
    /// <param name="collection">Form collection of data posted to the action</param>
    [CLSCompliant(false)]
    public static void CopyToModelState(this ExceptionList exList, ModelStateDictionary modelState, FormCollection collection)
    {
        CopyToModelState(exList, modelState, collection, null, false);
    }

基本上,我们只是将一组异常抛回控制器并让控制器将它们添加到ModelState。非常简单和模块化。