Create a REST API in C# Using ChatGPT
ChatGPT is a large language model developed by OpenAI. In this article, readers will use a tutorial to learn how to use ChatGPT to create a REST API in C#.
Join the DZone community and get the full member experience.
Join For FreeChatGPT is a cutting-edge natural language processing model created by OpenAI, an artificial intelligence research center founded by Elon Musk, Sam Altman, and Greg Brockman. The model was announced in June 2018, and has continuously been modified and upgraded, with the most recent version, GPT-3, being released in 2020. ChatGPT was made from GPT-3, and was released back in 2022. The “GPT” in ChatGPT stands for “Generative Pre-trained Transformer,” a reference to the model’s deep learning architecture. ChatGPT essentially uses massive amounts of text data to “learn” the intricacies of human language, allowing it to create replies that are frequently impossible to differentiate from those of humans. The ChatGPT technology is based on a type of neural network known as a transformer, which is well-suited to natural language processing applications.
ChatGPT’s capacity to create high-quality output to a wide range of prompts you give in the chat box is one of its key features. The response you get feels like it has been generated by a human. You can also specify the conditions of your request. The model was trained on a vast corpus of text, so it can rely on a wide range of data to answer questions, provide information, or participate in casual conversation generated from its neural network. It is crucial to remember; however, that ChatGPT is not flawless. When faced with suggestions that are beyond the model’s area of knowledge, the model may provide illogical or unsuitable replies. ChatGPT usage is sometimes high, and, because of this, there can sometimes be a limit to how many queries you can send.
Now, since the main purpose of this article is to give you a comprehensive and hands-on example of how ChatGPT can be used for generating code for a REST API, let’s first understand what a REST API is. A REST API is a type of web service that allows two computer systems to communicate with one another over the internet by following a set of standardized rules. It follows the REST architecture, which is known for its stateless and client-server nature. A REST API works by the client sending a request to the server using a specific URL and HTTP method, such as GET
, POST
, PUT
, or DELETE
, and the server responding with a message containing the requested data or indicating whether the requested operation was successful. REST APIs are widely used in modern web and mobile applications because they provide a standardized and efficient method of exchanging data between systems. You can usually learn more about a specific API by reading through the documentation. Some APIs are commercial and usually have different pricing plans. This also means that making a request requires a bearer token.
Now comes the interesting part—creating a fully functional REST API in C# for managing students with the help of ChatGPT, so keep on reading.
Creating the API
In this section, we’ll let ChatGPT code a fully functional REST API for managing students, including creation, deletion, and modification of student records. To do this, we should have a “students controller,” which would have the API endpoint, and a “students class,” which would have the needed fields such as “Id,” “name,” and “age.” The only job we have here is to make logical, well-structured queries which would become gradually more complex as we build the API part by part. Let’s begin.
Write a REST API for Managing Students in C#
Here’s an example of a RESTful API for managing students in C#. This API will use the HTTP methods GET
, POST
, PUT
, and DELETE
to perform CRUD (Create, Read, Update, Delete) operations on a list of student resources.
First, let’s define a “student class” to represent a student resource:
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
}
Next, let’s create a StudentsController
class to handle the HTTP requests:
[Route("api/students")]
public class StudentsController : Controller
{
private static List<Student> students = new List<Student>
{
new Student { Id = 1, Name = "John Smith", Age = 20, Email = "john.smith@example.com" },
new Student { Id = 2, Name = "Jane Doe", Age = 19, Email = "jane.doe@example.com" },
new Student { Id = 3, Name = "Bob Johnson", Age = 21, Email = "bob.johnson@example.com" }
};
[HttpGet]
public IActionResult GetAllStudents()
{
return Ok(students);
}
[HttpGet("{id}")]
public IActionResult GetStudent(int id)
{
var student = students.FirstOrDefault(s => s.Id == id);
if (student == null)
{
return NotFound();
}
return Ok(student);
}
[HttpPost]
public IActionResult CreateStudent([FromBody] Student student)
{
student.Id = students.Max(s => s.Id) + 1;
students.Add(student);
return CreatedAtAction(nameof(GetStudent), new { id = student.Id }, student);
}
[HttpPut("{id}")]
public IActionResult UpdateStudent(int id, [FromBody] Student student)
{
var existingStudent = students.FirstOrDefault(s => s.Id == id);
if (existingStudent == null)
{
return NotFound();
}
existingStudent.Name = student.Name;
existingStudent.Age = student.Age;
existingStudent.Email = student.Email;
return NoContent();
}
[HttpDelete("{id}")]
public IActionResult DeleteStudent(int id)
{
var student = students.FirstOrDefault(s => s.Id == id);
if (student == null)
{
return NotFound();
}
students.Remove(student);
return NoContent();
}
This StudentsController
class defines the following endpoints:
GET /api/students
: Returns a list of all students.GET /api/students/{id}
: Returns a single student resource by ID.POST /api/students
: Creates a new student resource.PUT /api/students/{id}
: Updates an existing student resource by ID.DELETE /api/students/{id}
: Deletes an existing student resource by ID.
Note: we are using the [FromBody]
attribute to deserialize the request body into a “student object” for the CreateStudent
and UpdateStudent
methods.
Also note that the students list is static and initialized with some sample data. In a real-world scenario, this data would likely be stored in a database or some other persistent storage.
Finally, we’re using the HTTP status codes 200 OK, 201 Created, 204 No Content, and 404 Not Found to indicate the outcome of each operation.
Add More Properties to the Student Class
Here’s an updated version of the “student class” with some additional properties:
public class Student
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public string Email { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
}
In this updated version of the class, we’ve added the following properties:
FirstName
: The first name of the student.LastName
: The last name of the student.Address
: The street address of the student.City
: The city where the student lives.State
: The state where the student lives.ZipCode
: The ZIP code of the student’s address.
These additional properties can provide more information about the student and can be useful for filtering, sorting, and searching operations in the API.
Add Another Property to the Student Class
Regarding the Subjects the Student Has Taken
Here’s an updated version of the “student class” with an additional property for the subjects the student has taken:
public class Student
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public string Email { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public List<string> SubjectsTaken { get; set; }
}
In this updated version of the class, we’ve added a property called SubjectsTaken
, which is a list of strings representing the names of the subjects the student has taken. This property can be useful for querying and filtering students by the subjects they have studied.
You can add subjects to the list like this:
var student = new Student
{
Id = 1,
FirstName = "John",
LastName = "Doe",
Age = 20,
Email = "john.doe@example.com",
Address = "123 Main St",
City = "Anytown",
State = "CA",
ZipCode = "12345",
SubjectsTaken = new List<string> { "Math", "Science", "History" }
};
And, you can retrieve the list of subjects for a given student like this:
var student = GetStudent(1);
var subjects = student.SubjectsTaken;
Change SubjectTaken to an Object Named Subject
Containing the Properties Id, Name, Teacher, and Credits
Here’s an updated version of the “student class” where the SubjectsTaken
property is replaced with a new object subject containing the Id
, Name
, Teacher
, and Credits
properties:
public class Subject
{
public int Id { get; set; }
public string Name { get; set; }
public string Teacher { get; set; }
public int Credits { get; set; }
}
public class Student
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public string Email { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public List<Subject> SubjectsTaken { get; set; }
}
In this updated version of the class, we’ve replaced the SubjectsTaken
property with a new object subject containing the Id
, Name
, Teacher
, and Credits
properties. This new structure can provide more detailed information about the subjects the student has taken, and it can be useful for filtering and querying students based on specific subject properties.
You can add a subject to the SubjectsTaken
list like this:
var student = new Student
{
Id = 1,
FirstName = "John",
LastName = "Doe",
Age = 20,
Email = "john.doe@example.com",
Address = "123 Main St",
City = "Anytown",
State = "CA",
ZipCode = "12345",
SubjectsTaken = new List<Subject>
{
new Subject { Id = 1, Name = "Math", Teacher = "Mr. Smith", Credits = 4 },
new Subject { Id = 2, Name = "Science", Teacher = "Ms. Jones", Credits = 3 }
}
};
And you can retrieve the list of subjects for a given student like this:
var student = GetStudent(1);
var subjects = student.SubjectsTaken;
Change the State Property in the Student Class to Enum
public enum State
{
AL, AK, AZ, AR, CA, CO, CT, DE, FL, GA, HI, ID, IL, IN, IA, KS, KY, LA, ME,
MD, MA, MI, MN, MS, MO, MT, NE, NV, NH, NJ, NM, NY, NC, ND, OH, OK, OR, PA,
RI, SC, SD, TN, TX, UT, VT, VA, WA, WV, WI, WY
}
public class Student
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public string Email { get; set; }
public string Address { get; set; }
public string City { get; set; }
public State State { get; set; }
public string ZipCode { get; set; }
public List<Subject> SubjectsTaken { get; set; }
}
In this updated version of the class, we’ve replaced the State
property with an enum called State
. The State
enum contains a list of state abbreviations and provides type safety for the State
property.
You can set the State
property for a student like this:
var student = new Student
{
Id = 1,
FirstName = "John",
LastName = "Doe",
Age = 20,
Email = "john.doe@example.com",
Address = "123 Main St",
City = "Anytown",
State = State.CA,
ZipCode = "12345",
SubjectsTaken = new List<Subject>
{
new Subject { Id = 1, Name = "Math", Teacher = "Mr. Smith", Credits = 4 },
new Subject { Id = 2, Name = "Science", Teacher = "Ms. Jones", Credits = 3 }
}
};
And you can retrieve the State
property for a given student like this:
var student = GetStudent(1);
var state = student.State;
Add Validation for Making the ID, FirstName, and Email Mandatory
Here’s an updated version of the student class that includes validation for the Id
, FirstName
, and Email
properties:
public class Student
{
private int _id;
private string _firstName;
private string _email;
public int Id
{
get { return _id; }
set
{
if (value <= 0)
{
throw new ArgumentException("Id must be greater than zero.");
}
_id = value;
}
}
public string FirstName
{
get { return _firstName; }
set
{
if (string.IsNullOrEmpty(value))
{
throw new ArgumentException("First name cannot be null or empty.");
}
_firstName = value;
}
}
public string LastName { get; set; }
public int Age { get; set; }
public string Email
{
get { return _email; }
set
{
if (string.IsNullOrEmpty(value))
{
throw new ArgumentException("Email cannot be null or empty.");
}
_email = value;
}
}
public string Address { get; set; }
public string City { get; set; }
public State State { get; set; }
public string ZipCode { get; set; }
public List<Subject> SubjectsTaken { get; set; }
}
In this updated version of the class, we’ve added private fields for the Id
, FirstName
, and Email
properties and added validation logic to their corresponding setter methods. The Id
property must be greater than zero, and the FirstName
and Email
properties cannot be null or empty. If any of these validation checks fail, an ArgumentException
will be thrown.
You can create a new student object like this:
var student = new Student
{
Id = 1,
FirstName = "John",
LastName = "Doe",
Age = 20,
Email = "john.doe@example.com",
Address = "123 Main St",
City = "Anytown",
State = State.CA,
ZipCode = "12345",
SubjectsTaken = new List<Subject>
{
new Subject { Id = 1, Name = "Math", Teacher = "Mr. Smith", Credits = 4 },
new Subject { Id = 2, Name = "Science", Teacher = "Ms. Jones", Credits = 3 }
}
};
If you attempt to create a new student object with invalid data, an ArgumentException
will be thrown:
var invalidStudent = new Student
{
Id = 0, // throws ArgumentException
FirstName = "", // throws ArgumentException
LastName = "Doe",
Age = 20,
Email = "", // throws ArgumentException
Address = "123 Main St",
City = "Anytown",
State = State.CA,
ZipCode = "12345",
SubjectsTaken = new List<Subject>()
};
Make the Students Controller Asynchronous
Here’s an updated version of the StudentsController
class that makes use of asynchronous methods:
[ApiController]
[Route("api/[controller]")]
public class StudentsController : ControllerBase
{
private readonly IStudentRepository _studentRepository;
public StudentsController(IStudentRepository studentRepository)
{
_studentRepository = studentRepository;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<Student>>> GetAllStudents()
{
var students = await _studentRepository.GetAllStudentsAsync();
return Ok(students);
}
[HttpGet("{id}")]
public async Task<ActionResult<Student>> GetStudentById(int id)
{
var student = await _studentRepository.GetStudentByIdAsync(id);
if (student == null)
{
return NotFound();
}
return Ok(student);
}
[HttpPost]
public async Task<ActionResult<Student>> CreateStudent(Student student)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
await _studentRepository.AddStudentAsync(student);
return CreatedAtAction(nameof(GetStudentById), new { id = student.Id }, student);
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateStudent(int id, Student student)
{
if (id != student.Id)
{
return BadRequest();
}
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var existingStudent = await _studentRepository.GetStudentByIdAsync(id);
if (existingStudent == null)
{
return NotFound();
}
await _studentRepository.UpdateStudentAsync(student);
return NoContent();
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteStudent(int id)
{
var existingStudent = await _studentRepository.GetStudentByIdAsync(id);
if (existingStudent == null)
{
return NotFound();
}
await _studentRepository.DeleteStudentAsync(existingStudent);
return NoContent();
}
}
In this updated version of the class, we’ve added the async keyword to the action methods that interact with the IStudentRepository
. We’ve also added the await keyword before calling the asynchronous methods to wait for the result to complete before continuing.
If the action method returns a value, we’ve wrapped it in the ActionResult<T>
type, where “T” is the type of the returned value. If an error occurs, we return an appropriate ActionResult
, such as BadRequest()
or NotFound()
.
Note: the IStudentRepository
interface must also be updated to include asynchronous versions of its methods. Here’s an example of what the updated IStudentRepository
might look like:
public interface IStudentRepository
{
Task<IEnumerable<Student>> GetAllStudentsAsync();
Task<Student> GetStudentByIdAsync(int id);
Task AddStudentAsync(Student student);
Task UpdateStudentAsync(Student student);
Task DeleteStudentAsync(Student student);
}
In this version of the interface, we’ve added the async keyword to each method and changed the return types to Task<T>
, where “T” is the type of the returned value. This allows the calling code to use the await keyword to wait for the method to complete.
Conclusion
In this article, we used ChatGPT to build a REST API for managing students using ASP.NET Core and C# programming language. This API is a basic implementation of a web service that implements CRUD (Create, Read, Update, Delete) operations for managing a list of students by providing several distinct endpoints. ChatGPT was able to add basic validation to the student class, as well as make the code asynchronous. Apart from that, this AI tool easily changed the type of the state property to enum and created a whole new class when we needed a new object for the subject property. All in all, it did a great job and created fully functional classes, a controller, and a repository.
ChatGPT, in my opinion, should be taken seriously as a programming aid, especially for simple and repetitive tasks, since it can automate them and recommend more efficient and effective programming techniques. As a result, it can enable programmers to save time, and they can use that time to solve more challenging and creative programming tasks. However, I also believe it’s important to use it as a complement to human programming skills rather than a replacement since it is oftentimes incapable of providing optimal solutions in complex situations. As for its power, I am confident this article was enough to prove the power of ChatGPT even to the biggest skeptics out there. If you are a developer, you can use ChatGPT for other various use cases, such as to validate or test code. You can even use it for code generation in Python. Many companies are already looking for ways to integrate ChatGPT to their platform.
In summary, ChatGPT is an impressive AI language model that has the potential to revolutionize the way we approach programming, and while it may not be able to completely replace human programmers, it can certainly be considered a valuable resource.
Opinions expressed by DZone contributors are their own.
Comments