简体   繁体   中英

Multiple models in one view using IEnumerable

Problem Statement: I want to create a view where first I'm accepting two parameters as a from date and to date and also a dropdown based on which one index in order to display all the details corresponding to the item selected in the combobox.

For this I've defined two models: First model consists of the parameters which is to be inserted from the front end and again in the second model I'm defining all the parameters required to display in the index of that page.

Here is my model :

public class SearchModel
    {
        [Required]
        [Display(Name = "From Date")]
        public DateTime FromDate { get; set; }

        [Required]
        [Display(Name = "To Date")]
        public DateTime ToDate { get; set; }

        [Display(Name = "Search #")]
        public String SearchNumber { get; set; }
    }

 public class IndexModel
    {
        [Required]
        [Display(Name = "Search #")]
        public string SearchNumber { get; set; }

        [Key]
        [Required]
        [Display(Name = "SearchID")]
        public int SearchID{ get; set; }

        [Display(Name = "Received Date")]
        public DateTime ReceivedDate { get; set; }
}

And finally I'm defining both of the models in a global Model as:

public class GlobalModel
    {
        public SearchModel SearchModel { get; set; }
        public IndexModel IndexModel { get; set; }
    }

Finally, when I try to write code in the view in index with GlobalModel as

@model IEnumerable<...SomePath.GlobalModel>  

@{
    ViewBag.Title = "Index";
}
<div style="padding-left: 40%">
        @using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl }))
        {
            @Html.AntiForgeryToken()
            @Html.ValidationSummary(true)

            <fieldset>
                <legend>Search</legend>
                  <ol>
                    <li>

                        <div class="editor-label">
                            @Html.LabelFor(model => model.SearchModel.FromDate)
                        </div>
                        <div class="editor-field">
                            @Html.EditorFor(model => model.SearchModel.FromDate)
                            @Html.ValidationMessageFor(model => model.SearchModel.FromDate)
                        </div>
                    </li>
                    <li>
                          <div class="editor-label">
                            @Html.LabelFor(model => model.SearchModel.ToDate)
                        </div>
                        <div class="editor-field">
                            @Html.EditorFor(model => model.SearchModel.ToDate)
                            @Html.ValidationMessageFor(model => model.SearchModel.ToDate)
                        </div>
                    </li>
                    <li>
                        @Html.DropDownListFor(model => model.SearchModel.SearchNumber, new SelectList(Model.ddlSearchNo.ddlSearchNumber, "Value", "Text"), "Select Search #", new { id="SearchID",onchange="GetSearchNo()" })
                        @Html.ValidationMessageFor(model => model.FirstOrDefault().SearchModel.SearchNumber)
                    </li>
                </ol>
               </fieldset>

        }
    </div>

<div>
    <table style="border-collapse: separate; border-spacing: 15px;">
    <tr>
        <th style="text-align:center;">
            @Html.DisplayNameFor(model => model.IndexModel.SearchNumber)
        </th>
        <th style="text-align:center;">
            @Html.DisplayNameFor(model => model.IndexModel.SearchID)
        </th>
        <th style="text-align:center;">
            @Html.DisplayNameFor(model => model.IndexModel.ReceivedDate)
        </th>

       </tr>

@foreach (var item in Model) {
    <tr>
        <td style="text-align:center;">
            @Html.DisplayFor(modelItem => item.IndexModel.SearchNumber)
        </td>
       <td style="text-align:center;">
            @Html.DisplayFor(modelItem => item.IndexModel.SearchID)
        </td>

        <td style="text-align:center;">
            @Html.DisplayFor(modelItem => item.IndexModel.ReceivedDate)
        </td>

        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.IndexModel.SearchID}) |
            @Html.ActionLink("Details", "Details", new{id=item.Model.SearchID}) |
            @Html.ActionLink("Delete", "Delete", new {id=item.IndexModel.SearchID })
        </td>
    </tr>
}

</table>

</div>

Here,though I am using the global model name at the top and with the object of the global model I'm trying to access the parameters of the child models but I'm getting error like not declared or cannot recognise.

I am able to access all the parameters of the child model if I use FirstorDefault() which was suggested by someone as :

@Html.LabelFor(model => model.FirstorDefault().SearchModel.FromDate)

but at the time of loading it throws exception as values cannot be null.

Again if I dont use Ienumerable in top then I'm getting error in the foreach loop.

Also I found in stackoverflow that I need to use Ienumerable while defining the child model in the parent model as :

public IEnumerable<SearchModel> SearchModel { get; set; }
        public IEnumerable<IndexModel> IndexModel { get; set; }

but again some other error are there.

I just want to load my view which I'm not able even after lot of try and research. What changes should I make...?

Any help would be appreciated.

In controller index action method,I've written code as:

 public ActionResult Index()
        {
            var result = GetDetails();
            return View(result); 
        }

