2

出于某种原因,每当我尝试远程验证模型中数组内的原始属性时,该属性的值都不会作为参数传递。

例如,当调用我的远程验证方法(UniqueItemNo)时,字符串参数“id”始终为空。如果我要对 CartNumber 而不是 ItemNumber 执行验证,则参数将正确传递。

控制器

public class HomeController : Controller
{
    public ActionResult Index()
    {
        CartModel cart = new CartModel();
        cart.Items.Add(new ItemModel() { ItemNumber = "12345" });
        return View(cart);
    }

    [HttpPost]
    public JsonResult UniqueItemNo(string id)
    {
        /** Do Work **/
        return null;
    }
}

楷模

public class ItemModel
{
    [Remote("UniqueItemNo", "Home", HttpMethod="POST")]
    public string ItemNumber { get; set; }
}

public class CartModel
{
    public CartModel()
    {
        Items = new List<ItemModel>();
    }

    public List<ItemModel> Items { get; set; }
    public string CartNumber { get; set; }
}

看法

@{
    ViewBag.Title = "Home Page";
}

<h2>@ViewBag.Message</h2>
@using(Html.BeginForm()) {
    <p>
        @for(int i = 0; i < Model.Items.Count; i++)
        {
            @Html.TextBoxFor(m => m.Items[i].ItemNumber);
            @Html.ValidationMessageFor(m => m.Items[i].ItemNumber);                                    
        }
    </p>
}
4

4 回答 4

7

刚刚解决了同样的问题。所以对于我这种将来会遇到这个问题的人来说,这是解决方案

这是根本原因。

当你这样做时,@Html.TextBoxFor(x=>x.m.Items[i].ItemNumber) 它会输出这样的东西

<input type=text value='value' name='items[index].ItemNumber' ...

然后它添加其他验证,如 data-* 属性进行验证。例如远程验证 url data-remot-url 等

现在,当表单得到验证时,它会请求带有 key=xxx[1].propertyname 等数据的远程 url

并且这不能分配给将接收此属性的远程操作方法中的单个变量。

如果您将动作参数更改为这样的东西,那么它将起作用

 public JsonResult UniqueItemNo(list<string> propertyname)

即使那样你也不能保证,因为它要求参数索引从 0 开始并且没有任何间隙。所以 xxx[1].ItemNumber 永远不会被映射。

唯一剩下的解决方案是从查询字符串中获取属性名称并将其映射到您所需的变量。像这样

    if(Request.QueryString.AllKeys.FirstOrDefault(p => p.ToLower().Contains("propertyname"))!=null)
    {
                     propertyname = Request.QueryString[Request.QueryString.AllKeys.First(p => p.ToLower().Contains("propertyname"))];
}

它将搜索并映射所需的变量。

希望这会有所帮助

于 2012-11-20T22:26:56.107 回答
1

我希望你已经找到了答案,但如果你没有,试试这个:

[HttpPost]
public JsonResult UniqueItemNo()
{
    var itemNumber = Request.Form[Request.Form.AllKeys.First(p => p.Contains("ItemNumber"))];

    /** Do Work **/
    return Json(true);
}

请注意,@Mamoon 您的 Rasheed 答案几乎是正确的,但是由于您使用的是 POST,因此您的参数将位于 Form 属性内,而不是 QueryString 内。

如果您对此仍有任何问题,请告诉我。

顺便说一句,你应该使用 try/catch。我写它不是为了简单。

于 2014-01-16T19:58:33.283 回答
0

不幸的是,您对此没有支持。

在客户端,远程验证由 jquery.validate.unobtrusive.js 处理,它说

...
$.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) {
    var paramName = appendModelPrefix(fieldName, prefix);
    value.data[paramName] = function () {
        return $(options.form).find(":input[name='" + escapeAttributeValue(paramName) + "']").val();
    };
});
...

所以你应该注意到,对于每个附加字段,它只在查询字符串中构造一个参数(或者如果你发布的话,在表单中)。因为你的服务器端远程属性应该看起来像

[Remote("UniqueItemNo", AdditionalFields = "ItemNumber[0],ItemNumber[1],...")]

你在设计时不知道的事实。

您可以使用 js hack 并保留一个名为 ItemNumber 的隐藏字段,并带有一个连接的 id 列表。在服务器端,您应该将 ItemNumber 数组的类型更改为字符串并拆分值。

我希望这会有所帮助,尽管您已经很久没有问过了。

于 2013-05-14T11:42:43.153 回答
0

尝试更改参数以匹配模型。像这样:

    [HttpPost]
    public JsonResult UniqueItemNo(ItemModel itemModel)
    {
        // look at itemModel.ItemNumber...
        /** Do Work **/
        return null;
    }

您仍然可以按照正常的编码约定ActionMethod以小写(itemNumber而不是)开头的参数名称。ItemNumber

编辑:你试过View这样编码吗?

@{
    ViewBag.Title = "Home Page";
}

<h2>@ViewBag.Message</h2>
        @foreach (var item in Items)
        {
           @using(Html.BeginForm()) {
              <p>
                 @Html.HiddenFor(m=>m.CartNumber)
                 @Html.TextBoxFor(m => item.ItemNumber);
                 @Html.ValidationMessageFor(m => item.ItemNumber);                                    
              </p>
           }
        }
于 2012-01-20T23:04:57.807 回答