使用带有kendo + knockout的Ajax Asp Mvc3提交服务器验证时不会触发

时间:2012-08-31 19:03:15

标签: ajax asp.net-mvc-3 knockout.js fluentvalidation

我有Asp Mvc3应用程序。在我看来,我正在使用kendoui + knockoutjs。我正在使用kendo验证器处理客户端验证。我是asp mvc3的新手,我不能让我的服务器端验证工作。

这是我的业务对象:

[Validator(typeof(FranchiseInfoValidator))]
    public class FranchiseInfo
    {
        public string FullName { get; set; }
        public string ShortName { get; set; }
    }
}

我正在使用FluentValidation。这是我的验证规则的实现:

public class FranchiseInfoValidator : AbstractValidator<FranchiseInfo>
    {
        public FranchiseInfoValidator()
        {
            RuleFor(franchiseInfo => franchiseInfo.FullName).NotEmpty();
            RuleFor(franchiseInfo => franchiseInfo.ShortName).NotEmpty();
        }
    }

这是我的观点模型:

public class FranchiseInfoViewModel
    {
        public string FullName { get; set; }
        public string ShortName { get; set; }
    }

这是我对FranchiseInfoViewModel强烈输入的视图:

@model MvcApplication2.Models.FranchiseInfoViewModel

<script src="../../Scripts/Details.js" type="text/javascript"></script>

<form id="franchiseForm" action="" style="font-family: Trebuchet MS, Verdana, Helvetica, Sans-Serif;"> 
     <table>
            <tr>
                <td><label for="fullName">FullName:</label></td>
                <td><input id="fullName" data-bind= "value: FullName" /></td>
            </tr>
            <tr>
                <td><label for="shortName">ShortName:</label></td>
                <td><input id="shortName" data-bind= "value: shortName" /></td>
            </tr>
    </table>
    <button id="submit" class="k-button" data-bind="click: save" form="franchiseForm">Save Franchise</button>
</form>

提交表单我调用javascript函数保存:

$(function () {

    save = function () {

        // some logic

        $.ajax({
            url: "/franchise/SaveFranchise",
            type: "POST",
            data: { franchiseInfoViewModel: jsonData },               
            dataType: 'json',
            success: function (data, textStatus, xhr) {
                window.location.href = data.redirectToUrl;
            }
        });
    }
});

在保存时,我以json格式提交数据并将数据发送到SaveFranchise控制器:

public ActionResult SaveFranchise(string franchiseInfoViewModel)
        {
            var franchiseInfoVM = JsonConvert.DeserializeObject<FranchiseInfoViewModel>(franchiseInfoViewModel);

            if (!ModelState.IsValid)
            { 
                // do some action
            }

            return View();
        }

我想要完成的是(!ModelState.IsValid)返回视图并显示流畅的验证错误消息。出于某种原因,在我的情况下,ModelState.IsValid始终为true。

如上所述,我是Asp Mvc 3的新手。从我读过的文章中,示例是将表单提交到服务器(没有javascript),其中有绑定,服务器验证消息返回到视图。但是该视图是使用Razor实现的,客户端验证是通过jquery完成的。

在我看来,我正在使用带有数据绑定的javascript视图模型(kendoui + knockout)。在我的情况下,我该怎么做才能进行服务器端验证。请帮我。谢谢你的时间和精力!

1 个答案:

答案 0 :(得分:5)

简答:

您应该在控制器操作中使用模型绑定 - 这样做可以让您使用ModelState.IsValid

所以你的控制器动作:

public ActionResult SaveFranchise(string franchiseInfoViewModel)

..应改为:

public ActionResult Create(FranchiseInfo franchiseInfo)

确保以一种格式发布表单,使模型绑定器能够实例化FranchiseInfo模型的实例。您可以使用JSON来执行此操作,但如果您只是在表单上使用标准action属性发布表单,我认为会更好(也更简单)。

详细解答:

我建议的第一件事是你使用ASP.NET MVC框架提供的模型验证,包括服务器端验证的模型绑定,模型状态和数据注释,以及客户端的不显眼的javascript验证。这样做会为您提供更多DRY实施方式,并使用明确Separation of Concerns (SoC)

要实现这一目标 - 我建议您首先开始研究ASP.NET MVC中的模型绑定。

"The Features and Foibles of ASP.NET MVC Model Binding"中所述:

  

通过模型绑定,控制器操作可以专注于提供业务价值,避免浪费时间进行平凡的请求映射和解析。

为了看到这一点,这个MSDN article对模型绑定器有一个很好的定义:

  

MVC中的模型绑定器提供了一种将发布的表单值映射到.NET Framework类型的简单方法,并将该类型作为参数传递给操作方法。 (...)模型绑定器类似于类型转换器,因为它们可以将HTTP请求转换为传递给操作方法的对象。

有了这个抽象,你很快就会看到签名:

public ActionResult SaveFranchise(string franchiseInfoViewModel)

..可以改为:

public ActionResult Create(FranchiseInfo franchiseInfo)

...此时,事情已经开始变得更加干净了,因为像自定义数据映射这样的代码:

var franchiseInfoVM = JsonConvert.DeserializeObject<FranchiseInfoViewModel>(franchiseInfoViewModel);

...可以删除。

通常,您不需要将表单序列化为JSON并发布 - 而是应该利用MVC中的模型绑定并以标准方式提交表单数据(通过使用action属性表单元素 - 好吧,模型绑定器能够基于JSON绑定对象,但我认为你明白我的意思..)。实际上,ASP.NET MVC使用Html.BeginForm为模型生成表单非常简单 - 使用它的示例是shown here

所以,现在当您重构视图以使用发布其数据的表单而不将表单数据序列化为JSON时,您应该看看MVC3中的数据注释。

如上所述in this example,.NET的System.ComponentModel.DataAnnotations命名空间......

  

提供了一组内置的验证属性,您可以声明性地将这些属性应用于任何类或属性。 (...)验证属性指定要对其应用的模型属性强制执行的行为。

其中一个可用的注释是Required属性 - 它定义了特定的模型属性必须具有值。有Range,例如MaxLengthRegularExpressionpublic class Movie { public int ID { get; set; } [Required(ErrorMessage = "Title is required")] public string Title { get; set; } [Required(ErrorMessage = "Date is required")] public DateTime ReleaseDate { get; set; } [Required(ErrorMessage = "Genre must be specified")] public string Genre { get; set; } [Required(ErrorMessage = "Price Required")] [Range(1, 100, ErrorMessage = "Price must be between $1 and $100")] public decimal Price { get; set; } [StringLength(5)] public string Rating { get; set; } } 等。某些属性的示例用法可能如下所示:

ModelState.IsValid

(该例子来自:several other attributes

使用数据注释填充模型使您可以非常轻松地检查模型是否有效,在提交给定表单时,以及检查所提供模型的有效性。给定的行动 - 它在ModelState.IsValid证明是有用的。

如上所述http://www.asp.net/mvc/tutorials/getting-started-with-aspnet-mvc3/cs/adding-validation-to-the-model

  

(...)第二个Create方法调用ModelState.IsValid来检查电影是否有任何验证错误。调用此方法将评估已应用于对象的任何验证属性。

所以在这一点上,你应该能够看到使用数据注释来声明模型上的约束/所需行为将允许你有一个简单的实现,其中逻辑在模型中定义,并且可以使用{轻松检查{1}}。

为了扩展这一点,我可以告诉你一些我在ASP.NET MVC3中在服务器和客户端进行模型验证的经验。

正如您可能已经猜到的那样,在模型验证方面,我对ASP.NET MVC3的最佳体验是使用数据注释和通过ModelState.IsValid和客户端验证对服务器端验证的内置支持通过不引人注目的JavaScript。

对于数据注释,我使用内置注释和in this post项目提供的扩展的组合。

使用ASP.NET MVC3支持不引人注目的客户端验证有几个好处。

  • 首先,data annotation extension非常容易实现,因为模型验证逻辑只定义在一个地方 - 而且在模型所在的位置。
  • 其次,您可以在视图中获得更多SoC实现(避免重复逻辑并获得更易于维护的代码),并让框架为您做繁重的工作。

可以找到如何在ASP.NET MVC3中使用不显眼的客户端验证的示例DRY

但是,有时候使用注释可能看起来不那么直接 - 例如,当你想要验证信用卡和文件扩展名等属性时。在需要逻辑调用基本注释以外的替代方案的情况下,我倾向于使用here(除非我可以将我的.NET 4.5应用程序作为目标,例如data annotation extensions,例如FileExtensionAttribute)因为它们提供了一系列优秀的注释扩展,只需开箱即用(has added a series of more attributes - 所以设置并开始使用非常简单。)

还有一些特殊情况,您可能拥有一个取决于数据库状态的属性 - 例如如果要在用户填写用户注册表单时检查用户名是否已存在。在这种情况下,ASP.NET MVC3远程验证注释是您的朋友。正如exist a data annotation extensions nuget package for MVC3

  

ASP.NET MVC 3提供了一种机制,可以进行远程服务器调用,以便验证表单字段,而无需将整个表单发布到服务器。当您有一个无法在客户端验证的字段时,这很有用,因此在提交表单时可能无法通过验证。

在ASP.NET MVC3中进行远程验证的好处是,它也使用数据注释表示(如MSDN article states和此this blogpost中所示)。

总而言之 - 使用这些框架功能(imo)确实为您提供了一系列严谨的工具来覆盖或多或少的任何类型的模型验证&#34;正确的方式&#34;在ASP.NET MVC3中。