Welcome to our in-depth tutorial on REST API in .NET. REST (Representational State Transfer) APIs have become fundamental in modern web development, enabling communication between client and server using stateless, cacheable requests. In this guide, we'll explore the intricacies of creating, consuming, and handling REST APIs using .NET, ensuring you're equipped with the knowledge needed to build robust, efficient, and maintainable APIs.
![[探索 5 分鐘] 淺談 ASP.NET MVC 的生命週期](https://i.pinimg.com/originals/c6/09/36/c609363eaac03343e9f95605929c2a69.png)
Whether you're a seasoned developer or just starting your journey, this tutorial caters to all skill levels, guiding you through practical examples and concepts to help you grasp everything from the basics to more advanced topics.

Setting Up Your Environment
Before we dive into the world of REST APIs, let's ensure your development environment is set up correctly.

To create REST APIs in .NET, you'll need to have the following prerequisites: .NET SDK (5.0 or later), a text editor or integrated development environment (IDE) such as Visual Studio or Visual Studio Code, and optional but recommended: Postman for testing API requests and responses.
Creating a New .NET Project

Open your terminal or command prompt, navigate to the directory where you want to create your project, and run:
dotnet new webapi -n RestApiTutorial
The Web API template provides a perfect starting point for building RESTful APIs with ASP.NET Core.
Running Your New Project

Navigate into your newly created project directory and start the application:
cd RestApiTutorial dotnet run
Your API should now be up and running at https://localhost:5001.
Designing RESTful APIs

Before implementing your API, it's essential to understand how to design RESTful endpoints that follow best practices and standards.
This includes using appropriate HTTP methods (GET, POST, PUT, DELETE) based on the CRUD operation you're performing and implementing status codes to provide context about the response.









CRUD Operations and HTTP Methods
Here's a table mapping CRUD operations to their corresponding HTTP methods and web-related actions:
| CRUD Operation | HTTP Method | Web-related action |
|---|---|---|
| Create | POST | Add a new resource |
| Read | GET | Retrieve the list or details of a resource |
| Update | PUT | Replace the entire resource |
| Update (partially) | PATCH | Update one or more properties of an existing resource |
| Delete | DELETE | Remove a resource |
Status Codes
Implementing the appropriate status code helps make your API more interoperable and easier to understand. Some crucial status codes include:
- 200 OK: The request was successful.
- 201 Created: A new resource was created.
- 204 No Content: The request was successful but there's no content to return.
- 400 Bad Request: The client's request was invalid.
- 401 Unauthorized: The client needs to authenticate to access the requested resource.
- 404 Not Found: The requested resource could not be found.
- 500 Internal Server Error: An unexpected error occurred on the server.
Building REST API Endpoints
Now that you're familiar with essential design principles, let's create some RESTful endpoints to handle CRUD operations for a simple fictional "Todos" resource.
Creating a Model Class
First, create a model class Todo.cs with properties for Id, Title, and IsComplete:
public class Todo
{
public int Id { get; set; }
public string Title { get; set; }
public bool IsComplete { get; set; }
}
Implementing RESTful Endpoints
Replace the content of WeatherForecastController.cs with the following:
[ApiController]
[Route("[controller]")]
public class TodoController : ControllerBase
{
private static List<Todo> _todos = new List<Todo>();
private static int _nextId = 1;
[HttpGet]
public ActionResult<IEnumerable<Todo>> GetAllTodos()
{
return _todos;
}
[HttpGet("{id}")]
public ActionResult<Todo> GetTodo(int id)
{
var todo = _todos.Find(t => t.Id == id);
if (todo == null)
{
return NotFound();
}
return todo;
}
[HttpPost]
public ActionResult<Todo> CreateTodo(Todo newTodo)
{
newTodo.Id = _nextId++;
_todos.Add(newTodo);
return CreatedAtAction(nameof(GetTodo), new { id = newTodo.Id }, newTodo);
}
[HttpPut("{id}")]
public IActionResult UpdateTodo(int id, Todo updatedTodo)
{
var existingTodo = _todos.Find(t => t.Id == id);
if (existingTodo == null)
{
return NotFound();
}
existingTodo.Title = updatedTodo.Title;
existingTodo.IsComplete = updatedTodo.IsComplete;
return NoContent();
}
[HttpDelete("{id}")]
public IActionResult DeleteTodo(int id)
{
var existingTodo = _todos.Find(t => t.Id == id);
if (existingTodo == null)
{
return NotFound();
}
_todos.Remove(existingTodo);
return NoContent();
}
}
Congratulations! You've now created a simple yet functional REST API for managing todos. To test your API, use tools like Postman or the built-in testing features in Visual Studio or Visual Studio Code.
Consuming REST APIs with .NET
Now that you've built an API, let's explore how to consume it using .NET and the HttpClient class.
Creating an HttpClient Instance
First, create an HttpClient instance in your application's startup or configuration class:
public async Task ConfigureAsync(IWebHostEnvironment env, IApplicationBuilder app, IWebHostEnvironment webHostEnvironment)
{
// Other configuration...
var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("https://localhost:5001/");
// Other configuration...
}
Consuming REST API Endpoints
Now you can use this HttpClient instance to consume your API's endpoints. Here's an example of how to fetch all todos and handle the response:
var todos = await httpClient.GetAsync("todos");
if (todos.IsSuccessStatusCode)
{
var content = await todos.Content.ReadAsAsync<IEnumerable<Todo>>();
// Process the todos...
}
else
{
// Handle error...
}
You can also make POST, PUT, DELETE requests and handle their responses following a similar approach. Don't forget to set appropriate headers and provide data as needed.
Handling Exceptions and Validation
While not an exhaustive topic, it's essential to cover error handling and input validation when building APIs.
Input Validation
Use model validation attributes to ensure data integrity and perform basic input validation:
public class Todo
{
public int Id { get; set; }
[Required]
[MaxLength(100)]
public string Title { get; set; }
public bool IsComplete { get; set; }
}
Handling Exceptions
ASP.NET Core provides excellent support for automatic exception handling, enabling you to maintain clean and organized code:
[ApiController]
[Route("[controller]")]
[regonister("HIpRoute")] // Apply centralized exception handling
public class TodoController : ControllerBase
{
// Other code...
}
Centralized Exception Handling
To implement centralized exception handling, create a middleware class ExceptionMiddleware.cs:
public class ExceptionMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
public ExceptionMiddleware(RequestDelegate next, ILogger logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "An unhandled exception has occurred.");
await HandleExceptionAsync(context, ex);
}
}
private static Task HandleExceptionAsync(HttpContext context, Exception ex)
{
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.ContentType = "application/json";
var result = JsonConvert.SerializeObject(new { message = ex.Message });
return context.Response.WriteAsync(result);
}
}
Register this middleware in your application's startup class:
public async Task ConfigureAsync(IWebHostEnvironment env, IApplicationBuilder app, IWebHostEnvironment webHostEnvironment, ILogger logger)
{
// Other configuration...
app.UseMiddleware<ExceptionMiddleware>(logger);
// Other configuration...
}
Now, whenever an unhandled exception occurs, the middleware will log the error and return a 500 Internal Server Error response with a JSON message containing the exception's message.
With this comprehensive guide, you should now have a solid foundation for creating, consuming, and handling REST APIs using .NET. Happy coding, and may your APIs serve you well!