Tofetopo
Tofetopo

Reputation: 496

Add multiple records of the same model in ASP.NET MVC

I am developing a small web app in .NET Framework and in one of the views I need to upload/send 5 records on form submit. I have done a for loop in the cshtml file just like this.

The DataModel:

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace aspnet_client.Models
{
    /// <summary>
    /// The DataModel class
    /// </summary>
    public class DataModel
    {
        /// <summary>
        /// Gets or sets the identifier.
        /// </summary>
        /// <value>
        /// The identifier.
        /// </value>
        public int Id { get; set; }

        /// <summary>
        /// Gets or sets the description.
        /// </summary>
        /// <value>
        /// The description.
        /// </value>
        [Required(ErrorMessage = "Se requiere una descripción")]
        [DisplayName("Descripción")]
        public string Description { get; set; }

        /// <summary>
        /// Gets or sets the image.
        /// </summary>
        /// <value>
        /// The image.
        /// </value>
        [Required(ErrorMessage = "Se requiere una imagen")]
        [DisplayName("Imagen")]
        public byte[] Image { get; set; }
    }
}

The view:

@model List<aspnet_client.Models.DataModel>
@{
    ViewBag.Title = "AddData";
}

<h2>Añade nuevos registros</h2>
@using (Html.BeginForm(FormMethod.Post))
{
    @Html.ValidationSummary(true, "", new { @class="text-danger"})
        <div class="form-inline">
            @if (Model != null && Model.Count > 0)
            {
                var j = 0;
                foreach (var i in Model)
                {
                    <div class="data-element">
                        <div class="description">
                            @Html.TextBoxFor(x => x[j].Description, new { @class = "form-control", placeholder = "Descripción" })
                            @Html.ValidationMessageFor(model => model[j].Description, "", new { @class="text-danger"})
                        </div>
                        <br />
                        <div>
                            <input type="file" name="ImageData" id="ImageData" onchange="fileCheck(this);" />
                        </div>
                    </div>
                    <br />
                    j++;
                }
            }
     </div>
    <button type="submit" class="btn btn-success">Añadir Registros</button>
}

The Controller Action:

using aspnet_client.Models;
using System.Collections.Generic;
using System.Web.Mvc;

namespace aspnet_client.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        [HttpGet]
        public ActionResult AddData()
        {
            var records = new List<DataModel>();

            records.Add(new DataModel());
            records.Add(new DataModel());
            records.Add(new DataModel());
            records.Add(new DataModel());
            records.Add(new DataModel());

            return View(records);
        }

        [HttpPost]
        public ActionResult AddData(DataModel dataModel)
        {
            return View(dataModel);
        }

        [HttpGet]
        public ActionResult GetDataRecords()
        {
            return View();
        }
    }
}

I have updated my initial issue by adding 5 models to the list in the action as you can see in the action code, this seemed to have fixed my issue (might be a better solution for this out there?)

The problem now is to update the image Name attribute and ImageId attribute in the input image tag. Not sure how to do this as I can't access the model as I'm doing above, using the @Html. directive in the textboxes, I'm stuck

Upvotes: 2

Views: 1406

Answers (1)

michaela112358
michaela112358

Reputation: 483

In the background .net uses the id and possibly the name of a control to decide how to populate the model. Problem is that the id that is produced by your view for the page is not sufficient to be translated into the model needed for the post method.

I think you need a second model to hold the list of DataModels.

    public class PageModel
    {
      /// <summary>
      /// Gets or sets the list of records.
      /// </summary>
      /// <value>
      /// The identifier.
      /// </value>
      public List<DataModel> Records { get; set; }
    }

Have this as the model on your view

@model aspnet_client.Models.PageModel

and change the for loop as follows

        @if (Model != null && Model.Records.Count > 0)
        {
            var j = 0;
            foreach (var i in Model.Records)
            {
                <div class="data-element">
                    <div class="description">
                        @Html.TextBoxFor(x => x.Records[j].Description, new { @class = "form-control", placeholder = "Descripción" })
                        @Html.ValidationMessageFor(model => model.Records[j].Description, "", new { @class="text-danger"})
                    </div>
                    <br />
                    <div>
                        @*This will also need changed*@
                        <input type="file" name="ImageData" id="ImageData" onchange="fileCheck(this);" />
                    </div>
                </div>
                <br />
                j++;
            }
        }

Post method

    [HttpPost]
    public ActionResult AddData(PageModel model)
    {
        //Do stuff with records
    }

Get Method

    [HttpGet]
    public ActionResult AddData()
    {
        var pm = new PageModel();
        pm.Records = new List<DataModel>();

        pm.Records.Add(new DataModel());
        pm.Records.Add(new DataModel());
        pm.Records.Add(new DataModel());
        pm.Records.Add(new DataModel());
        pm.Records.Add(new DataModel());

        return View(pm);
    }

Upvotes: 1

Related Questions