0

I have view model which has a list of child models to render the partial view (below).

public class PRDocument
{
        [Key]
        [Column(Order = 0)]
        public int Id { get; set; }

        [DisplayName("Vendor Name")]
        [Column(Order = 2)]
        public int VendorId { get; set; }

        public virtual ICollection<PRDocumentQuotation> PRDocumentQuotations { get; set; }

        [NotMapped]
        public List<PRDocumentQuotation> Quotations { get; set; }

        public PRDocument()
        {
            Quotations = new List<PRDocumentQuotation>();
        }
}

    public class PRDocumentQuotation
    {
        [Key]
        [Column(Order = 0)]
        public int Id { get; set; } 

        [Required]
        [Column(Order = 1)]
        public int PRDocumentId { get; set; }

        [Display(Name = "Uploaded File")]
        [Column(Order = 2)]
        public string FileName { get; set; }
    }

And in the Partial View rendered like this.

@Html.Partial("_PRDocs", Model.Quotations)

Here is my partial view.

@model IEnumerable<JKLLPOApprovalApp.Models.PRDocumentQuotation>

<table class="table">
   <tr>
       <th>
           @Html.DisplayNameFor(model => model.FileName)
       </th>

       <th></th>
   </tr>

@foreach (var item in Model) {
   <tr>
       @Html.HiddenFor(modelItem => item.PRDocumentId)
       <td>
           @Html.DisplayFor(modelItem => item.FileName)
       </td>     
       <td>
           @Html.ActionLink("Delete", "Delete", new { id=item.Id })
       </td>
   </tr>
}

</table>

And the controller actions

  [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(PRDocument pRDocument)
        {
            if (ModelState.IsValid)
            {
                pRDocument.PRDocumentQuotations = pRDocument.Quotations;
                db.tbl_PRDocuments.Add(pRDocument);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(pRDocument);
        }

View Data Main View

@model JKLLPOApprovalApp.Models.PRDocument

@{
    ViewBag.Title = "Create";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Create</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>PRDocument</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })

        <div class="form-group">
            @Html.LabelFor(model => model.VendorId, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.VendorId, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.VendorId, "", new { @class = "text-danger" })
            </div>
        </div>

        @Html.Partial("_PRDocs", Model.Quotations)

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>




}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

What i want is to get the partial view data list (PRDocumentQuotation) into the Create action, bound with main model (PRDocument). How can i do this?

Nishantha Maduranga
  • 253
  • 1
  • 5
  • 17

1 Answers1

1

Interesting Question :)

The issue was that Model binding to list should have unique names. So the Generated HTML Should look like below:

<input id="Quotations_0__PRDocumentId" name="Quotations[0].PRDocumentId" type="hidden" value="0">

<input id="Quotations_1__PRDocumentId" name="Quotations[1].PRDocumentId" type="hidden" value="0">

The recommended solution is to use Editor Templates, Check this and this.

But I am giving alternate solution below using for loop to create unique names with index, taken from this post which faced same issue.

In Main View:

Pass The Main Model Instead

@Html.Partial("_PRDocs", Model)

Partial View:

@model JKLLPOApprovalApp.Models.PRDocument

<table class="table">
    @if (Model.Quotations != null)
    {
        for (var i = 0; i < Model.Quotations.Count(); i++)
        {
            <tr>
                <th>
                    @Html.DisplayNameFor(model => Model.Quotations[i].FileName)
                </th>

                <th></th>
            </tr>

            <tr>
                @Html.HiddenFor(modelItem => Model.Quotations[i].PRDocumentId)
                <td>
                    @Html.DisplayFor(modelItem => Model.Quotations[i].FileName)
                </td>
                <td>
                    @Html.ActionLink("Delete", "Delete", new { id = Model.Quotations[i].Id })
                </td>
            </tr>
        }
    }

</table>

Hope helps.

Shaiju T
  • 6,201
  • 20
  • 104
  • 196