Create a REST API with Attribute Routing in ASP.NET Web API 2

PUT and POST examples

This is just a simple example, exception and error handling is needed. for example, possible null assignment etc ...
PUT Example
        
        private ExamPrepContext _db = new ExamPrepContext();
        
        // PUT: api/Subjects/5
        [HttpPut]
        [Route("{id:int}")]
        [ResponseType(typeof(void))]
        public async Task PutSubject(int id, HttpRequestMessage request)
        {
            var json = request.Content.ReadAsStringAsync().Result;
            Subject subject = JsonConvert.DeserializeObject(json);

            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            
            if (id != subject.SubjectID)
            {
                return BadRequest();
            }

           _db.Subjects.Attach(subject); //_dbis the context object which you have instantiated in your class
            var entry = _db.Entry(subject);
            entry.Property(e => e.Name).IsModified = true;
            entry.Property(e => e.Description).IsModified = true;
            
            //_db.Entry(subject).State = EntityState.Modified;

            try
            {
                await _db.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!SubjectExists(id))
                {
                    return NotFound();
                }
                throw;
            }

            return StatusCode(HttpStatusCode.NoContent);
        }
            
            
        
And the PUT request using POSTMAN.
The "SubjectID" in json and the "id" in URL must be same to satisfy the if condition in the code above.

POST Example

            
            // POST: api/Subjects
        [HttpPost]
        [Route("")]
        [ResponseType(typeof(SubjectDto))]
        public async Task PostSubject(HttpRequestMessage request)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var subject = CreateMessage(request);  // Helper method

            _db.Subjects.Add(subject);
            await _db.SaveChangesAsync();

            return CreatedAtRoute("GetSubject", new { id = subject.SubjectID }, subject);
           // "GetSubject" is the Name of the Get method that, OnSuccess, will return this newly posted resource
        }

        put the Name attribute on your GET method as follows
        
        
        // GET: api/Subjects/5
        [Route("{id:int}", Name = "GetSubject")]
        [ResponseType(typeof(SubjectDto))]
        public async Task GetSubject(int id)
        {
            .............
        }
        
       

Helper method for PostSubject

private Subject CreateMessage(HttpRequestMessage request) { switch (request.Content.Headers.ContentType.MediaType) { case "application/x-www-form-urlencoded": var form = request.Content.ReadAsFormDataAsync().Result; var name = form.GetValues("Title").First(); var description = form.GetValues("Description").First(); var enrolmentdate = Convert.ToDateTime(form.GetValues("ErnollmentDate").First()); var teacherId = int.Parse(form.GetValues("TeacherId").First()); return new Subject { Name = name, Description = description, EnrollmentDate = enrolmentdate, TeacherId = teacherId }; case "application/json": var json = request.Content.ReadAsStringAsync().Result; var res = JsonConvert.DeserializeObject(json); var subject = new Subject { Name = res.Name, TeacherId = res.TeacherId, Description = res.Description, EnrollmentDate = res.ErnollmentDate }; return subject; default: throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } }
And the POST request using POSTMAN.
The "TeacherId" is needed because it assigns a teacher to this subject from the Teacher Model/Table.