0

我在做什么:我有 3 个组合框。前 2 个框中的选择决定了第 3 个框中的列表。每当在前 2 个框中的任何一个中进行选择时,我都会运行一些 jQuery 进行 $.ajax 调用以获取第 3 个框的列表。第三个框是我的“项目描述”框。

问题: jquery ajax 调用有效。当我选择前 2 个框中的值时,项目描述被加载到第 3 个框中。但是,当我尝试提交表单时,ModelState.IsValid = false 并且 ModelState 错误消息显示“需要项目描述”。

这是来自我的模型的元数据:

[Required(ErrorMessage = "Item Description is required.")]
public int ItemDescriptionID { get; set; }

我不希望用户能够在不选择描述的情况下提交表单。我可以在提交后进行验证,但我希望 MVC 会进行验证。

这是我正在使用的 JavaScript...

function getModels() {
    catId = $('#ItemModel_ItemCategoryID').val();
    manuId = $('#ItemModel_ItemManufacturerID').val();

    // remove all of the current options from the list
    $('#ItemDescriptionID').empty();

    // send request for model list based on category and manufacturer
    var jqxhr = $.ajax({
        url: '/Threshold/GetModels',
        type: 'POST',
        data: '{ CategoryID: ' + catId.toString() + ', ManufacturerID: ' + manuId.toString() + ' }',
        contentType: 'application/json',
        dataType: 'json',
        cache: false,
        async: true
    });

    // received list of models...
    jqxhr.done(function (data) {
        if (data == null) return;

        try {
            var ddl = $('#ItemDescriptionID');

            // add each item to DDL
            $.each(data, function (index, value) {
                ddl.append($('<option/>', {value: data[index].ItemDescriptionID}).html(data[index].ItemDescription))
            });
        }
        catch (result) {
            alert("Done, but with errors! " + result.responseText);
        }
    });

    // failed to retrieve data
    jqxhr.error(function (result) {
        alert("Error! Failed to retrieve models! " + result.responseText);
    });
}

那么我做错了什么?如果我删除必需的元数据标签,表单将提交。此外,在表单提交后,我可以从下拉列表中获取 ID,一切正常。问题出在模型状态/验证上。

编辑:

这是我的描述框剃刀...

@Html.DropDownListFor(m => m.ItemDescriptionID, new SelectList(new List<SelectListItem>()) )
@Html.ValidationMessageFor(m => m.ItemDescriptionID)
4

1 回答 1

1

如果我正确理解您的问题,您会发现即使用户没有从您的下拉列表中选择任何有效的内容,他们仍然可以发布到服务器。当用户没有选择任何东西 Mo​​delState.IsValid 为 false 并且您收到正确的错误消息时,模型似乎正在正确验证。但是,如果尚未进行选择,您希望完全避免发布数据。

这里的问题是 ModelState 和所有 MVC 验证实际上是在服务器端完成的。因此,为了让您的应用程序根据模型的数据注释检测到用户的选择无效,确实需要提交表单。

为了阻止用户发帖,您想要的是客户端验证,它不是 MVC 模型验证的一部分,但 MVC 4 已经内置了对它的支持。

内置 MVC 4 客户端验证

为了使用内置的 MVC 4 jQuery 验证启用客户​​端验证,请执行以下操作。

  • 启用 MVC 客户端验证支持

    确保“Unobtrusive JavaScript”(将输出所需的 HTML 属性)和“客户端验证”(将连接 javascript)。

    在 web.config 中(对于整个站点)

    <appSettings>
        <add key="ClientValidationEnabled" value="true"/>
        <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
    </appSettings>
    

    或在代码中 - global.asax.cs、视图或控制器,具体取决于您想要的范围

    HtmlHelper.ClientValidationEnabled = true;
    HtmlHelper.UnobtrusiveJavaScriptEnabled = true;
    
  • 在视图中包含所需的脚本

    MVC 4 准备了一个包,包括 jQuery 验证和不显眼的验证脚本。这必须在 jQuery 包之后添加。

    @Scripts.Render("~/bundles/jqueryval")
    

始终检查 ModelState.IsValid

即使您启用了客户端验证,您也必须在执行任何操作之前对发布的数据执行服务器端验证。无论用户提交的数据是有效还是无效,您的 ActionMethod 仍将执行......因此,您需要在对已提交的数据执行操作之前检查 IsValid。

      [HttpPost]
      public ActionResult ActionMethodName(ModelClass modelParameterName)
      {
       //exit directly on invalid data
       if(!ModelState.IsValid) return View(modelParameterName);
       //okay to save data etc...
       ...
       ...
       //return whatever makes sense for your scenario
       return View(modelParameterName); 
      }

其他选项

您还可以手动使用 jQuery 验证或其他第三方 javascript 验证库。

自定义 javascript 表单验证也是一个选项 - 从表单的提交事件调用的函数返回 false。

HTML5 支持客户端验证属性(在您的情况下为“必需”),尽管并非所有浏览器都实现它。

如果您自己执行验证而不使用 MVC 4 不显眼的脚本,您应该关闭内置功能以避免冲突并减少返回的 HTML 的大小。

    <appSettings>
        <add key="ClientValidationEnabled" value="false"/>
        <add key="UnobtrusiveJavaScriptEnabled" value="false"/>
    </appSettings>

或者在您可以控制您希望它应用到的范围的代码中。

    HtmlHelper.ClientValidationEnabled = false;
    HtmlHelper.UnobtrusiveJavaScriptEnabled = false;
于 2013-11-01T15:56:56.367 回答