ElectricalStorm
ElectricalStorm

Reputation: 113

Check for duplicates before adding to the database

I have a simple database with brand names. This is my model class:

Brand.cs

[Key]
public int BrandID { get; set; }

[Required(ErrorMessage = "Enter Brandname")]
[Display(Name = "Brandname")]
[StringLength(30)]
public string BrandName { get; set; }

The controller part to post an new brand name in the SQL database looks like this.

Brandscontroller.cs

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("BrandID,BrandName")] Brand brand)
{
    if (ModelState.IsValid)
    {
        _context.Add(brand);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }

    return View(brand);
}

How can I prevent, or give a signal to the user, that a brand name already exists when he adds one that is already in the database?

Upvotes: 1

Views: 2851

Answers (4)

ElectricalStorm
ElectricalStorm

Reputation: 113

Thanks for that you all. Working with the Remote attribute had my preference but I never got this far.

[Remote("IsAlreadyExist", "Home", HttpMethod = "POST", ErrorMessage = "BrandName already exists in database.")]

In case someone else has the same question make sure to change “Home” to the name of the right controller “Brands” in my case.

In the controller itself I had to make the public async Task<IActionResult> IsAlreadyExist(string brandname)synchronous i.e. public IActionResult IsAlreadyExist(string brandname)

Upvotes: 0

Matt Ghafouri
Matt Ghafouri

Reputation: 1577

As other guys have mentioned there are different approaches for implementing this scenario.

I think If you want to prevent duplicating brand name before Adding check the existence of the brand name

if (!_context.Brands.Any(o => o.BrandName == brand.BrandName))
 {
    _context.Add(brand);
     await _context.SaveChangesAsync();
 }

But it's better to add Unique constraints on the persistence side. In which even if the client would pass the server-side validation, the SQL Server will prevent it from duplication.

Upvotes: 1

Zhi Lv
Zhi Lv

Reputation: 21421

You could use the [Remote] validation to check whether the BrandName is exist or not, then show the validation message.

Refer the following code:

public class Brand
{
    [Key]
    public int BrandID { get; set; }

    [Required(ErrorMessage = "Enter Brandname")]
    [Display(Name = "Brandname")]
    [StringLength(30)]
    [Remote("IsAlreadyExist", "Home", HttpMethod = "POST", ErrorMessage = "BrandName already exists in database.")]
    public string BrandName { get; set; }
}

Controller:

    public IActionResult CreateBrand()
    {
        return View();
    }
    [HttpPost]
    public async Task<IActionResult> CreateBrand(Brand brand)
    {
        //insert the brand to the database
        if (ModelState.IsValid)
        {
            _context.Add(brand);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
        return View(brand);
    }
    [HttpPost]
    public async Task<IActionResult> IsAlreadyExist(string brandname)
    {
        //check whether the brandname is exists in the database.
        if (_context.Brands.Any(x => x.BrandName == brandName))
        {
            return Json(false); //the brand name exists in the database.
        }
        return Json(true);
    }

View Page:

@model WebApplication6.Models.Brand

@{
    ViewData["Title"] = "CreateBrand";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<div class="row">
    <div class="col-md-4">
        <form asp-action="CreateBrand">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="BrandName" class="control-label"></label>
                <input asp-for="BrandName" class="form-control" />
                <span asp-validation-for="BrandName" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>
 
@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

The result as below:

enter image description here

More detail information, see [Remote] attribute.

Upvotes: 3

persian-theme
persian-theme

Reputation: 6638

Use Any method in linq which specifies whether there is a set of sequences in the table elements.

with :

if(!_context.Brands.Any(o => o.BrandName == brand.BrandName))

If any item does not match the condition, you can add it.

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("BrandID,BrandName")] Brand brand)
{
  if (ModelState.IsValid)
  {
     if (!_context.Brands.Any(o => o.BrandName == brand.BrandName))
     {
        _context.Add(brand);
         await _context.SaveChangesAsync();
     }
     else
     {
        ViewBag.Message = "already record with this brand name exist";
        return View(brand);
     }
     return RedirectToAction(nameof(Index));
  }
  return View(brand);
}

Upvotes: 2

Related Questions