简体   繁体   中英

C# MVC: Dynamically Add Object To ViewModel From View

I have the following View (see below) - The idea is it will display any existing brand items in a table, but also give the user the ability to add new brand items (and upload an associated brand file). Visually it works the way it should. The user clicks the button to dynamically add a append a new table row with the empty fields.

The issue I'm having, is that the newly added rows in the table aren't being binded to the ViewModel, so when I hit submit, and debug into my Action, there is only one (or however many rows were pre existing) binded to the ViewModel. I'm also unsure how to get this information from the formValues variable as it would be unfeasible to retrive each row as:

BrandItems[1].Identifier, BrandItems[2].Identifier

as I will never know how many exist.

Another problem I'm having with this method is binding the file upload to the model also.

Any help would be greatly appreciated. Any questions or need more information just ask.

Here is my View:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Main.Master" 
Inherits="System.Web.Mvc.ViewPage<MyProject.Web.Models.BrandViewModel>" %>

<%@ Import Namespace="MyProject.Extensions" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <% Html.BeginForm("EditBrandItems", "Brands"); %>
    <table class="normal" border="1px" cellpadding="2px" style="border-collapse: collapse; width: 530px;">
        <tr>
            <th style="text-align: left;">
                Delete
            </th>
            <th style="text-align: left;">
                Type
            </th>
            <th style="text-align: left;">
                Identifier
            </th>
            <th>
                File Upload
            </th>
        </tr>
        <% for (int i = 0; i < Model.BrandItems.Count; i++) %>
        <% { %>
        <% var tb = Model.BrandItems[i]; %>
        <tr class="BrandItems-editor">
            <td style="text-align: center;">
                <%: Html.HiddenFor(m => m.BrandItems[i].BrandItemID) %>
                <%: Html.HiddenFor(m => m.BrandItems[i].BrandID) %>
                <%: Html.HiddenFor(m => m.BrandItems[i].FileName) %>
                <%: Html.HiddenFor(m => m.BrandItems[i].BrandItemType.Name) %>

                <%: Html.EditorFor(m => m.BrandItems[i].Deleted) %>
            </td>
            <td style="text-align: center;">
                <%: tb.BrandItemType.Name %>
            </td>
            <td style="text-align: center;">
                <%: Html.EditorFor(m => m.BrandItems[i].Identifier) %>
            </td>
            <td>
                <input name="ASSET_<%: Model.BrandItems[i].BrandItemID %>" type="file" id="ASSET_<%: Model.BrandItems[i].BrandItemID %>" />
            </td>
        </tr>

        <% if (i == 0) { %>
        <tr class="BrandItems-editor-template" style="display:none">
            <td style="text-align: center;">
                <%: Html.EditorFor(m => m.BrandItems[i].Deleted) %>
            </td>
            <td style="text-align: center;">
                <%: Html.EditorFor(m => m.BrandItems[i].BrandItemType.Name) %>
            </td>
            <td style="text-align: center;">
                <%: Html.EditorFor(m => m.BrandItems[i].Identifier) %>
            </td>
            <td>
               <input name="NEWASSET_<%: Model.BrandItems[i].BrandID %>" type="file" id="NEWASSET_<%: Model.BrandItems[i].BrandID %>" />
            </td>
        </tr>
        <% } %>
     <% } %>

    </table>
    <br />
    <input type="button" class="add-button" name="add" value="Add" />
    <% Html.RenderPartial("UpdateButtons"); %>
    <% Html.EndForm(); %>
</asp:Content>

<asp:Content ID="Content3" ContentPlaceHolderID="Header" runat="server">
    <script type="text/javascript">
        $(document).ready(function () {
            var count = 2;
            $('.add-button').click(function () {
                count++;
                var template = $('.BrandItems-editor-template').clone()
                template.find('input[type=text]').val('');
                $.each(template.find('input[type=text]'), function () {
                    var name = $(this).attr('name');
                    name = name.replace('0', count - 1);
                    $(this).attr('name', name);
                });

                $('.normal').append(template);
                template.removeClass('BrandItems-editor-template').addClass('BrandItems-editor').show();
            })
        });
 </script>
</asp:Content>

Here is my action method within my controller:

[HttpPost]
[ValidateInput(false)]
public virtual ActionResult EditBrandItems(BrandViewModel model, FormCollection formValues)
{
    //DO SOMETHING WITH DATA
    return View(model);
}

HEre is the BrandViewModel - (BrandItems is a list within this model)

    public class BrandViewModel
    {
        public BrandViewModel()
        {
            Brand = new Brand();
            BrandItems = new List<Data.BrandItem>();
        }

        public Data.Brand Brand { get; set; }
        public List<Data.Brand> BrandItems { get; set; }
    }

Change BrandViewModel to List < BrandViewModel > model

 [HttpPost] 
    [ValidateInput(false)]
    public virtual ActionResult EditBrandItems(List < BrandViewModel > model, FormCollection formValues)
    {
        //DO SOMETHING WITH DATA
        return View(model);
    }

I think u should create two buttons one which will append new row and second submit. Check generated html of your page and look on the last item in ( for (int i = 0; i < Model.BrandItems.Count; i++)). Next item which u append in your table should be generated with next id. If that no help u should looking custom binder in mvc. Good luck

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM