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



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

这是我的业务对象:

[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函数save:

$(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+knocket)。在我的情况下,我应该做些什么来进行服务器端验证。请帮帮我。谢谢你的时间和努力!

简短回答:

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

所以你的控制器动作:

public ActionResult SaveFranchise(string franchiseInfoViewModel)

应该改成这样的东西:

public ActionResult Create(FranchiseInfo franchiseInfo)

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

详细答案:

我首先建议您使用ASP.NET MVC框架提供的模型验证,包括用于服务器端验证的模型绑定、模型状态和数据注释,以及用于客户端验证的不引人注目的javascript。这样做将为您提供一种更DRY的实现方式,并具有明确的关注点分离(SoC)。

要做到这一点,我建议您首先查看ASP.NET MVC中的模型绑定。

如"ASP.NET MVC模型绑定的特性和弱点"中所述:

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

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

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.NETMVC使得使用Html.BeginForm为模型生成表单变得非常简单——这里展示了它的示例用法。

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

如本例所述,.NET的System.ComponentModel.DataAnnotations命名空间…

提供了一组内置的验证属性,您可以将这些属性以声明方式应用于任何类或属性。(…)验证属性指定要在应用它们的模型属性上强制执行的行为。

可用的注释之一是Required属性,它定义了特定模型属性必须具有值。还有其他几个属性,如RangeMaxLengthRegularExpression等。其中一些属性的示例使用如下:

public 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; }
}

(示例借用自:http://www.asp.net/mvc/tutorials/getting-started-with-aspnet-mvc3/cs/adding-validation-to-the-model)

用数据注释填充模型可以让您在提交给定表单时很容易地检查模型是否有效,并且您要在给定操作中检查所提供模型的有效性-ModelState.IsValid在这里被证明是有用的。

如本文所述:

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

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

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

正如你可能已经猜到的,我最好的经验与ASP。NET MVC3在模型验证方面使用了数据注释和内置的支持,通过ModelState.IsValid进行服务器端验证,并通过不引人注目的JavaScript进行客户端验证。

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

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

  • 首先,SoC确实很容易实现,因为模型验证逻辑只定义在一个地方,那就是它所属的模型中
  • 其次,您可以在视图中获得一个更DRY的实现(避免重复的逻辑,获得更易于维护的代码),并让框架为您承担重任

如何在ASP中使用不引人注目的客户端验证的示例。NET MVC3可以在这里找到。

然而,有时使用注释可能看起来不那么简单——例如,当您想要验证信用卡和文件扩展名等属性时。在这些情况下,其中对逻辑的需要需要除了基本注释之外的替代方案,我倾向于使用数据注释扩展(除非我可以将我的应用程序定位为.NET 4.5,例如,它添加了一系列更多的属性,如FileExtensionAttribute),因为它们提供了一系列开箱即用的优秀注释扩展(MVC3有一个数据注释扩展nuget包,所以设置和开始使用非常简单)。

在特殊情况下,您可能拥有一个取决于数据库状态的属性,例如,如果您想在用户填写用户注册表时检查用户名是否已经存在。NET MVC3远程验证注释是您的朋友。正如MSDN的这篇文章所说:

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

还有ASP中远程验证的好处。NET MVC3,它也使用数据注释来表达(如本博客文章和MSDN文章中所示)。

总之,使用这些框架功能(imo)确实为您提供了一系列重要的工具,可以或多或少地以ASP中的"正确方式"覆盖任何类型的模型验证。NET MVC3。

最新更新