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="width: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渲染的方式,所以在做的時候也是跟着項目同樣的風格去做,做的時候才發現這個問題並解決了下,學習,學習,可能還有其他解決方案,這也算是其中一種吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM