When i try to update records it will create new record instead of updating

I try to combine both create and edit file in one view and controller. I detect when to edit and when to update by checking id. if id==0 then it will create. But when i updating it will always create because the id was always 0. But the populated value of the form is correct. Here is my code.

Here is my Controller:

public IActionResult Upsert(int? id)
{
    if(id == null || id == 0)
    {
        return View();
    }
    Product product = _productRepository.Get(u=>u.Id == id);
    return View(product);
}
[HttpPost]
public IActionResult Upsert(Product product)
{
    if (ModelState.IsValid)
    {
        if (product.Id == 0)
        {
            _productRepository.Add(product);
        }
        else
        {
            _productRepository.Update(product);
        }
        _productRepository.Save();
        return RedirectToAction("Index");
    }
    return View();
}

Here is my Product Model:

using System.ComponentModel.DataAnnotations;
namespace test.Models
{
    public class Product
    {
        public int Id { get; set; }
        [Required]
        public string? Title { get; set; }
        public string? Description { get; set; }
        [Required]
        public string? ISBN { get; set; }
        [Required]
        public string? Author { get; set; }
        [Required]
        [Range(1,1000)]
        [Display(Name ="ListPrice")]
        public int ListPrice { get; set; }


        [Required]
        [Range(1, 1000)]
        [Display(Name = "Price for 1-50")]
        public int Price { get; set; }

        [Required]
        [Range(1, 1000)]
        [Display(Name = "Price for 50+")]
        public int Price50 { get; set; }

        [Required]
        [Range(1, 1000)]
        [Display(Name = "Price for 100+")]
        public int Price100 { get; set; }
    }
}

Here is my View:

@model Product
<div class="row justify-content-center">
    <div class="col-10">
        <div class="card shadow border-0 mt-4">
            <div class="card-header bg-secondary bg-gradient m-lg-0 py3">
                <div class="row">
                    <div class="col-12 text-center">
                        <h2 class="text-white py-2">Update Category</h2>
                    </div>
                </div>
            </div>
            <div class="card-body p-4">
                <form method="post" class="row">
                    <input asp-for="Id" hidden value="0" />
                    <div class="row">
                        <div class="col-10">
                            <div class="border pt-3">
                                <div class="py-2">
                                    <input type="text" asp-for="Title" placeholder="Title" class="form-control form-floating shadow border-0" />
                                    <span asp-validation-for="Title" class="text-danger"></span>
                                </div>
                                <div class="py-2">
                                    <textarea asp-for="Description" placeholder="Discription" class="form-control form-floating shadow border-0"></textarea>

                                </div>
                                <div class="py-2">
                                    <input type="text" asp-for="ISBN" placeholder="ISBN" class="form-control form-floating shadow border-0" />
                                    <span asp-validation-for="ISBN" class="text-danger"></span>
                                </div>
                                <div class="py-2">
                                    <input type="text" asp-for="Author" placeholder="Author" class="form-control form-floating shadow border-0" />
                                    <span asp-validation-for="Author" class="text-danger"></span>
                                </div>
                                <div class="py-2">
                                    <input type="number" asp-for="ListPrice" placeholder="ListPrice" class="form-control form-floating shadow border-0" />
                                    <span asp-validation-for="ListPrice" class="text-danger"></span>
                                </div>
                                <div class="py-2">
                                    <input type="text" asp-for="Price" placeholder="Price for 1-50" class="form-control form-floating shadow border-0" />
                                    <span asp-validation-for="Price" class="text-danger"></span>
                                </div>
                                <div class="py-2">
                                    <input type="text" asp-for="Price50" placeholder="Price for 50+" class="form-control form-floating shadow border-0" />
                                    <span asp-validation-for="Price50" class="text-danger"></span>
                                </div>
                                <div class="py-2">
                                    <input type="text" asp-for="Price100" placeholder="Price for 100+" class="form-control form-floating shadow border-0" />
                                    <span asp-validation-for="Price100" class="text-danger"></span>
                                </div>
                                <div class="row mt-5">
                                    <div class="col-6">
                                        <button type="submit" class="btn btn-primary form-control">Create</button>
                                    </div>
                                    <div class="col-6">
                                        <a asp-controller="Product" asp-action="Index" class="btn btn-outline-primary form-control">Back to List</a>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div> 
                </form>
            </div>
        </div>
    </div>
</div>
@section Scripts{
    <script>
        tinymce.init({
            selector: 'textarea',
            plugins: 'ai tinycomments mentions anchor autolink charmap codesample emoticons image link lists media searchreplace table visualblocks wordcount checklist mediaembed casechange export formatpainter pageembed permanentpen footnotes advtemplate advtable advcode editimage tableofcontents mergetags powerpaste tinymcespellchecker autocorrect a11ychecker typography inlinecss',
            toolbar: 'undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | link image media table mergetags | align lineheight | tinycomments | checklist numlist bullist indent outdent | emoticons charmap | removeformat',
            tinycomments_mode: 'embedded',
            tinycomments_author: 'Author name',
            mergetags_list: [
                { value: 'First.Name', title: 'First Name' },
                { value: 'Email', title: 'Email' },
            ],
            ai_request: (request, respondWith) => respondWith.string(() => Promise.reject("See docs to implement AI Assistant")),
        });
    </script>
    @{
        <partial name="_ValidationScriptsPartial" />
    }
}

I use repository Pattern for database.. repository pattern is fine.. because create is working.. also update is working when i try to do with the seperated edit and update file. but i want to combine both here.

Here i am also providing reposiroty…
Here is my repository interface IRepository:

using System.Linq.Expressions;

namespace test.dataAccess.Repository.IRepository
{
    public interface IRepository<T> where T : class
    {
        IEnumerable<T> GetAll();
        T Get(Expression<Func<T, bool>> filter); 
        void Add(T entity);
        void Remove(T entity);
        void RemoveRange(IEnumerable<T> entity);
    }
}

And here is the implementation of IRepository:

using Microsoft.EntityFrameworkCore;
using System.Linq.Expressions;
using test.dataAccess.Data;
using test.dataAccess.Repository.IRepository;

namespace test.dataAccess.Repository
{
    public class Repository<T> : IRepository<T> where T : class
    {
        private readonly ApplicationDbContext _db;
        internal DbSet<T> dbSet;

        public Repository(ApplicationDbContext db)
        {
            _db = db;
            this.dbSet = _db.Set<T>(); 
        }

        public void Add(T entity)
        {
            dbSet.Add(entity);
        }

        public T Get(Expression<Func<T, bool>> filter)
        {
            IQueryable<T> query = dbSet.Where(filter);
            return query.FirstOrDefault();
        }

        public IEnumerable<T> GetAll()
        {
            IQueryable<T> query = dbSet;
            return query.ToList();
        }

        public void Remove(T entity)
        {
            dbSet.Remove(entity);
        }

        public void RemoveRange(IEnumerable<T> entity)
        {
            dbSet.RemoveRange(entity);
        }
    }
}

Here is the interface of IProductRepository:

using test.Models;

namespace test.dataAccess.Repository.IRepository
{
    public interface IProductRepository : IRepository<Product>
    {
        void Update(Product product);
        void Save();
    }
}

Here is my repository interface IRepository:

using System.Linq.Expressions;

namespace test.dataAccess.Repository.IRepository
{
    public interface IRepository<T> where T : class
    {
        IEnumerable<T> GetAll();
        T Get(Expression<Func<T, bool>> filter); 
        void Add(T entity);
        void Remove(T entity);
        void RemoveRange(IEnumerable<T> entity);
    }
}

And the implementation of IProductRepository:

using test.dataAccess.Data;
using test.dataAccess.Repository.IRepository;
using test.Models;

namespace test.dataAccess.Repository
{
    public class ProductRepository : Repository<Product>, IProductRepository
    {
        private readonly ApplicationDbContext _db;

        public ProductRepository(ApplicationDbContext db) : base(db)
        {
            _db = db;
        }

        public void Save()
        {
            _db.SaveChanges();
        }

        public void Update(Product product)
        {
            _db.Update(product);
        }
    }
}

I am trying to combine both edit and create page. **create is working **but when i try to update data it will create instead of update. when i debug i found that the id value is always zero when the post method is called. so it will create instead of update

  • It shouldn’t be hard to find why Id values are always 0, should it?

    – 

  • “But the populated value of the form is correct “. I guess the form is not sending always 0 on id, right ?

    – 

  • See this link for help: stackoverflow.com/questions/6613044/…

    – 

   public void Update(Product product)
    {
          _db.Entry(product).State = EntityState.Modified;
    }

You may also need to attach the product to the context in order to let it be tracked. so use this line, before changing the State, when needed

 _db.Attach(product);

Leave a Comment