and my method is:

 public IEnumerable<GlobalModel> GetDetails()
        {
            return (from po in dbEntity.SearchDetails.AsEnumerable()
                      select new GlobalModel()
                    {
                      IndexModel = po

                       //SearchID = po.SearchID,
        //             //ReceivedDate = po.ReceivedDate,



                    }).ToList();

        }

Here,I am passing the Global model for the view to be loaded that consists of two child models.Now since the Index details is coming from database ,so here also I'm not able to initialise all the parameters,since I am trying to initialise the entire model to the fields of the table which is not at all possible .

Also, I'm getting all the fields of the database table at po. but again not able to initialise as IndexModel refers to entire parameters of the Index Model.

So,I got stuck here.I need to solve this issue.Where am I doing wrong..?

As I can see you only want to loop through the IndexModel and SearchModel only have a single value. Try doing this approach:

Change your Global Model to:

public class GlobalModel
    {
        public SearchModel SearchModel { get; set; }
        public IEnumerable<IndexModel> IndexModels { get; set; }

    }

For your method to get the IndexModels:

public IEnumerable<IndexModel> GetDetails()
        {
            return (from po in dbEntity.SearchDetails
                      select new IndexModel()
                    {
                      SearchNumber = po.SearchNumber,
                      SearchID = po.SearchID,
                      ReceivedDate = po.ReceivedDate 
                    }).ToList();

        }

In your Action Method:

public ActionResult Index()
        {
            var model = new GlobalModel():
            var model.IndexModels = GetDetails();
            return View(model); 
        }

Finally in your View:

@model ProjectName.Model.GlobalModel

@{
    ViewBag.Title = "Index";
}
<div style="padding-left: 40%">
        @using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl }))
        {
            @Html.AntiForgeryToken()
            @Html.ValidationSummary(true)

            <fieldset>
                <legend>Search</legend>
                  <ol>
                    <li>

                        <div class="editor-label">
                            @Html.LabelFor(model => model.SearchModel.FromDate)
                        </div>
                        <div class="editor-field">
                            @Html.EditorFor(model => model.SearchModel.FromDate)
                            @Html.ValidationMessageFor(model => model.SearchModel.FromDate)
                        </div>
                    </li>
                    <li>
                          <div class="editor-label">
                            @Html.LabelFor(model => model.SearchModel.ToDate)
                        </div>
                        <div class="editor-field">
                            @Html.EditorFor(model => model.SearchModel.ToDate)
                            @Html.ValidationMessageFor(model => model.SearchModel.ToDate)
                        </div>
                    </li>
                    <li>
                        @Html.DropDownListFor(model => model.SearchModel.SearchNumber, new SelectList(Model.ddlSearchNo.ddlSearchNumber, "Value", "Text"), "Select Search #", new { id="SearchID",onchange="GetSearchNo()" })
                        @Html.ValidationMessageFor(model => model.SearchModel.SearchNumber)
                    </li>
                </ol>
               </fieldset>

        }
    </div>

<div>
    <table style="border-collapse: separate; border-spacing: 15px;">
    <tr>
        <th style="text-align:center;">
            @Html.DisplayNameFor(model => model.IndexModels.SearchNumber)
        </th>
        <th style="text-align:center;">
            @Html.DisplayNameFor(model => model.IndexModels.SearchID)
        </th>
        <th style="text-align:center;">
            @Html.DisplayNameFor(model => model.IndexModels.ReceivedDate)
        </th>

       </tr>

@foreach (var item in Model.IndexModels) {
    <tr>
        <td style="text-align:center;">
            @Html.DisplayFor(modelItem => item.SearchNumber)
        </td>
       <td style="text-align:center;">
            @Html.DisplayFor(modelItem => item.SearchID)
        </td>

        <td style="text-align:center;">
            @Html.DisplayFor(modelItem => item.ReceivedDate)
        </td>

        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.SearchID}) |
            @Html.ActionLink("Details", "Details", new{id=item.SearchID}) |
            @Html.ActionLink("Delete", "Delete", new {id=item.SearchID })
        </td>
    </tr>
}

</table>

</div>

let me know if it works.

The problem is because you don't initialize your Search model and the Index model!

First, you should modify your GetDetails method as follows

  public IEnumerable<GlobalModel> GetDetails()
    {
        var models=(from po in dbEntity.SearchDetails.AsEnumerable()
                  select new GlobalModel()
                {
                  IndexModel = new IndexModel(){
                     /* FromDate= po. FromDate,
                      ToDate= po. ToDate,*/
                      },
                  SearchModel = new SearchModel(){
                       /*SearchID = po.SearchID,
                       ReceivedDate = po.ReceivedDate,*/
                     },
                }).ToList();

    }

In addition, you'd better create an empty constructor for the IndexModel class and the SearchModel class as well. This constructor will initialize the class fields/properties.

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