DEV Community

yogini16
yogini16

Posted on

8

10 Bad Practices to Avoid in ASP.NET Core API Controllers

Building APIs is like creating a bridge for different software components to communicate, and it can be a lot of fun. But, just like any other craft, there are some best practices and pitfalls to avoid. In this conversation, we'll take a friendly stroll through 10 common "oopsies" you should steer clear of when building ASP.NET Core API controllers.

Think of these as the friendly neighborhood guidelines that help you keep your API organized, secure, and easily understandable. We'll talk about everything from how to structure your API routes to handling errors with grace, so you can serve up smooth and reliable services to your users. So, let's get started on this API-building adventure!

1. Not Using Attribute Routing: Imagine your API is like a menu in a restaurant. You need to organize it by putting labels (attributes) on each dish (endpoint). Without these labels, it's like a menu with no sections, making it hard to find what you want to order.

// Bad Practice
[Route("api/controller")]
public class MyController : Controller
{
    [HttpGet("getdata")]
    public IActionResult GetData()
    {
        // ...
    }
}

Enter fullscreen mode Exit fullscreen mode
// Good Practice
[Route("api")]
public class MyController : Controller
{
    [HttpGet("data")]
    public IActionResult GetData()
    {
        // ...
    }
}
Enter fullscreen mode Exit fullscreen mode

2. Exposing Sensitive Information: When something goes wrong in your API, you don't want to give away too much information. It's like a detective not revealing all the clues. In your code, you should avoid telling users too much about the errors that occur.

// Bad Practice
[HttpGet("{id}")]
public IActionResult Get(int id)
{
    var data = _dataService.GetDataById(id);
    if (data == null)
    {
        return NotFound($"Data with ID {id} not found.");
    }
    return Ok(data);
}

Enter fullscreen mode Exit fullscreen mode
// Good Practice
[HttpGet("{id}")]
public IActionResult Get(int id)
{
    var data = _dataService.GetDataById(id);
    if (data == null)
    {
        return NotFound();
    }
    return Ok(data);
}

Enter fullscreen mode Exit fullscreen mode

3. Overusing Data Annotations: Think of data annotations like sticky notes on a form. It's better to have a single note (like a class for input) with all the information rather than putting sticky notes all over the place.

// Bad Practice
[HttpPost]
public IActionResult Create([Required] string name, [Range(1, 100)] int age)
{
    // ...
}

Enter fullscreen mode Exit fullscreen mode
// Good Practice
[HttpPost]
public IActionResult Create([FromBody] UserData userData)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    // ...
}

Enter fullscreen mode Exit fullscreen mode

4. Ignoring Input Validation: It's like letting people enter any building without checking who they are. In your code, you should always check and make sure the data people give you is valid and safe.

// Bad Practice
[HttpPost]
public IActionResult Create(UserData userData)
{
    // No input validation
    // ...
}

Enter fullscreen mode Exit fullscreen mode
// Good Practice
[HttpPost]
public IActionResult Create([FromBody] UserData userData)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    // ...
}

Enter fullscreen mode Exit fullscreen mode

5. Overusing HTTP Verb Tunneling: If you use the wrong method (like using a hammer to cut a cake), things can get confusing. Make sure you use the right method (HTTP verb) for each job in your API.

// Bad Practice
[HttpPost("update/{id}")]
public IActionResult Update(int id, [FromBody] UpdateData data)
{
    // ...
}

Enter fullscreen mode Exit fullscreen mode
// Good Practice
[HttpPut("update/{id}")]
public IActionResult Update(int id, [FromBody] UpdateData data)
{
    // ...
}

Enter fullscreen mode Exit fullscreen mode

6. Not Using Dependency Injection: Imagine you need tools to build a treehouse. Instead of asking for tools, you start building your own tools every time. That's what happens when you don't use dependency injection. You should ask for the tools you need.

// Bad Practice
public MyController()
{
    _dataService = new DataService();
}

Enter fullscreen mode Exit fullscreen mode
// Good Practice
public MyController(IDataService dataService)
{
    _dataService = dataService;
}

Enter fullscreen mode Exit fullscreen mode

7. Not Handling Exceptions Gracefully: If your API makes a mistake, it's like a chef burning a dish. You should apologize and offer something else (handle the error gracefully) instead of just serving a burnt dish (an error) to your customers.

// Bad Practice
[HttpGet("{id}")]
public IActionResult Get(int id)
{
    var data = _dataService.GetDataById(id);
    return Ok(data); // No exception handling
}

Enter fullscreen mode Exit fullscreen mode
// Good Practice
[HttpGet("{id}")]
public IActionResult Get(int id)
{
    try
    {
        var data = _dataService.GetDataById(id);
        return Ok(data);
    }
    catch (Exception ex)
    {
        return StatusCode(500, "An error occurred.");
    }
}

Enter fullscreen mode Exit fullscreen mode

8. Not Using ViewModel/DTO: When you show a house to someone, you don't show them all the messy details (domain models) inside. You use a clean and presentable version (ViewModel) of the house. Similarly, in your API, use ViewModel or DTO to present data to the user, not the messy stuff from your database.

// Bad Practice
[HttpGet("{id}")]
public IActionResult Get(int id)
{
    var data = _dbContext.Users.Find(id);
    return Ok(data);
}

Enter fullscreen mode Exit fullscreen mode
// Good Practice
[HttpGet("{id}")]
public IActionResult Get(int id)
{
    var data = _userService.GetUserById(id);
    return Ok(data.ToViewModel());
}

Enter fullscreen mode Exit fullscreen mode

9. Not Implementing Proper Authentication and Authorization: It's like having a nightclub with no bouncer at the door. Anyone can enter, and that can lead to trouble. In your API, you should have a "bouncer" (authentication and authorization) to check who's allowed in.

// Bad Practice
[HttpGet("{id}")]
public IActionResult Get(int id)
{
    var data = _dataService.GetDataById(id);
    return Ok(data);
}

Enter fullscreen mode Exit fullscreen mode
// Good Practice
[HttpGet("{id}")]
[Authorize]
public IActionResult Get(int id)
{
    var data = _dataService.GetDataById(id);
    return Ok(data);
}

Enter fullscreen mode Exit fullscreen mode

10. Not Versioning Your API: Imagine a phone that doesn't get updates. It can become outdated and stop working well. Similarly, your API needs updates too. You should create different versions (like software updates) of your API to keep it running smoothly for all users.

// Bad Practice
[Route("api/controller")]
public class MyController : Controller
{
    [HttpGet("getdata")]
    public IActionResult GetData()
    {
        // ...
    }
}

Enter fullscreen mode Exit fullscreen mode
// Good Practice
[Route("api/v1/controller")]
public class MyController : Controller
{
    [HttpGet("getdata")]
    public IActionResult GetData()
    {
        // ...
    }
}

Enter fullscreen mode Exit fullscreen mode

By avoiding these bad practices, you can make your API more organized, secure, and user-friendly, just like a well-managed restaurant or a smoothly running machine.

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

The Most Contextual AI Development Assistant

Pieces.app image

Our centralized storage agent works on-device, unifying various developer tools to proactively capture and enrich useful materials, streamline collaboration, and solve complex problems through a contextual understanding of your unique workflow.

👥 Ideal for solo developers, teams, and cross-company projects

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay