I'm trying to switch from using a MVC model to Razor Pages but I'm having trouble displaying the data from my database into a table. The problem is that on the Razor Page I can't use a foreach because there is no GetEnumerator in the Model and using @model IEnumerable<...> throws an exception when calling the page saying that there is no constructor for type "ModelName", even if in MVC it works.

In MVC I did it like this and it's all working fine:

Controller

public IActionResult ViewMenu()
{
    IList<ServixModel.MenuModel> menu = null;
    using (_context)
    {
        menu = _context.Menu.Select(m => new ServixModel.MenuModel()
        {
            Id = m.Id,
            Id_Parent = m.Id_Parent,
            Testo = m.Testo,
            Link = m.Link,
            SortOrder = m.SortOrder
        }).ToList<ServixModel.MenuModel>();
    }
    return View(menu);
}

View

@model IEnumerable<servix_test1.Models.ServixModel.MenuModel>

@{
    ViewData["Title"] = "ViewMenu";
}

<h1>ViewMenu</h1>

<table style="border:solid 1px black;">

    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Id)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Id_Parent)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Testo)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Link)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.SortOrder)
        </th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Id)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Id_Parent)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Testo)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Link)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.SortOrder)
            </td>
        </tr>
    }

</table>


Using Razor Pages I had to change it a bit:

ViewMenu.cshtml

@page
@model servix2.Models.Servix2Model.MenuModel
@{
    ViewData["Title"] = "ViewMenu";
    Layout = "~/Pages/Shared/_Layout.cshtml";
}
<h1>ViewMenu</h1>

<table>
    <thead>
        @Html.DisplayNameFor(model => model)
    </thead>
    <thead>
        @Html.DisplayNameFor(model => model.Id_Parent)
    </thead>
    <thead>
        @Html.DisplayNameFor(model => model.Link)
    </thead>
    <thead>
        @Html.DisplayNameFor(model => model.SortOrder)
    </thead>
    <thead>
        @Html.DisplayNameFor(model => model.Testo)
    </thead>
    @foreach (var item in Model) //Error here
    {
        <tr>
            <td>
                @Html.DisplayNameFor(modelItem => item.Id)
            </td>
            <td>
                @Html.DisplayNameFor(modelItem => item.Id_Parent)
            </td>
            <td>
                @Html.DisplayNameFor(modelItem => item.Link)
            </td>
            <td>
                @Html.DisplayNameFor(modelItem => item.SortOrder)
            </td>
            <td>
                @Html.DisplayNameFor(modelItem => item.Testo)
            </td>

        </tr>
    }
</table>

ViewMenu.cshtml.cs

    public class ViewMenuModel : PageModel
    {

        private readonly Servix2DbContext _context;  

        public ViewMenuModel(Servix2DbContext context)
        {
            _context = context;
        }

        public IList<MenuModel> Menu { get; set; }

        public async Task OnGetAsync()
        {
            Menu =  await _context.Menu.AsNoTracking().ToListAsync();
        }
    }

If you think the code is written badly and I can improve something just let me know.

Thanks to anyone who is willing to help.

1 Answers

0
Adrian On

I managed to fix it like this:

Viewmenu.cshtml

@page
@model servix2.Pages.ViewMenuModel
@{
    ViewData["Title"] = "ViewMenu";
    Layout = "~/Pages/Shared/_Layout.cshtml";
}
<h1>ViewMenu</h1>

<table>
    <tr>
        <th>@Html.DisplayNameFor(x => x.Menu[0].Id)</th>        
        <th>@Html.DisplayNameFor(x => x.Menu[0].Id_Parent)</th>
        <th>@Html.DisplayNameFor(x => x.Menu[0].Link)</th>
        <th>@Html.DisplayNameFor(x => x.Menu[0].Testo)</th>
        <th>@Html.DisplayNameFor(x => x.Menu[0].SortOrder)</th>
    </tr>
    @foreach (var item in Model.Menu)
    {
        <tr>
            <td>@item.Id</td>
            <td>@item.Id_Parent</td>
            <td>@item.Link</td>
            <td>@item.Testo</td>
            <td>@item.SortOrder</td>
        </tr>
    }
</table>

ViewMenu.cshtml.cs

public class ViewMenuModel : PageModel
{

    private readonly Servix2DbContext _context;  

    public ViewMenuModel(Servix2DbContext context)
    {
        _context = context;
    }

    public List<MenuModel> Menu { get; set; }

    public async Task OnGetAsync()
    {
        Menu =  await _context.Menu.AsNoTracking().ToListAsync();
    }
}