-2

I have created a asp.net core webapi controller named StudentsController.cs using the functionality provided by Visual Studio which is API Controller with actions,using Entity Framework. It implements all the controller methods with return type async Task<ActionResult<>> which is asynchronous method implementation and it is auto generated by Visual Studio

Question is Why it creates all the methods async by its own and how can I create all the methods synchronously using the same auto generate feature of Visual Studio?

async example of controller

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Students.Models;

namespace Students.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class StudentsController : ControllerBase
    {
        private readonly StudentContext _context;

        public StudentsController(StudentContext context)
        {
            _context = context;
        }

        // GET: api/Students
        [HttpGet]
        public async Task<ActionResult<IEnumerable<Student>>> GetStudents()
        {
            return await _context.Students.Include(d => d.Department).ToListAsync();
        }

        // GET: api/Students/5
        [HttpGet("{id}")]
        public async Task<ActionResult<Student>> GetStudent(int id)
        {
            var student = await _context.Students.Include(d => d.Department).FirstOrDefaultAsync(i => i.SId == id);

            if (student == null)
            {
                return NotFound();
            }

            return student;
        }

        // PUT: api/Students/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for
        // more details see https://aka.ms/RazorPagesCRUD.
        [HttpPut("{id}")]
        public async Task<IActionResult> PutStudent(int id, Student student)
        {
            if (id != student.SId)
            {
                return BadRequest();
            }
            _context.Departments.Update(student.Department);
            await _context.SaveChangesAsync();
            _context.Entry(student).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!StudentExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return Ok();
        }
        //[HttpPut]
        //public async Task<IActionResult> PutStudent(Student student)
        //{

        //    _context.Departments.Update(student.Department);
        //    await _context.SaveChangesAsync();
        //    _context.Entry(student).State = EntityState.Modified;

        //    try
        //    {
        //        await _context.SaveChangesAsync();
        //    }
        //    catch (DbUpdateConcurrencyException)
        //    {
        //        if (!StudentExists(student.SId))
        //        {
        //            return NotFound();
        //        }
        //        else
        //        {
        //            throw;
        //        }
        //    }

        //    return Ok();
        //}

        // POST: api/Students
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for
        // more details see https://aka.ms/RazorPagesCRUD.
        [HttpPost]
        public async Task<ActionResult<Student>> PostStudent(Student student)
        {
            _context.Students.Add(student);
            await _context.SaveChangesAsync();

            return CreatedAtAction("GetStudent", new { id = student.SId }, student);
        }


        [HttpPost]
        [Route("StudentList")]
        public async Task<ActionResult<Student>> PostStudentList([FromBody] List<Student> student)
        {
            try
            {
                foreach (Student s in student)
                {
                    _context.Students.Add(s);
                }
                _context.SaveChanges();
                return CreatedAtAction("GetStudents", student, _context.Students.Include(d => d.Department));
            }
            catch(Exception ex)
            {
                return BadRequest();
            }
        }

        // DELETE: api/Students/5
        [HttpDelete("{id}")]
        public async Task<ActionResult<Student>> DeleteStudent(int id)
        {
            var student = await _context.Students.FindAsync(id);
            if (student == null)
            {
                return NotFound();
            }

            _context.Students.Remove(student);
            await _context.SaveChangesAsync();

            return student;
        }

        private bool StudentExists(int id)
        {
            return _context.Students.Any(e => e.SId == id);
        }
    }
}

sync example of controller

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CourseCRUD.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace CourseCRUD.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class SubjectController : Controller
    {
        private readonly CourseContext _context;

        public SubjectController(CourseContext context)
        {
            _context = context;
        }

        [HttpGet]
        // GET:api/subject
        public IActionResult GetSubjects()
        {
            try
            {
                var subjects = _context.subjects.ToList();
                return Ok(subjects);
            }
            catch
            {
                return BadRequest();
            }
        }
        [HttpPost]
        public IActionResult AddSubject([FromBody]Subject subject)
        {

            try
            {
                _context.subjects.Add(subject);
                _context.SaveChanges();
                return CreatedAtAction("GetSubjets", subject);
            }
            catch
            {
                return BadRequest();
            }
        }
        [HttpGet("{id}")]
      public IActionResult GetSuject(int id)
        {
            try
            {
                var subject = _context.subjects.Find(id);
                return Ok(subject);
            }
            catch
            {
                return BadRequest();
            }
        }

        [HttpPut("id")]

        [HttpPut("{id}")]
        public IActionResult UpdateSubject(int id, Subject subject)
        {
            if (id != subject.SubjectId)
            {
                return BadRequest();
            }
            _context.Entry(subject).State = EntityState.Modified;
            try
            {
                _context.SaveChanges();
                return Ok(subject);
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!SubjectDetailExist(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

        }

        private bool SubjectDetailExist(int id)
        {
            throw new NotImplementedException();
        }
        [HttpDelete("{id}")]
        public IActionResult DeleteSubject(int id)
        {
            var result = _context.subjects.Find(id);
            if (result == null)
            {
                return NotFound();
            }

            _context.subjects.Remove(result);

            try
            {
                _context.SaveChanges();
                return Ok(result);
            }
            catch
            {
                return BadRequest();
            }
        }

    }
}```
Jay Bhiyani
  • 313
  • 1
  • 4
  • 14
  • 4
    Probably because most web applications use database calls, calls to other services, etc. so it allows a server to handle more requests if you use async calls (since you're not blocking a thread while waiting for a response from the database, etc.). That would be my guess. Why do you want to make all of your methods sync? – ProgrammingLlama Dec 06 '19 at 02:53
  • Can you please elaborate your answer and show how can I create all methods synchronously as given in example of sync controller using the same auto code generate feature of Visual Studio?**And** I want to create all sync because this implementation is part of my training as trainee in a company and I have been asked to differentiate these both types of implementation – Jay Bhiyani Dec 06 '19 at 02:55
  • 2
    Again: I'm simply guessing why they are all _async_. I have no idea how you can do that, and I don't really understand _why_ you want to. – ProgrammingLlama Dec 06 '19 at 02:56
  • *"Why it creates all the methods async"* - Because It's Better™ – Gabriel Luci Dec 06 '19 at 17:52
  • If you've been given a task to differentiate two types of controllers, then just create an `aysnc` and create a copy you can change it into `sync`.... why would you make more work for yourself to create everything twice? – Erik Philips Dec 09 '19 at 07:16

2 Answers2

0

it's a long time since I did anything with t4 templates so a bit rusty but you should perhaps start here

https://learn.microsoft.com/en-us/visualstudio/modeling/code-generation-and-t4-text-templates?view=vs-2019

You specify templates in text files and use rules to generate the required code.

<#@ output extension=".cs" #>
<#@ assembly name="System.Xml" #>
<#
 System.Xml.XmlDocument configurationData = ...; // Read a data file here.
#>
namespace Fabrikam.<#= configurationData.SelectSingleNode("jobName").Value #>
{
  ... // More code here.
}

Depending on the values in the XML file, the generated .cs file would resemble the following:

namespace Fabrikam.FirstJob
{
  ... // More code here.
}

I don't know if controller scaffolding uses t4 templates but it wouldn't suprise me.. or something similar.

stemixrf
  • 474
  • 5
  • 10
0

The async actions are generated by templates of scaffolding which locates in path similar to C:\ProgramFiles\dotnet\sdk\NuGetFallbackFolder\microsoft.visualstudio.web.codegenerators.mvc\2.0.3\Templates

You could change the template manually.Refer to https://stackoverflow.com/a/39503291/10158551

Ryan
  • 19,118
  • 10
  • 37
  • 53