6

有很多非常好的帖子和解释如何使用 ASP.NET MVC 实现验证,我更喜欢其中之一:

但是,我真的很喜欢通过 jquery $.ajax 方法调用 ActionMethods。我想使用 $.ajax 的原因之一是因为会通过 $.ajax 调用将很多部分视图动态加载到页面中(甚至是用于创建实体的表单),而我不能只返回视图 -我将丢失所有动态加载的内容。

为了让您更好地了解该问题,我将发布一些简单的代码来解释我希望如何调用控制器操作并在客户端 jquery 代码中处理响应。

控制器ActionMethod:

    public ActionResult CreateCustomer(string name, string accountNumber)
    {
        try
        {
            CustomerService.InsertCustomer(name, accountNumber);

            return Json(new ActionInfo()
            {
                Success = true,
                Message = "Customer Is Successfully Created"
            });

        }
        catch (Exception ex)
        {
            return Json(new ActionInfo()
            {
                Success = false,
                Message = ex.Message
            });
        }
    }

在客户端代码中调用和处理:

$.ajax({
type: "POST",
url: $form.attr('action'),// /MyController/CreateCustomer
data: $form.serialize(),
error: HandleUnespectedError,
dataType: "json",
success: function(response) {

    if (response.Success)
        alert("Success: " + response.Message);
    else
        alert("Error: " + response.Message);
}});

有没有一种好方法可以使其中一些验证框架按我需要的方式工作?我知道我可以在 ActionInfo 中添加验证错误,然后在客户端中处理它,但我相信这已经是我的一个验证的构建。

4

2 回答 2

5

我在使用数据注释属性通过 AJAX 进行验证方面取得了巨大成功。为了检查数据的有效性,您将需要使用控制器的ModelState属性,该属性具有自己的属性,称为IsValid. 我强烈建议您查看官方 ASP.NET MVC 站点的数据注释验证属性教程

首先,您需要修改控制器操作以接受模型对象作为参数,而不是单独的名称和帐号。这将使执行验证(我将在下面演示)变得更加简单。从您的示例中,我最好的猜测是您的模型对象是或将被称为客户。您可能有以下代码来定义模型对象和控制器操作...

// model object
public class Customer
{
  public Int32 Id {get; set;}
  public String Name {get; set;}
  public String AccountNumber {get; set;}
}

// controller
public class CustomerController : Controller
{
  public ActionResult CreateCustomer( [Bind(Exclude = "Id")] Customer customer )
  {
     // controller action code
  }
}


确保您的表单字段的名称与 Customer 对象的属性名称相匹配,以便 ASP.NET MVC 可以自动绑定它们。在这种情况下,“Bind”属性告诉 ASP.NET MVC 在将表单字段绑定到模型属性时忽略 Customer 类的“Id”属性。由于这是一个新客户,我们还没有 Id,所以我们可以放心地将 Id 保留为默认值,并让数据层找出如何最好地生成它。

一旦控制器为动作方法构建了模型对象,就可以通过ModelState.IsValid属性轻松检查其有效性。正如人们所期望的那样,如果模型属性有效,它将返回 true,如果 1 个或多个属性无效,它将返回 false。

从最初的问题来看,该CustomerService.InsertCustomer方法似乎在验证失败时抛出异常。这是完全没有必要的。InsertCustomer 应该只需要执行插入新记录所需的任何数据操作。除非您希望抽象实现特定的异常,例如 SqlException,否则 InsertCustomer 不应该真的需要捕获或抛出任何异常,但很可能只是让任何异常冒泡到控制器(或调用者可能是谁)。

所有这一切的最终结果可能是一个如下所示的控制器操作:

public ActionResult CreateCustomer( [Bind(Exclude = "Id")] Customer customer )
{
  // model is invalid
  if (!ModelState.IsValid)
  {
    return Json(new ActionInfo()
    {
      Success = false,
      Message = "Validation failed" // you will probably want a more robust message :-)
    });
  }

  // service method accepts a Customer object rather than arbitrary strings  
  CustomerService.InsertCustomer(customer);

  return Json(new ActionInfo()
  {
    Success = true,
    Message = "Customer created successfully."
  });

}


如果您想报告意外错误,例如与数据库相关的异常,那么您当然可以在对 InsertCustomer 的调用周围添加一个 try/catch 块,并将显示错误消息所需的结果返回给客户端。

于 2009-10-15T07:02:14.910 回答
2

这是您提出问题一年多之后,但我在我的博客文章中介绍了使用 Ajax 调用的服务器端验证,您可能对此很感兴趣。我看到您将失败的结果作为成功的 HTTP 调用返回。我以不同的方式处理了这个问题(我想它更正确,因为它$.ajax具有响应功能的能力)successerror您的特定示例是一个完美的示例,可以使用我在博客文章中解释的功能来实现。

基本上不是总是返回一个成功的响应(但设置了属性来告诉客户端服务器端处理失败),我宁愿在服务器上抛出一个异常并在客户端上相应地处理它。我正在使用自定义 ModelStateException 类和HandleModelStateException操作过滤器。

于 2010-11-27T11:04:40.780 回答