Rusty0918-B
Rusty0918-B

Reputation: 11

Trouble Binding InputSelect (drop down list) in Blazor from Database

I'm new to Blazor and the next issue I'm having is trying to bind dynamic data from a lookup table onto an InputSelect deal

Here's the Create Code:

@page "/movies/create"
@rendermode InteractiveServer
@using Microsoft.EntityFrameworkCore
@using BlazorWebAppMovies.Models
@using BlazorWebAppMovies.Data
@inject IDbContextFactory<BlazorWebAppMovies.Data.BlazorWebAppMoviesContext> DbFactory
@inject NavigationManager NavigationManager

<PageTitle>Create</PageTitle>

<h1>Create</h1>

<h2>Movie</h2>
<hr />
<div class="row">
    <div class="col-md-4">
        <EditForm method="post" Model="Movie" OnValidSubmit="AddMovie" FormName="create" Enhance>
            <DataAnnotationsValidator />
            <ValidationSummary class="text-danger" role="alert"/>
            <div class="mb-3">
                <label for="title" class="form-label">Title:</label> 
                <InputText id="title" @bind-Value="Movie.Title" class="form-control" /> 
                <ValidationMessage For="() => Movie.Title" class="text-danger" /> 
            </div>        
            <div class="mb-3">
                <label for="releasedate" class="form-label">Release Date:</label> 
                <InputDate id="releasedate" @bind-Value="Movie.ReleaseDate" class="form-control" /> 
                <ValidationMessage For="() => Movie.ReleaseDate" class="text-danger" /> 
            </div>        
            <div class="mb-3">
                <label for="genre" class="form-label">Genre:</label> 
                <InputText id="genre" @bind-Value="Movie.Genre" class="form-control" /> 
                <ValidationMessage For="() => Movie.Genre" class="text-danger" /> 
            </div>        
            <div class="mb-3">
                <label for="price" class="form-label">Price:</label> 
                <InputNumber id="price" @bind-Value="Movie.Price" class="form-control" /> 
                <ValidationMessage For="() => Movie.Price" class="text-danger" /> 
            </div>
            <div class="mb-3">
                <label for="rating" class="form-label">Rating:</label>
                <InputText id="rating" @bind-Value="Movie.Rating" class="form-control" />
                <ValidationMessage For="() => Movie.Rating" class="text-danger" />
            </div>
            <div class="mb-3">
                <label for="moviestarrating" class="form-label:">Movie Star Rating:</label>
                <InputSelect id="moviestarrating" @bind-value="Movie.MovieStarRatingId" class="form-control">
                    <option value="">-- Select --</option>
                    @foreach (var movieStarRating in StarRatings)
                    {
                        <option value="@movieStarRating.Id">@movieStarRating.Descr</option>
                    }
                </InputSelect>
                <ValidationMessage For="() => Movie.MovieStarRating" class="text-danger"></ValidationMessage>
            </div>
            <button type="submit" class="btn btn-primary">Create</button>
        </EditForm>
    </div>
</div>

<div>
    <a href="/movies">Back to List</a>
</div>

@code {
    private BlazorWebAppMoviesContext context = default!;

    [SupplyParameterFromForm]
    private Movie Movie { get; set; } = new();

    private IQueryable<MovieStarRating> StarRatings => context.MovieStarRating;

    // To protect from overposting attacks, see https://learn.microsoft.com/aspnet/core/blazor/forms/#mitigate-overposting-attacks.
    private async Task AddMovie()
    {
        using var context = DbFactory.CreateDbContext();
        context.Movie.Add(Movie);
        await context.SaveChangesAsync();
        NavigationManager.NavigateTo("/movies");
    }
}

It's throwing an "object reference not set to instance of object" or something like that saying that my context object is null. Again, I'm quite new to this.

Upvotes: 0

Views: 14

Answers (1)

Chris K
Chris K

Reputation: 560

There may be a couple of issues here, but you see how you're injecting a DbContextFactory at the top of the page? You haven't created a context from it, so the context is indeed null.

You are creating a context instance in your AddMovie function; you'll need to do the same thing before you can access it elsewhere.

I guess if it were me, I'd do something like this:

@code {
[SupplyParameterFromForm]
private Movie Movie { get; set; } = new();

private IList<MovieStarRating> StarRatings {get; set;} = [];

protected override async Task OnInitializedAsync() {
    await using var context = await DbFactory.CreateDbContextAsync();
    StarRatings = await context.MovieStarRating.ToListAsync();
}

It's not perfect, but I'm running with what you've got. Basically, if you are going to inject a context factory, you need to create a context instance from it. You could do this as above in OnInitializedAsync and populate a list with the movie ratings.

Upvotes: 0

Related Questions