【问题标题】:Remote Validation for LIST of MODELs模型列表的远程验证
【发布时间】:2014-12-16 20:35:54
【问题描述】:

我使用了以下教程: http://msdn.microsoft.com/en-us/library/gg508808%28VS.98%29.aspx

一切似乎都很好,但就我而言,字符串用户名总是返回 null。经过大量研究,我发现每个人都发现了 BIND 前缀。在许多情况下这会很好,但不是这种情况。我应该注意所有属性和名称都排成一行,但是在我的 for 循环中,EditorFor 创建了一个 [i].Username 字段,它不会映射到任何模型属性。

问题:我想我想将 [i].Username 映射到 Username,其中 i 是从 0 到无穷大的任意数字,因此当它获取时,该值会正确传递给 Action。我该怎么做呢?如果这是错误的,我该如何验证表中的特定行?

@for (var i = 0; i < Model.Count; i++)
{
  BLAH BLAH BLAH CODE FOR BUILDING TABLE ROWS
  <td>
     @Html.EditorFor(modelItem => Model[i].Username)
  </td>                               
}

由于我在技术上可以拥有数百甚至数千条记录,所以我宁愿没有为所有 1000 条记录设置绑定前缀。我是否从根本上遗漏了什么?我是 ASP.NET MVC 的新手,并且习惯于 WebForms,所以我觉得有时我在混合概念并混搭一些完全错误的东西。

编辑: 我通过执行以下操作来修复它,但不确定这是否是最好的主意。我将参数设置为等于没有 [i] 前缀的 FieldName,但仍然检索具有 [i] 前缀的元素。 Javascript 不是我的强项,所以如果它很糟糕,请告诉我。

adapters.add("remote", ["url", "type", "additionalfields"], function (options) {
    var value = {
        url: options.params.url,
        type: options.params.type || "GET",
        data: {}
    },
        prefix = getModelPrefix(options.element.name);

    $.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) {

        var paramName = fieldName.substr(fieldName.lastIndexOf(".") + 1);

        var actualFieldName = appendModelPrefix(fieldName, prefix)
        value.data[paramName] = function () {
            return $(options.form).find(":input").filter("[name='" + escapeAttributeValue(actualFieldName) + "']").val();
        };
    });

    setValidationValues(options, "remote", value);
});

【问题讨论】:

  • 你肯定在这里遗漏了一些东西。整个集合只有一个前缀。您不需要为其中的每个项目设置一个前缀。但是,我什至不明白你的问题是什么。您需要提供更多代码并尝试更清楚地解释您的问题。

标签: c# asp.net asp.net-mvc model-binding remote-validation


【解决方案1】:

您尚未发布模型或控制器的代码,但假设您已将 RemoteAttribute 应用于属性 Username,例如

public class MyModel
{
  [Remote("IsValidUserName", "Person")]
  public string Username { get; set; }
}

使用PersonController中的方法

public JsonResult IsValidUserName(string Username)
{
  ....
}

还有风景

@model List<Person>
...
@for (var i = 0; i < Model.Count; i++)
{
  @Html.EditorFor(m => m[i].Username)                           
}

这样会生成html比如

<input name="[0].UserName" ... />
<input name="[1].UserName" ... />

不幸的是,jquery-validate 中的 remote 方法回发了元素的名称和值,因此 ajax 调用看起来像

$.ajax({
  url: '/Person/IsValidUserName',
  data: { [0].UserName: 'someone@somewhere.com' },
  ...

不会绑定的。

我已将此报告为issue at Codeplex,并提供了可能的解决方案。同时可以修改jquery-validate.js文件中的remote方法如下

remote: function(value, element, param) {
  ....
  var data = {};
  // data[element.name] = value;
  data[element.name.substr(element.name.lastIndexOf(".") + 1)] = value; // add this

这将去除前缀,以便发布的数据是

 data: { UserName: 'someone@somewhere.com' },

并将正确绑定到方法。

【讨论】:

  • 做到了。谢谢老兄。
  • 额外的字段呢?我需要为他们更改其他内容吗?
  • 不确定 - 我还没有测试过(目前没有时间)。如果您尝试它并且存在问题,那么建议您对该问题添加评论(请参阅答案中的链接),以便它得到解决。有趣的是,我最近报告了另一个关于 [Remote] 的附加字段的错误,原因是 this question
  • 我编辑了我的帖子以包含我的修复。子字符串不是我的首选方法。你看起来很聪明,推荐?否则,我很乐意评论您从原始答案提交的链接。
  • 我认为最好将 cmets 添加到 CodePlex 问题并让专家解决它(已分配,因此希望他们能尽快提出解决方案)
【解决方案2】:

假设代码格式如下:
查看:

@for(var i = 0; i<Model.Count; i++) {
    <div class="row">
        @Html.EditorFor(modelItem => Model[i].Username)
    </div>
}

<style>
    .valid{
        background: lime;
    }
</style>
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}

型号:

public class MyModel {
    [Remote("IsValidUserName", "Validation", HttpMethod = "POST")]
    public string Username { get; set; }
}

可以使用自动模型绑定来绑定到远程验证。如果您为此使用列表或数组,则绑定会失败,而 Dictionary 可以捕获此错误。
但是请注意,字典中的 Key 将与视图中的 id 一致(例如 [5].Username 将映射到 {Key: 5, Value: MyModel{Username:...}})并且不会默认为 0,因此使用 Linq 查询。
控制器:

[HttpPost]
public JsonResult IsValidUserName(Dictionary<int,MyModel> Users) {
    return Json(Users.First().Value.Username.Contains("User"));
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-02
    • 1970-01-01
    • 2021-04-27
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多