• ASP.NET MVC之表单集合数据自动绑定到对象属性(集合)中


    前言

    之前没遇到过这个问题,在项目中遇到这个问题时想法挺好,按照流程走下去,结果事与愿违,于是开始探索着解决方案,接下来我们来看看这个问题,早已经明了的童鞋请绕道,此文仅供未遇到的童鞋提供一种解决方案。

    话题

    首先我们来看看整个问题的出现,介绍一下问题的背景。

    复制代码
         public class Blog
        {
            public string BlogName { get; set; }
            public string BlogAddress { get; set; }
            public List<Article> Article { get; set; }
        }
    
        public class Article
        {
            public string ArticleIntr { get; set; }
            public string ArticleName { get; set; }
        }
    复制代码

    上述给出两个类,一个博客包含多篇文章取集合属性。

    复制代码
            public ActionResult Test(Blog b)
            {
                var articleList = new List<Article>() { new Article() { ArticleIntr = "asp.net mvc", ArticleName = "mvc" }, new Article { ArticleIntr = "WebAPi", ArticleName = "WebAPi Authentication" } };
                var blog = new Blog() { BlogName = "xpy0928", BlogAddress = "CreateMyself", Article = articleList };           
                return View(blog);
            }
    复制代码

    利用强类型视图渲染到页面

    复制代码
    @using FormToObjList.Models
    @model Blog
    @{
        Layout = null;
    }
    <script src="~/Scripts/jquery-1.10.2.min.js"></script>
    <script src="~/Scripts/bootstrap.min.js"></script>
    <link href="~/Content/bootstrap.min.css" rel="stylesheet" />
    <div style="700px;margin-left:200px;">
        <form action="test" method="post" enctype="multipart/form-data">
            <div style="float:left;">
                博客地址:<input type="text" class="form-control" value="@Model.BlogAddress" /><br />
                博客名称:<input type="text" class="form-control" value="@Model.BlogName" /><br />
            </div>
            <br />
    
            <div style="float:right;">
                <table>
                    <tr>
                        <th>序号</th>
                        <th>文章介绍</th>
                        <th>文章名称</th>
                    </tr>
                    @{
                        var i = 0;
                        foreach (var article in Model.Article)
                        {
                            <tr>
                                <td>@(++i)</td>
                                <td><input type="text" class="form-control" value="@article.ArticleIntr" /></td>
                                <td><input type="text" class="form-control" value="@article.ArticleName" /></td>
                            </tr>
                        }
                    }
                </table>
            </div>
            <div style="clear:both;float:right;">
                <button class="btn btn-primary" type="submit">提交</button>
            </div>
        </form>
    </div>
    复制代码

    到这里我们需要实现的是点击提交后将页面上所有的数据都添加到后台【Blog b】属性,着重强调的是获取到b中属性Article要有两条我们渲染的数据。 

    我们看看演示结果:

    我们可以看到居然都为空,别着急,此时都会想到既然要获取到值,则文本的name属性要和类中的属性一一对应才是,说完就开干。

    复制代码
      博客地址:<input type="text" name="BlogAddress" class="form-control" value="@Model.BlogAddress" /><br />
      博客名称:<input type="text" name="BlogName"    class="form-control" value="@Model.BlogName" /><br />
    
    
    
     <td><input type="text" name="ArticleIntr" class="form-control" value="@article.ArticleIntr" /></td>
     <td><input type="text" name="ArticleName" class="form-control" value="@article.ArticleName" /></td>
    复制代码

    进行如上设置后我们再来看看结果:

    恩,有点小忧伤,对于Article这个集合属性数据并未添加到其中去,这个就是我们需要解决的问题。到了这里我寻思着是不是不能用html标签,需要用mvc自己来渲染成html标签才行呢?也就是说利用【 @Html.TextBoxFor() 】来进行渲染,此时是个集合,则只能用for循环来进行遍历,于是乎将数据渲染时修改成下面的这个样子。

    复制代码
                   @{
                        var j = 0;
                        for (var i = 0; i < Model.Article.Count; i++)
                        {
                            <tr>
                                <td>@(++j)</td>
                                <td>@Html.TextBoxFor(a => a.Article[i].ArticleIntr, new { @class="form-control"})</td>
                                <td>@Html.TextBoxFor(a => a.Article[i].ArticleName, new { @class="form-control"})</td>
                            </tr>
                        }
                    }
    复制代码

    我们继续看看结果:

    好了,我们终于得到我们想要的结果了,你是不是觉得就这么愉快的结束了呢?

    实际需求

    在项目中我们需要做的是添加,同时在页面开始时有几个默认的文本框且还需要动态添加行,这个时候我们又该如何做呢?我们一起来看看。

    复制代码
                   @{
                        if (Model.Article != null)
                        {
                            var j = 0;
                            for (var i = 0; i < Model.Article.Count; i++)
                            {
                                <tr>
                                    <td>@(++j)</td>
                                    <td>@Html.TextBoxFor(a => a.Article[i].ArticleIntr, new { @class = "form-control" })</td>
                                    <td>@Html.TextBoxFor(a => a.Article[i].ArticleName, new { @class = "form-control" })</td>
                                </tr>
                            }
                        }
                        else 
                        {
                            
                        }
                    }
    复制代码

    如果默认没有值时,我们则需要自己添加默认的文本,此时该如何添加,我们想想当直接利用htm文本标签和利用Html.TextBoxFor渲染的效果有何不同?看看如下:

    复制代码
    //Html标签
    <input type="text" name="ArticleIntr" class="form-control" value="WebAPi">
    
    
    //Html.TextBoxFor()
    <input class="form-control" id="Article_1__ArticleIntr" name="Article[1].ArticleIntr" type="text" value="Angular">
    复制代码

    这个时候我们恍然大悟,既然是集合那么name则是取到对应的索引值,我们照样画葫芦,于是我们修改成如下:

    复制代码
                    @{
                        if (Model.Article != null)
                        {
                            var j = 0;
                            for (var i = 0; i < Model.Article.Count; i++)
                            {
                                <tr>
                                    <td>@(++j)</td>
                                    <td>@Html.TextBoxFor(a => a.Article[i].ArticleIntr, new { @class = "form-control" })</td>
                                    <td>@Html.TextBoxFor(a => a.Article[i].ArticleName, new { @class = "form-control" })</td>
                                </tr>
                            }
                        }
                        else
                        {
                            var j = 0;
                            for (var i = 0; i < 3; i++)
                            {
                                <tr id="trs">
                                    <td>@(++j)</td>
                                    <td><input type="text" name="Article[@i].ArticleIntr" class="form-control" /></td>
                                    <td><input type="text" name="Article[@i].ArticleName" class="form-control" /></td>
                                </tr>
                            }
                        }
                    }
    复制代码

    动态添加时的操作:

    复制代码
            $("#btnAdd").on("click", function () {
                var trLen = $("#tb tr[id='trs']").length;
                var $lastTr = $("#tb tr[id='trs']").last();
                var tr = "<tr id='trs'>";
                tr += "<td>" + (trLen + 1) + "</td>";
                tr += "<td><input type='text' name='Article[" + trLen + "].ArticleIntr' class='form-control' /></td>";
                tr += "<td><input type='text' name='Article[" + trLen + "].ArticleName' class='form-control' /></td>";
                tr += "</tr>";
                $(tr).insertAfter($lastTr);
            });
    复制代码

    完整效果如下:

    至此我们的需求才算结束。

    总结

    项目中渲染视图都是采用MVC中Razor渲染的方式,所以在做的时候也是跟着项目同样的风格去做,做的时候才发现这个问题并解决了下,学习,学习,可能还有其他解决方案,这也算是其中一种吧。


    感谢花时间阅读此篇文章,如果您觉得这篇文章你学到了东西也是为了犒劳下博主的码字不易不妨打赏一下吧,让楼主能喝上一杯咖啡,在此谢过了!
    如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!
    本文版权归作者和博客园共有,来源网址:http://www.cnblogs.com/CreateMyself)/欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
    成功就像怀孕,别人都祝贺你有喜了,但没人知道你曾被生活操哭过多少次!
  • 相关阅读:
    侧滑界面的实现
    Private field 'XXX' is never assigned的解决办法
    android先加载注册页面而不是MainActivity主页面
    每日日报4
    每日日报3
    47 选择排序和插入排序
    计算机启动过程 BIOS MBR等
    ARM中MMU地址转换理解(转)
    深度学习框架 CatBoost 介绍
    预训练词嵌入
  • 原文地址:https://www.cnblogs.com/webenh/p/6034557.html
Copyright © 2020-2023  润新知