admin管理员组

文章数量:1244316

My dev environment is ASP.NET Core 8.0 Razor Pages with EF Core and SQL Server in Visual Studio 2022.

I have two classes, Event and EventType. An Event can have one EventType.

My model classes:

public class Event
{
     public int Id { get; set; }

     [DisplayName("Active")]
     public required bool IsActive { get; set; }

     public required string Title { get; set; }
     public string? SubTitle { get; set; }
     public required string Description { get; set; }

     [DisplayName("Start Date")]
     [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
     public DateOnly StartDate { get; set; }

     [DisplayName("End Date")]
     [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
     public DateOnly EndDate { get; set; }

     [DisplayName("Start Time")]
     [DisplayFormat(DataFormatString = "{0:hh:mm tt}", ApplyFormatInEditMode = true)]
     public required TimeOnly StartTime { get; set; }

     [DisplayName("End Time")]
     [DisplayFormat(DataFormatString = "{0:hh:mm tt}", ApplyFormatInEditMode = true)]
     public TimeOnly? EndTime { get; set; }

     [DisplayName("Registration Ends")]
     [DisplayFormat(DataFormatString = "{0:hh:mm tt}", ApplyFormatInEditMode = true)]
     public required TimeOnly RegistrationEndTime { get; set; }

     [DisplayName("Buy In")]
     [DisplayFormat(DataFormatString = "{0:C2}", ApplyFormatInEditMode = true)]
     public decimal? BuyIn { get; set; }

     [DisplayName("Chip Count")]
     [DisplayFormat(DataFormatString = "{0:C0}", ApplyFormatInEditMode = true)]
     public decimal? ChipCount { get; set; }

     // New property for Blinds, in minutes
     [DisplayName("Blinds (Minutes)")]
     public int? Blinds { get; set; }

     // Custom property to display Blind duration with "minutes" suffix
     [NotMapped]
     public string BlindDisplay => $"{Blinds} minutes";

     public string? Image { get; set; }

     //Navigation Properties
     [ForeignKey("Event")]
     public required int EventTypeId { get; set; }
     [DisplayName("Event Type")]
     public required EventType EventType { get; set; }
}

public class EventType
{
     public int Id { get; set; }
     public required string Description { get; set; }

     [StringLength(7, MinimumLength = 7, ErrorMessage = "Color must be exactly 7 characters long.")]
     [RegularExpression("^#[a-f0-9]{6}$", ErrorMessage = "Color must start with '#' and be followed by 6 lowercase hexadecimal characters.")]
     [DisplayName("Hex Color")]
     public required string Color { get; set; }
}

My code correctly populates a SelectList with EventType (EventTypeSelectList).

Issue: the OnPost method fails model validation when EventType is null.

Here is the OnPost method:

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

     _context.Events.Add(Events);

     await _context.SaveChangesAsync();

     TempData["success"] = "Event Type database entry successfully created.";

     return RedirectToPage("./Index");
 }

Here is the pertinent part of the Create.csthml form

<form method="post">
    <div class="form-group">
        <label asp-for="Events.EventTypeId" class="control-label"></label>
        <select asp-for="Events.EventTypeId" class="form-control" asp-items="Model.EventTypeSelectList"></select>
        <span asp-validation-for="Events.EventType.Id" class="text-danger"></span>
    </div>

    <button type="submit" class="btn btn-primary my-3">Submit</button>
</form>

My dev environment is ASP.NET Core 8.0 Razor Pages with EF Core and SQL Server in Visual Studio 2022.

I have two classes, Event and EventType. An Event can have one EventType.

My model classes:

public class Event
{
     public int Id { get; set; }

     [DisplayName("Active")]
     public required bool IsActive { get; set; }

     public required string Title { get; set; }
     public string? SubTitle { get; set; }
     public required string Description { get; set; }

     [DisplayName("Start Date")]
     [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
     public DateOnly StartDate { get; set; }

     [DisplayName("End Date")]
     [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
     public DateOnly EndDate { get; set; }

     [DisplayName("Start Time")]
     [DisplayFormat(DataFormatString = "{0:hh:mm tt}", ApplyFormatInEditMode = true)]
     public required TimeOnly StartTime { get; set; }

     [DisplayName("End Time")]
     [DisplayFormat(DataFormatString = "{0:hh:mm tt}", ApplyFormatInEditMode = true)]
     public TimeOnly? EndTime { get; set; }

     [DisplayName("Registration Ends")]
     [DisplayFormat(DataFormatString = "{0:hh:mm tt}", ApplyFormatInEditMode = true)]
     public required TimeOnly RegistrationEndTime { get; set; }

     [DisplayName("Buy In")]
     [DisplayFormat(DataFormatString = "{0:C2}", ApplyFormatInEditMode = true)]
     public decimal? BuyIn { get; set; }

     [DisplayName("Chip Count")]
     [DisplayFormat(DataFormatString = "{0:C0}", ApplyFormatInEditMode = true)]
     public decimal? ChipCount { get; set; }

     // New property for Blinds, in minutes
     [DisplayName("Blinds (Minutes)")]
     public int? Blinds { get; set; }

     // Custom property to display Blind duration with "minutes" suffix
     [NotMapped]
     public string BlindDisplay => $"{Blinds} minutes";

     public string? Image { get; set; }

     //Navigation Properties
     [ForeignKey("Event")]
     public required int EventTypeId { get; set; }
     [DisplayName("Event Type")]
     public required EventType EventType { get; set; }
}

public class EventType
{
     public int Id { get; set; }
     public required string Description { get; set; }

     [StringLength(7, MinimumLength = 7, ErrorMessage = "Color must be exactly 7 characters long.")]
     [RegularExpression("^#[a-f0-9]{6}$", ErrorMessage = "Color must start with '#' and be followed by 6 lowercase hexadecimal characters.")]
     [DisplayName("Hex Color")]
     public required string Color { get; set; }
}

My code correctly populates a SelectList with EventType (EventTypeSelectList).

Issue: the OnPost method fails model validation when EventType is null.

Here is the OnPost method:

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

     _context.Events.Add(Events);

     await _context.SaveChangesAsync();

     TempData["success"] = "Event Type database entry successfully created.";

     return RedirectToPage("./Index");
 }

Here is the pertinent part of the Create.csthml form

<form method="post">
    <div class="form-group">
        <label asp-for="Events.EventTypeId" class="control-label"></label>
        <select asp-for="Events.EventTypeId" class="form-control" asp-items="Model.EventTypeSelectList"></select>
        <span asp-validation-for="Events.EventType.Id" class="text-danger"></span>
    </div>

    <button type="submit" class="btn btn-primary my-3">Submit</button>
</form>
Share Improve this question edited Feb 17 at 4:39 marc_s 755k184 gold badges1.4k silver badges1.5k bronze badges asked Feb 17 at 2:46 1 Zero 3 Tech1 Zero 3 Tech 1213 silver badges11 bronze badges 1
  • 2 It is best not to pass entities to views & back. At least for the POST action create a simple ViewModel representation of the properties you can populate to post back, then fetch the relevant entity(ies) to update. Your form element will only populate fields you have input controls for so things like navigation properties will be #null. – Steve Py Commented Feb 17 at 4:15
Add a comment  | 

1 Answer 1

Reset to default 0

As stated in this document

The validation system treats non-nullable parameters or bound properties as if they had a [Required(AllowEmptyStrings = true)] attribute.

You could create a ViewModel with

[DisplayName("Event Type")]
public EventType? EventType { get; set; }

Or just remove it in your new view model

If you want disable this feature in razorpage project,try

builder.Services.AddRazorPages().AddMvcOptions(op=>op.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes=true);

本文标签: cInvalid model state in OnPost with foreign keyStack Overflow