locked
How to make a viewModel to be Enumerable RRS feed

  • Question

  • User-259252065 posted

    I'm implementing asp.net core 3.1. I'm passing a viewmodel to the razor view which is in the following:

    public class BuyRequestViewModel {
    
        public IEnumerable<BuyRequest> BuyRequestVM { get; set; }
        public IEnumerable<string> PlatesVM { get; set; }
    
    }
    

    My problem is, as my viewmodel is not of type Ienumerable, I'm getting error in foreach in the razor view. The error is like the following: ForEach statement can not operate on variables of type 'MyPanel.ViewModels.BuyRequestViewModel' because 'MyPanel.ViewModels.BuyRequestViewModel' does not contain a public instance definition for 'GetEnumerator'

    And my razor view code is like below:

    @model MyPanel.ViewModels.BuyRequestViewModel
    <table id="myDummyTable" class="table m-table mytable table-striped table-bordered">
    
        <thead>
            <tr>
                <th>
                    Region
                </th>
                <th>
                    Zone
                <th>
                    MyPlate
                </th>
      
            </tr>
        </thead>
        <tbody>
            @foreach (var item in Model)
            {
                <tr>
                    <td>
                        @Html.DisplayFor(modelItem => item.BuyRequestVM.Select(x => x.Region))
                    </td>
                    <td>
    
                        @Html.DisplayFor(modelItem => item.BuyRequestVM.Select(x => x.Zone))
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.PlatesVM)
                    </td>
                </tr>
            }
        </tbody>
    </table>

    And here below is the Index action in my controller:

    public async Task<IActionResult> Index()
    {
    
        var bwrvm = new BuyRequestViewModel();
    
        List<string> platesList = new List<string>();
    
       
        var WasteAPIContext = _context.BuyRequest
           
            .Include(b => b.UserWasteUnitNavigation).ToList();
    
       bwrvm.BuyWasteRequestVM = WasteAPIContext;
        
    
        var plateData = _context.Car.Select(x => x.Plate).ToList();
    
        for (int i = 0; i < plateData.Count; i++)
        {
            //platesList.Add(plateData[i].ToString().Substring(2, 5));
            string temp = getPlateCharacter(plateData[i].ToString().Substring(2, 3));
            plateData[i].Remove(2, 3);
            string totalPlate = plateData[i].Insert(2, temp);
    
            platesList.Add(totalPlate);
        }
    
        bwrvm.PlatesVM = platesList;
    
        return View(bwrvm);
    }

    I appreciate of any help.
    Sunday, September 6, 2020 8:09 AM

All replies

  • User1120430333 posted

    A viewmodel class is a singular entity in its definition. A viewmodel can be used in another VM as a collection of the VM loaded into a collection object like a List<T>.

    Your BuyRequestVM is not a viewmodel. It's  just a collection BuyRequest objects in BuyRequestViewModel. BuyRequestVM should be named BuyRequests a plural naming convention. The same is true for PlatesVM it's  just Plates.

    You need to make another VM that has an IEnumeral defined for the other VM you expect to be a collection of VM(s) and use it in the view. VM-a holding VM-b(s).

    https://www.dotnettricks.com/learn/mvc/understanding-viewmodel-in-aspnet-mvc

    Sunday, September 6, 2020 9:55 AM
  • User711641945 posted

    Hi Elenorarez:

    The foreach error is because the model you return to the view is not a collection.

    If you want to use foreach then you can use the following code:

    @foreach (var item in Model.BuyRequestVM)
    {
               <tr>
                    <td>
                        @Html.DisplayFor(modelItem => item.Region)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.Zone)
                    </td>                  
               </tr>
     }

    However, since you are writing in the table, if you use two foreach, your rows and columns will not match. I suggest you use a for loop to do:

    @model Button.Models.BuyRequestViewModel
    @{
        int j = 0;
    }
    <table id="myDummyTable" class="table m-table mytable table-striped table-bordered">
        <thead>
            <tr>
                <th>
                    Region
                </th>
                <th>
                    Zone
                </th>
                <th>
                    MyPlate
                </th>
            </tr>
        </thead>
        <tbody>
            @for (var i = 0; i < Model.BuyRequestVM.Count(); i++)
            {
                <tr>
                    <td>@Html.DisplayFor(x => Model.BuyRequestVM.ToList()[i].Region)</td>
                    <td>@Html.DisplayFor(x => Model.BuyRequestVM.ToList()[i].Zone)</td>
                    @for (var n = j; j < Model.PlatesVM.Count(); n++)
                    {
                        <td>@Html.DisplayFor(x => Model.PlatesVM.ToList()[n])</td>
                        j++;
                        break;
                    }
                </tr>
            }
        </tbody>
    </table>

    Result:

    Best Regards,

    Rena

    Monday, September 7, 2020 6:24 AM