0

I currently have an ASP.NET Core 2.0 Web Application (built in VS 2017 from the default web application template). I have a RazorPage with a dropdown built in that I would like to populate via a SQL Query. I've used Entity Framework Core to build a model of my database as follows:

    public partial class INVOPEContext : DbContext
    {
        public virtual DbSet<PmeFundData> PmeFundData { get; set; }

            modelBuilder.HasAnnotation"Relational:DefaultSchema", "Server\\User");

            modelBuilder.Entity<PmeFundData>(entity =>
            {
                entity.ToTable("PME_FUND_DATA", "dbo");
                entity.Property(e => e.Firm).HasMaxLength(255);
            });
    }


    public partial class PmeFundData
    {
        public string Firm { get; set; }
    }

I've updated the RazorPage PageModel (pmepe.cshtml.cs) to include the DBContext and Query:

    public class pmepeModel : PageModel
    {
        private readonly INVOPEContext _db;
        public pmepeModel(INVOPEContext db)
        {
            _db = db;
        }

        public IActionResult dropdowns()
        {
            List<PmeFundData> firmList = new List<PmeFundData>();

            firmList = (from Firm in _db.PmeFundData
                        select Firm).Distinct().ToList();

            firmList.Insert(0, new PmeFundData {Firm = "All Firms" });

            ViewBag.ListofFirms = firmList;

            return View();
        }
    }

Finally, the view with the dropdown (pmepe.cshtml) is as follows:

    @page
    @model pmepeModel
    @{
        ViewData["Title"] = "pmepe";
    }

    <select asp-for="dropdowns"
        id="firm" 
        class="dropdown" 
        asp-items= "@(new SelectList(ViewBag.ListofFirms, "Firm"))">
    </select>

I am getting errors that neither ViewBag nor View exist in the current context in the PageModel (no errors in the view - Intellisense picks it up). Every example I've found on the web is for MVC rather than RazorPages. The solution commonly provided for MVC is imbedding the query in a Controller and adjusting the MVC version in the web.config file. But the RazorPages template doesn't have Controllers and I can't find a web.config file - so I haven't been able to get it to work in my app. Any help you can provide would be most appreciated.

SultanGromma
  • 37
  • 1
  • 8

1 Answers1

1

There are multiple issues in your code.

  1. PmeFundData should have Id property, otherwise, you will receive error while running update-database command.

    public partial class PmeFundData
    {
    public int Id { get; set; }
    public string Firm { get; set; }
    }
    
  2. ViewBag is not supported in RazorPage, you could trace this issue from Add ViewBag to PageModel #6754, you could try ViewData or PageModel Property to bind the object.

Here is a simple code for ViewData.

    public class PmepeModelModel : PageModel
{
    private readonly CoreRazor2_1.Data.ApplicationDbContext _context;

    public PmepeModelModel(CoreRazor2_1.Data.ApplicationDbContext context)
    {
        _context = context;
    }

    public IActionResult OnGet()
    {
        return Page();
    }
    [BindProperty]
    public int SelectedFirm { get; set; }
    [ViewData]
    public IList<PmeFundData> ListofFirms { get {
            return Dropdowns();
        }
    }
    public IList<PmeFundData> Dropdowns()
    {
        List<PmeFundData> firmList = new List<PmeFundData>();
        firmList = new List<PmeFundData> {
            new PmeFundData{ Id = 1, Firm = "F1"},
            new PmeFundData{ Id = 2, Firm = "F3"},
            new PmeFundData{ Id = 3, Firm = "F2"}
        };
        //firmList = (from Firm in _context.PmeFundData
        //            select Firm).Distinct().ToList();

        firmList.Insert(0, new PmeFundData { Firm = "All Firms" });
        return firmList;
        //ViewData["ListofFirms"] = firmList;
    }

    public async Task<IActionResult> OnPostAsync()
    {
        var value = SelectedFirm;
        if (!ModelState.IsValid)
        {
            return Page();
        }

        _context.PmeFundData.Add(PmeFundData);
        await _context.SaveChangesAsync();

        return RedirectToPage("./Index");
    }
}

View

@page
@model CoreRazor2_1.Pages.PmepeModelModel

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

<h2>PmepeModel</h2>
<h4>PmeFundData</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form method="post">
            <select asp-for="@Model.SelectedFirm"
                    class="dropdown"
                    asp-items="@(new SelectList((IEnumerable<PmeFundData>)@ViewData["ListofFirms"], "Id" ,"Firm"))">

            </select>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </form>
    </div>
</div>
<div>
    <a asp-page="Index">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

You may also learn Razor Page from Introduction to Razor Pages in ASP.NET Core

Edward
  • 28,296
  • 11
  • 76
  • 121
  • Thanks so much for your quick response. Strangely, when I enter your code I am still getting a red underline on [ViewData] in the PageModel. I tried your code verbatim both in my existing project and a fresh project. It's telling me [ViewData] cannot be found and crtl+. doesn't prompt any references to add. Any ideas on why I could be missing? – SultanGromma Jul 11 '18 at 22:50
  • For `ViewData` attribute, you will need to start with `Asp.Net Core 2.1`, if you want to deal with `Asp.Net Core 2.0`, I think you could follow this [https://stackoverflow.com/a/51258256/6265620] to try `BindProperty` – Edward Jul 12 '18 at 01:33
  • Great! Thank you. – SultanGromma Jul 12 '18 at 01:43