ASP.NET MVC 4, EF5, Code First, SQL Server 2012 Express
What is best practice to enforce a unique value in a model? I have a places class that has a
Faced similar issue in my ASP.NET Razor Page Project. Creating custom UniqueDataAttribute didn't work, because on Edit, it would throw an error if you're not changing unique field.
I needed unique Book Name. This is how I resolved:
Code:
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity()
.HasIndex(u => u.Name)
.IsUnique();
}
Code:
// Validate uniqueness of Name field in database.
// If validation is done on existing record, pass the id of the record.
// Else, if validating new record Name, then id is set to dummy key integer -1
public static bool UniqueNameInDb(this string data, ApplicationDbContext db, int id = -1)
{
var duplicateData = from o in db.Book
where o.Name == data && o.Id != id
select o;
if(duplicateData.Any())
{
return false;
}
return true;
}
}
Create model:
public async Task OnPost()
{
if(ModelState.IsValid)
{
if (!Book.Name.UniqueNameInDb(_db)) //<--Uniqueness validation
{
ModelState.AddModelError("Book.Name", "Name already exist"); //<-- Add error to the ModelState, that would be displayed in view.
return Page();
}
await _db.Book.AddAsync(Book);
await _db.SaveChangesAsync();
return RedirectToPage("Index");
}
else
{
return Page();
}
}
Edit Model:
public async Task OnPost()
{
if(ModelState.IsValid)
{
var bookFromDb = await _db.Book.FindAsync(Book.Id);
if (!Book.Name.UniqueNameInDb(_db, Book.Id)) //<--Uniqueness validation
{
ModelState.AddModelError("Book.Name", "Name already exist"); //<-- Add error to the ModelState, that would be displayed in view.
return Page();
}
bookFromDb.Name = Book.Name;
bookFromDb.Author = Book.Author;
await _db.SaveChangesAsync();
return RedirectToPage("Index");
}
return Page();
}
PS: Your Razor view should've Model validation set on in the form to capture and display the error.
i.e,
and below validation against the field.