简体   繁体   English

简单的ASP.Net MVC 1.0验证

[英]Simple ASP.Net MVC 1.0 Validation

On the current project we are working on we haven't upgraded to MVC 2.0 yet so I'm working on implementing some simple validation with the tools available in 1.0. 在我们正在开发的当前项目上,我们还没有升级到MVC 2.0,所以我正在使用1.0中提供的工具实现一些简单的验证。

I'm looking for feedback on the way I'm doing this. 我正在寻找有关我这样做的反馈。

I have a model that represents a user profile. 我有一个代表用户个人资料的模型。 Inside that model I have a method that will validate all the fields and such. 在该模型中,我有一个方法可以验证所有字段等。 What I want to do is pass a controller to the validation method so that the model can set the model validation property in the controller. 我想要做的是将控制器传递给验证方法,以便模型可以在控制器中设置模型验证属性。 The goal is to get the validation from the controller into the model. 目标是从控制器进入模型验证。

Here is a quick example 这是一个简单的例子

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

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

And my model validation signature is like 我的模型验证签名就像

public void ValidateModel(Controller currentState)

What issues can you see with this? 你能看到什么问题? Am I way out to lunch on how I want to do this? 我可以出去吃午餐了吗?

The problem I can see with this approach is that your validation logic is coupled to the controller. 我用这种方法可以看到的问题是你的验证逻辑耦合到控制器。 Actually the validator doesn't need the controller but only an IDictionary<string, ModelState> in order to set errors. 实际上验证器不需要控制器,只需要IDictionary<string, ModelState>来设置错误。

I would suggest you looking at the fluent validation library which allows you to completely decouple your validation logic from the controller. 我建议您查看流畅的验证库 ,它允许您将验证逻辑与控制器完全分离。 It uses a model binder in which it has access to the controller in order to set errors. 它使用模型绑定器,它可以访问控制器以设置错误。

So your action code will look like this: 所以你的动作代码将如下所示:

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

         }
         return View();
     }
}

Model errors are added during the binding. 在绑定期间添加模型错误。 Here's a nice article demonstrating the integration of this library with ASP.NET MVC. 这是一篇很好的文章,演示了这个库与ASP.NET MVC的集成。 Unit testing your validation logic is also very easy and readable. 对验证逻辑进行单元测试也非常简单易读。

For MVC 1.0 projects we do the following: 对于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);
    }

Basically, we're just throwing a group of exceptions back to the controller and letting the controller add them to ModelState. 基本上,我们只是将一组异常抛回控制器并让控制器将它们添加到ModelState。 Pretty simple and modular. 非常简单和模块化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM