I have a [Products]
class, a [Product_Types]
class and a [Products_Product_Types]
class. I have a Razor page for [Products_Product_Types]
and ModelState is only validating one of the two [Required]
ID properties...specifically it's validating the ProductProductType.ProductId
property and ignoring the ProductProductType.ProductTypeId
property. In the code samples below, when I leave the ProductProductType.ProductTypeId
blank I get this error...
The value of 'ProductProductType.ProductTypeId' is unknown when attempting to save changes. This is because the property is also part of a foreign key for which the principal entity in the relationship is not known.
...when instead I expect to see the UnobtrusiveValidation that the ProductProductType.ProductTypeId
dropdown is required.
I fully expect the issue is in my DatabaseContext.cs
file, but I've reviewed all the documentation I can find and I'm not sure how to resolve this error.
Product.cs
public partial class Product
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ProductId { get; set; }
[Display(Name = "Product Name")]
public string? ProductName { get; set; }
}
ProductType.cs
public partial class ProductType
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ProductTypeId { get; set; }
[Display(Name = "Product Type")]
public string? ProductTypeName { get; set; }
}
ProductsProductType.cs
public partial class ProductsProductType
{
[Required]
public int ProductId { get; set; }
[Required]
[Display(Name = "Product Type")]
public int ProductTypeId { get; set; }
public virtual Product? Product { get; set; } = null!;
//public virtual ICollection<Product>? Products { get; set; } = new List<Product>();
public virtual ProductType? ProductType { get; set; } = null!;
//public virtual ICollection<ProductType>? ProductTypes { get; set; } = new List<ProductType>();
}
DatabaseContext.cs
public virtual DbSet<ProductsProductType> ProductsProductTypes{ get; set; }
modelBuilder.Entity<ProductsProductType>(entity =>
{
entity.HasKey(e => new { e.ProductId, e.ProductTypeId }).HasName("PK_Products_Product_Types");
entity.ToTable("Products_Product_Types");
entity.Property(e => e.ProductId).HasColumnName("ProductID");
entity.Property(e => e.ProductTypeID).HasColumnName("ProductTypeID");
entity.HasOne(f => f.Product).WithMany(e => e.ProductsProductTypes)
.HasForeignKey(f => f.ProductId).IsRequired()
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK_Products_Product_Types_Products");
entity.HasOne(f => f.ProductType).WithMany(e => e.ProductsProductTypes)
.HasForeignKey(f => f.ProductTypeID).IsRequired()
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK_Product_Product_Types_Product_Types");
});
/ProductsProductTypes/Create.cshtml
<form method="post" asp-page-handler="ProductProductTypeCreate" data-ajax="true" data-ajax-method="post" data-ajax-success="refreshPartial('GetProductProductTypes', 'ProductProductTypes-container')" data-ajax-failure="ajaxValidationHandler">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="ProductProductType.ProductId" value="@ViewBag.ProductId" />
<div class="form-group">
<label asp-for="ProductProductType.ProductTypeId" class="control-label"></label>
<select asp-for="ProductProductType.ProductTypeId" class="form-control" asp-items="ViewBag.ProductTypes"><option disabled selected>- Select Product Type -</option></select>
<span asp-validation-for="ProductProductType.ProductTypeId" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
<a class="btn btn-secondary" href="javascript:parent.actionPaneClose();">Cancel</a>
</div>
</form>
/ProductsProductTypes/Create.cshtml.cs
[BindProperty]
public ProductsProductType ProductsProductType { get; set; } = default!;
public async Task<IActionResult> OnPostProductProductTypeCreateAsync()
{
if (!ModelState.IsValid || _context.ProductsProductTypes == null || ProductsProductType == null)
{
ViewData["ProductId"] = ProductsProductType.ProductId;
ViewData["ProductTypes"] = new SelectList(_context.ProductTypes, nameof(ProductType.ProductTypeId), nameof(ProductType.ProductTypeName));
return Page();
}
_context.ProductsProductTypes.Add(ProductsProductType);
await _context.SaveChangesAsync();
return Page();
}