通过 jquery $.ajax 发布时的 ASP.NET MVC 验证框架?

发布于 2024-08-07 10:43:49 字数 1670 浏览 11 评论 0原文

有很多非常好的帖子和解释如何使用 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 中添加验证错误,然后在客户端中处理它,但我相信这已经是我的一次验证的构建。

There is a plenty of very good post and explanations how to implement validation with ASP.NET MVC, and I prefer one of these:

However, I really like to call ActionMethods via jquery $.ajax method. One of the reasons why I want to use $.ajax is because there will be a lot of partial views loaded into the page dynamically (even the form for entity creation) via $.ajax calls and I can't just return the view - I'll lose all dynamically loaded content.

To give you a better view on the problem, I'll post some simple code to explain how would I like to call controllers actions and handle responses in client, jquery code.

The controllers 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
            });
        }
    }

Calling and handling in client code:

$.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);
}});

Is there a good way to make some of these validation frameworks to work the way I need? I know that I can add validation errors in ActionInfo, and then handle it in client, but that would be already a building of my one validation, I believe.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

酷到爆炸 2024-08-14 10:43:49

我通过 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 块,并返回将错误消息显示回客户端所需的结果。

I have had great success doing validation via AJAX using data annotations attributes. In order to check the validity of your data, you will want to use the controller's ModelState property, which has a property of its own called IsValid. I strongly suggest taking a peek at the data annotations validation attributes tutorial from the official ASP.NET MVC site.

First off, you will want to modify your controller action to accept your model object as a parameter, rather than a separate name and account number. This will make performing the validation, which I will demonstrate below, much simpler. From your example, my best guess is that your model object is, or would be, called Customer. You might have the following code to define the model object and your controller action...

// 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
  }
}

Make sure your form fields are named to match the names of the properties of the Customer object so ASP.NET MVC can automagically bind them. The "Bind" attribute, in this case, is telling ASP.NET MVC to ignore the "Id" property of the Customer class when binding form fields to model properties. Since this is a new customer, we don't have an Id yet, so we can safely leave the Id as whatever the default value is and leave the data layer to figure out how best to generate it.

Once the controller has constructed the model object for the action method, its validity can be easily checked via the ModelState.IsValid property. As one might expect, it will return true if the model properties are valid, or false if 1 or more properties are invalid.

From the original question, it appears that the CustomerService.InsertCustomer method is throwing exceptions when validation fails. This is completely unnecessary. InsertCustomer should only need to perform whatever data operations are necessary for inserting the new record. Unless you wish to abstract implementation specific exceptions, like SqlException, InsertCustomer should not really need to catch or throw any exceptions, but can most likely just let any exceptions bubble up to the controller (or whoever the caller may be).

The end result of all of this, might be a controller action that looks like the following:

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."
  });

}

If you want to report unexpected errors, like database related exceptions, then you can certainly add a try/catch block around the call to InsertCustomer, and return the necessary result for displaying the error message back to the client.

心凉 2024-08-14 10:43:49

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

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

This is more than a year after you've asked your question, but I've covered server side validation with Ajax calls in my blog post that may be of a lot of interest to you. I see that you return failed results as successful HTTP calls. I've handled this differently (I guess it's more correct since $.ajax has the capability of success and error response functionality). And your particular example is a perfect example that could be implemented with the functionality I explain in my blog post.

Basically instead of always returning a successful response (but with properties set to tell the client that server side processing failed) I rather throw an exeception on the server and handle it accordingly on the client. I'm using a custom ModelStateException class along with an HandleModelStateException action filter.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文