【问题标题】:ASP.NET MVC Post list becomes null under very strange circumstancesASP.NET MVC Post 列表在非常奇怪的情况下变为空
【发布时间】:2013-11-21 13:40:52
【问题描述】:

所以我有一个这样的控制器:

public class TestController : Controller
    {
        //
        // GET: /Test/

        public ActionResult Index()
        {
            return View("Test");
        }

        public ActionResult Post(IList<Test> LanguageStrings, IList<Test> LanguageStringsGroup, IList<string> Deleted, IList<string> DeletedGroup)
        {
            if (LanguageStrings == null)
            {
                throw new ApplicationException("NULL");
            }


            return View("Test");
        }

    }

    public class Test
    {
        public string Val { get; set; }
        public string Another { get; set; }
    }

还有这样的视图:

<h2>Test</h2>

@using (Html.BeginForm("Post", "Test"))
{
    @Html.Hidden("LanguageStrings[0].Val", "test1")
    @Html.Hidden("LanguageStrings[0].Another")
    @Html.Hidden("LanguageStrings[1].Val", "test2")
    @Html.Hidden("LanguageStrings[1].Another")

    @Html.Hidden("LanguageStringsGroup[0].Val", "test4")

    @Html.Hidden("Deleted[0]")
    @Html.Hidden("Deleted[1]")
    @Html.Hidden("Deleted[2]")

    @Html.Hidden("DeletedGroup[0]")

    <button>Post</button>
}

当我发布表单时,我的控制器抛出异常,因为 LanguageStrings 为空。我在标题中提到的奇怪部分是,如果我在列表中再添加一条记录,一切正常。 像这样:

<h2>Test</h2>

@using (Html.BeginForm("Post", "Test"))
{
    @Html.Hidden("LanguageStrings[0].Val", "test1")
    @Html.Hidden("LanguageStrings[0].Another")
    @Html.Hidden("LanguageStrings[1].Val", "test2")
    @Html.Hidden("LanguageStrings[1].Another")
    @Html.Hidden("LanguageStrings[2].Val", "test3")
    @Html.Hidden("LanguageStrings[2].Another")

    @Html.Hidden("LanguageStringsGroup[0].Val", "test4")

    @Html.Hidden("Deleted[0]")
    @Html.Hidden("Deleted[1]")
    @Html.Hidden("Deleted[2]")

    @Html.Hidden("DeletedGroup[0]")

    <button>Post</button>
}

当我删除“已删除”列表时它也有效。 像这样:

<h2>Test</h2>

@using (Html.BeginForm("Post", "Test"))
{
    @Html.Hidden("LanguageStrings[0].Val", "test1")
    @Html.Hidden("LanguageStrings[0].Another")
    @Html.Hidden("LanguageStrings[1].Val", "test2")
    @Html.Hidden("LanguageStrings[1].Another")

    @Html.Hidden("LanguageStringsGroup[0].Val", "test4")

    @Html.Hidden("DeletedGroup[0]")

    <button>Post</button>
}

这与我使用的命名有关。我已经解决了将 LanguageStrings 重命名为其他内容的问题。但我想了解这里发生了什么,因为可能我可以从中学到一些东西 MVC 如何映射请求正文,并且能够避免类似的耗时问题。 请帮助我并解释造成这种情况的原因。

【问题讨论】:

    标签: asp.net-mvc list asp.net-mvc-4 http-post


    【解决方案1】:

    您在 MVC 4 的 PrefixContainer 中发现了一个已在 MVC 5 中修复的错误。

    这里是关于这个 bug 的带有 cmets 的修复版本:

    internal bool ContainsPrefix(string prefix)
    {
        if (prefix == null)
        {
            throw new ArgumentNullException("prefix");
        }
    
        if (prefix.Length == 0)
        {
            return _sortedValues.Length > 0; // only match empty string when we have some value
        }
    
        PrefixComparer prefixComparer = new PrefixComparer(prefix);
        bool containsPrefix = Array.BinarySearch(_sortedValues, prefix, prefixComparer) > -1;
        if (!containsPrefix)
        {
            // If there's something in the search boundary that starts with the same name
            // as the collection prefix that we're trying to find, the binary search would actually fail.
            // For example, let's say we have foo.a, foo.bE and foo.b[0]. Calling Array.BinarySearch
            // will fail to find foo.b because it will land on foo.bE, then look at foo.a and finally
            // failing to find the prefix which is actually present in the container (foo.b[0]).
            // Here we're doing another pass looking specifically for collection prefix.
            containsPrefix = Array.BinarySearch(_sortedValues, prefix + "[", prefixComparer) > -1;
        }
        return containsPrefix;
    }
    

    【讨论】:

    【解决方案2】:

    @Html.HiddenFor() 在回发到控制器方面取得了更大的成功。代码看起来像这样:

    @for (int i = 0; i < @Model.LanguageStrings.Count; i++)
    {
        @Html.HiddenFor(model => model.LanguageStrings[i].Val, string.Format("test{0}", i))
        @Html.HiddenFor(model => model.LanguageStrings[i].Another)
    }
    

    大多数 HTML 帮助器方法都有一个“For”帮助器,用于将数据绑定到模型。这是网站上的另一篇文章,很好地解释了“For”方法:What is the difference between Html.Hidden and Html.HiddenFor

    【讨论】:

      猜你喜欢
      • 2011-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-02
      • 1970-01-01
      • 2011-01-18
      • 1970-01-01
      相关资源
      最近更新 更多