Search code examples
c#asp.net-mvcdatabaseasp.net-coreentity-framework-core

ASP.NET Core MVC Automate DateTime fields during the Create/Update


I'm using ASP.NET Core MVC 8, EntityFramework Core, C# and SQL Server 2022.

Unable to automate the CreatedAt & UpdatedAt DateTime fields in my Database during the Create/Update operations.

When I perform the Create operation for the first time I would like to have the CreatedAt field populated with DateTime.UtcNow.

When I perform the Update operation I would like to ONLY add the DateTime.UtcNow value to the UpdatedAt field. The CreatedAt DateTime should not change in the Update Method that was initially created in the Create operation.

I tried to manually add the CreatedAt value in the Create operation along with manually adding the UpdatedAt value in the Update operation. The CreatedAt value does get added during the create operation while the UpdatedAt value is NULL. When I perform the Update operation the CreatedAt value goes to NULL and the UpdatedAt value is populated.

public class Gallery

{
    public Guid Id { get; set; }
    public string Title { get; set; }
    public bool IsPrivate { get; set; }
    public string? AccessCode { get; set; }
    public DateTime CreatedAt { get; set; }
    public DateTime? UpdatedAt { get; set; }
}
public class GalleryVM
{
    public Guid Id { get; set; }

    [Required(ErrorMessage = "Title is required")]
    [Display(Name = "Title")]
    [StringLength(50)]
    [MaxLength(50)]
    public string Title { get; set; }

    [Required(ErrorMessage = "IsPrivate is required")]
    [Display(Name = "Gallery is Private?")]
    public bool IsPrivate { get; set; }

    [Display(Name = "Access Code")]
    [StringLength(16)]
    [MaxLength(16)]
    public string? AccessCode { get; set; }

    public DateTime CreatedAt { get; set; }
    public DateTime? UpdatedAt { get; set; }
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(GalleryVM galleryVM)
{
    Gallery? galleryExists = _db.Galleries.SingleOrDefault(p => p.Title == galleryVM.Title);
    if (galleryExists != null)
    {
        ModelState.AddModelError("Title", galleryExists.Title + " " + "is already in the system.");
    }

    if (ModelState.IsValid)
    {
        var galleryObj = new Gallery();
        {
            galleryObj.Title = galleryVM.Title;
            galleryObj.IsPrivate = galleryVM.IsPrivate;
            galleryObj.AccessCode = galleryVM.AccessCode;
        }

        _db.Galleries.Add(galleryObj);
        _db.SaveChanges();
        TempData["success"] = "Gallery created successfully";
        return RedirectToAction("Index");
    }
    return View(galleryVM);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(GalleryVM galleryVM)
{
    if (ModelState.IsValid)
    {
        var galleryObj = new Gallery();
        {
            galleryObj.Id = galleryVM.Id;
            galleryObj.Title = galleryVM.Title;
            galleryObj.IsPrivate = galleryVM.IsPrivate;
            galleryObj.AccessCode = galleryVM.AccessCode;
        }

        _db.Galleries.Update(galleryObj);
        _db.SaveChanges();
        TempData["success"] = "Gallery updated successfully";
        return RedirectToAction("Index");
    }
    return View(galleryVM);
}

Solution

  • In your Edit action, you should avoid creating a new object because it will have default CreatedAt and null UpdatedAt.

    You could just fetch the existing Gallery and update certain properties.

    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult Edit(GalleryVM galleryVM)
    {
        if (ModelState.IsValid)
        {
            // fetch the existing gallery
            var galleryObj = _db.Galleries.FirstOrDefault(g => g.Id == galleryVM.Id);
    
            if (galleryObj != null)
            {
               // update these properties
               galleryObj.Title = galleryVM.Title;
               galleryObj.IsPrivate = galleryVM.IsPrivate;
               galleryObj.AccessCode = galleryVM.AccessCode;
               
               // assign a new value for updatedAt
               galleryObj.UpdatedAt = DateTime.UtcNow;
            }
    
            _db.Galleries.Update(galleryObj);
            _db.SaveChanges();
            TempData["success"] = "Gallery updated successfully";
            return RedirectToAction("Index");
        }
        return View(galleryVM);
    }