I'm developing a Blazor Server app called MovieDock for my school project. Where users can log in, register, browse movies, and comment/rate movies. While login/registration and the movie gallery work, comments and ratings (1-5) are not saved to the database when submitted from the movie details page. Manually inserting data via SQL works, and the UI updates correctly. Below are key code snippets. What am I missing? I added breakpoint to the SubmitComments and SubmitRatings tasks, yet still the same silence.I am connected to the correct connection string.Everything Loads as it should. Movies show up, no errors.
// Comment.cs
public class Comment {
public int Id { get; set; }
[Required][StringLength(1000, MinimumLength = 10)]
public string Text { get; set; }
public DateTime CreatedDate { get; set; }
[Required] public string UserId { get; set; }
[Required] public int MovieId { get; set; }
public ApplicationUser User { get; set; }
public Movie Movie { get; set; }
}
// Rating.cs
public class Rating {
public int Id { get; set; }
[Required][Range(1, 5)] public int Value { get; set; }
[Required] public string UserId { get; set; }
[Required] public int MovieId { get; set; }
public DateTime CreatedDate { get; set; }
public ApplicationUser User { get; set; }
public Movie Movie { get; set; }
}```
Movie Model
public class Movie {
public int Id { get; set; }
// ...other properties
public List\<Comment\> Comments { get; set; } = new();
public List\<Rating\> Ratings { get; set; } = new();
\[NotMapped\] public double AverageRating =\> Ratings.Any() ? Ratings.Average(r =\> r.Value) : 0;
}
DbContext Configuration
public class ApplicationDbContext : IdentityDbContext<ApplicationUser> {
public DbSet<Comment> Comments { get; set; }
public DbSet<Rating> Ratings { get; set; }
// ...other DbSets
protected override void OnModelCreating(ModelBuilder modelBuilder) {
modelBuilder.Entity<Comment>().HasOne(c => c.User).WithMany().OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<Rating>().HasOne(r => r.User).WithMany().OnDelete(DeleteBehavior.Restrict);
}
}
MovieService Methods
public async Task AddCommentAsync(Comment comment) {
_context.Comments.Add(comment);
await _context.SaveChangesAsync();
}
public async Task AddRatingAsync(Rating rating) {
var existing = await _context.Ratings
.FirstOrDefaultAsync(r => r.UserId == rating.UserId && r.MovieId == rating.MovieId);
if (existing != null) existing.Value = rating.Value;
else _context.Ratings.Add(rating);
await _context.SaveChangesAsync();
}
public async Task<Movie> GetMovieByIdAsync(int movieId) {
return await _context.Movies
.AsNoTracking()
.Include(m => m.Reviews).ThenInclude(r => r.User) // Missing Comments/Ratings?
.FirstOrDefaultAsync(m => m.Id == movieId);
}
And code for MovieDetails.razor
@code {
[Parameter]
public int movieId { get; set; }
private Movie movie;
private int currentRating;
private int inputNumber;
private string newReviewText = "";
private bool showError;
private string errorMessage = "";
private void UpdateFromNumber()
{
if (inputNumber >= 1 && inputNumber <= 5)
{
currentRating = inputNumber;
showError = false;
}
else
{
showError = true;
errorMessage = "Invalid value! Enter a number between 1 and 5.";
currentRating = 0;
}
}
private async Task HandleConfirmNumber()
{
if (inputNumber >= 1 && inputNumber <= 5)
{
currentRating = inputNumber;
showError = false;
// Added for visual feedback
await Task.Delay(50);
UpdateStarsVisual();
}
else
{
showError = true;
errorMessage = "Invalid value! Enter a number between 1 and 5.";
currentRating = 0;
}
StateHasChanged();
}
private void UpdateStarsVisual()
{
Console.WriteLine($"Current rating: {currentRating}");
}
private async Task SubmitReview()
{
showError = false;
try
{
// Highlighted validation
if (currentRating < 1 || currentRating > 5)
{
errorMessage = "Click on the stars for rating!";
showError = true;
return;
}
if (string.IsNullOrWhiteSpace(newReviewText) || newReviewText.Trim().Length < 10)
{
errorMessage = "Review must have at least 10 characters!";
showError = true;
return;
}
var authState = await AuthStateProvider.GetAuthenticationStateAsync();
var user = authState.User;
if (user.Identity.IsAuthenticated)
{
var userId = user.FindFirstValue(ClaimTypes.NameIdentifier);
var newReview = new Review
{
MovieId = movieId,
UserId = userId,
Rating = currentRating,
Comment = newReviewText.Trim(),
CreatedDate = DateTime.UtcNow
};
await MovieService.AddReviewAsync(newReview);
movie = null; // Reset movie
StateHasChanged();
await Task.Delay(100); // Short delay
movie = await MovieService.GetMovieByIdAsync(movieId);
// Reset form
currentRating = 0;
inputNumber = 0;
newReviewText = "";
showError = false;
StateHasChanged();
}
}
catch (Exception ex)
{
errorMessage = $"Action failed: {ex.Message}";
showError = true;
Console.WriteLine($"Error: {ex}");
}
}
}
Sorry for it being so long, but I have spent a long time trying to figure this out, changing things, yet still the same result.