简体   繁体   中英

HttpPut when working with DTO and AutoMapper in ASP.NET Core API

In my API project I have Course model such:

 public class Course
 {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int CourseId { get; set; }
        public string CourseName { get; set; }
        [ForeignKey("Department")]
        public int DepartmentId { get; set; }
        public Department Department { get; set; }
        public ICollection<CourseEnrollment> CourseEnrollments { get; set; }
        public ICollection<CourseAssignment> CourseAssignments { get; set; }
 }

I want to applied the DTO and AutoMapper concepts to my update course action using HttpPut , so I created a CourseUpdateDto DTO such:

public class CourseUpdateDTO
{
     [Required]
     public int CourseId { get; set; }
     [Required, MaxLength(100)]
     public string CourseName { get; set; }
     [Required]
     public int DepartmentID { get; set; }
}

This is my AutoMapper configuration:

 CreateMap<CourseUpdateDTO, Course>()
          .ForMember(dest => dest.CourseId,
                     opts => opts.MapFrom(src => src.CourseId))
          .ForMember(dest => dest.CourseName,
                     opts => opts.MapFrom(src => src.CourseName))
          .ForMember(dest => dest.DepartmentId,
                     opts => opts.MapFrom(src => src.DepartmentID));

And finally this is my trial to update course:

[HttpPut("{id:int}")]
public ActionResult PutCourse(int id, [FromBody] CourseUpdateDTO courseDto)
{
       if (courseDto is null)
       {
           return BadRequest();
       }

       var entity = new Course
       {
            CourseId = id,
            CourseName = courseDto.CourseName,
            DepartmentId = courseDto.DepartmentID
       };

       _mapper.Map(courseDto, entity);

       try
       {
           _unitOfWork.SaveChangesAsync();
       }
       catch (DbUpdateConcurrencyException)
       {
           ModelState.AddModelError(nameof(PutCourse), "unable to save changes");
           return StatusCode(500, ModelState);
       }

       return NoContent();
}

When I tested this action using Postman, it returned status of 204 But the course has not changed. Am I wrong anywhere? Im new to this concept so hope someone configure that out to me.

You didn't call the update method before saving. After mapping call update method and after call SaveChangesAsync();

First of all, you need to get an exact record from your database (here I mean get it from DbContext ), then map incoming data to your entity.

To make it works, you have to apply some changes like below:

var entity=_context.Cources.SingleOrDefault(x=>x.Id=id);

// check if it is not null 

_mapper.Map(courseDto, entity);
 _context.Entity(entity).Status = Status.Modified;
_context.SaveChangesAsync();

After got some suggestions from people in this post. I've changed the original action

[HttpPut("{id:int}")]
public ActionResult PutCourse(int id, [FromBody] CourseUpdateDTO courseDto)
{
       if (courseDto is null)
       {
           return BadRequest();
       }

       var entity = new Course
       {
            CourseId = id,
            CourseName = courseDto.CourseName,
            DepartmentId = courseDto.DepartmentID
       };

       _mapper.Map(courseDto, entity);

       try
       {
           _unitOfWork.SaveChangesAsync();
       }
       catch (DbUpdateConcurrencyException)
       {
           ModelState.AddModelError(nameof(PutCourse), "unable to save changes");
           return StatusCode(500, ModelState);
       }

       return NoContent();
}

to this

[HttpPut("{id:int}")]
        public async Task<ActionResult> PutCourse(int id, [FromBody] CourseUpdateDTO courseDto)
        {
            if (courseDto is null)
            {
                return BadRequest();
            }

            var entity = _unitOfWork.CourseService.Get(id);
            if (entity is null)
            {
                return NotFound();
            }

            _mapper.Map(courseDto, entity);
            try
            {
                _unitOfWork.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                ModelState.AddModelError(nameof(PutCourse), "unable to save changes");
                return StatusCode(500, ModelState);
            }

            return NoContent();
        }

However, it still doesn't work. But I realized the problem might be in the _unitOfWork.SaveChangesAsync(); that used async/await . but I didn't define the function as async. So I changed the function to async and add await await _unitOfWork.SaveChangesAsync(); . Finally, it worked! Very thanks for your warm support!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM