<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Elif Güzen</title>
    <description>The latest articles on DEV Community by Elif Güzen (@guzen).</description>
    <link>https://dev.to/guzen</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3020740%2Fd14af5e8-d085-4637-a945-45eebf27d47c.jpg</url>
      <title>DEV Community: Elif Güzen</title>
      <link>https://dev.to/guzen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/guzen"/>
    <language>en</language>
    <item>
      <title>Clean Architecture in ASP.NET Core: DTOs, CRUD Operations, and Project Layout</title>
      <dc:creator>Elif Güzen</dc:creator>
      <pubDate>Sat, 05 Apr 2025 19:05:54 +0000</pubDate>
      <link>https://dev.to/guzen/how-i-built-my-first-aspnet-core-api-project-structure-dtos-and-crud-explained-97b</link>
      <guid>https://dev.to/guzen/how-i-built-my-first-aspnet-core-api-project-structure-dtos-and-crud-explained-97b</guid>
      <description>&lt;p&gt;When you first start learning software development, everything can feel overwhelming and confusing.&lt;br&gt;
All the terminology — controllers, HTTP requests, DTOs — might sound like a foreign language.&lt;br&gt;
Trust me, I’ve been there too. I still am learning every day.&lt;br&gt;
But here’s the great part: with every step forward, things start to make sense.&lt;br&gt;
In this article, I want to share my own learning journey and walk you through building a simple yet complete API in ASP.NET Core that covers all essential CRUD operations — Create, Read, Update, and Delete.&lt;br&gt;
By writing this, I reinforce my own learning, and hopefully, I can help you as well if you're on the same path.&lt;br&gt;
Let’s dive in together! 🚀&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foc5xz7g1af9h3uhseija.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foc5xz7g1af9h3uhseija.jpg" alt="Image description" width="307" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This image shows the file and folder structure of our project.&lt;br&gt;
Let’s go through each part so you understand how everything connects.&lt;/p&gt;

&lt;p&gt;📁 Controllers&lt;br&gt;
Here we manage our API endpoints.&lt;br&gt;
      •   ClassroomsController.cs → Handles all operations related to classrooms.&lt;br&gt;
      •   StudentsController.cs → Manages student-related API endpoints.&lt;br&gt;
      •   TeachersController.cs → Handles API requests for teachers.&lt;br&gt;
Each controller contains CRUD operations for its respective entity.&lt;br&gt;
 📁 Data&lt;br&gt;
      •   AppDbContext.cs → Manages the connection to the database and defines the structure of our tables.&lt;br&gt;
 📁 Models &amp;gt; Dtos (Data Transfer Objects)&lt;br&gt;
Our DTOs live here.&lt;br&gt;
DTOs allow us to send clean and secure data to the outside world.&lt;br&gt;
      •   Classroom &amp;gt; ClassroomDetailDto.cs → Provides detailed class information, including teacher and students.&lt;br&gt;
      •   Student &amp;gt; StudentDto.cs → Contains student data for external use.&lt;br&gt;
      •   Teacher &amp;gt; TeacherCreateDto.cs &amp;amp; TeacherDto.cs&lt;br&gt;
              o TeacherCreateDto.cs → Model used when creating new teachers.&lt;br&gt;
              o TeacherDto.cs → Simplified data for teacher information shared outside.&lt;br&gt;
 📁 Models &amp;gt; Entities&lt;br&gt;
These are the database entity models. They represent our actual database tables and work with Entity Framework.&lt;br&gt;
      •   Classroom.cs → Classroom entity.&lt;br&gt;
      •   Student.cs → Student entity.&lt;br&gt;
      •   Teacher.cs → Teacher entity.&lt;br&gt;
Entities are the core data structures in our application.&lt;/p&gt;

&lt;p&gt;In short:&lt;br&gt;
      •   Entities: Actual database models.&lt;br&gt;
      •   DTOs: Clean, external-facing models for API communication.&lt;br&gt;
      •   Controllers: Handle incoming API requests.&lt;br&gt;
      •   AppDbContext: Central class for managing database connections.&lt;br&gt;
This structure keeps our application clean, maintainable, and scalable!&lt;/p&gt;

&lt;p&gt;🧩** Why Do We Use DTOs (Data Transfer Objects)?**&lt;/p&gt;

&lt;p&gt;Before we continue, let’s talk about DTOs — Data Transfer Objects.&lt;br&gt;
A DTO is a simple object that only contains the data we want to send or receive in our API responses.&lt;br&gt;
But why not just send our full database entity? Here’s why:&lt;br&gt;
      •   🚫 Security: Our database entities might include sensitive data (like passwords, internal IDs, or timestamps) that we don’t want to expose to the outside world.&lt;br&gt;
      •   🎯 Clarity and Focus: DTOs help us send only the necessary data. Clean and minimal responses improve performance and make APIs easier to use and understand.&lt;br&gt;
      •   ⚙️ Decoupling: By using DTOs, we create a layer between our internal data models and external responses. This way, if our database structure changes, we won’t break external systems or frontends.&lt;br&gt;
      •   📊 Validation and Transformation: DTOs are great for validating input data and transforming it before saving it to the database.&lt;br&gt;
In short:&lt;br&gt;
DTOs keep our APIs clean, secure, and future-proof.&lt;br&gt;
When building real-world applications, this separation between internal data and external output is crucial for maintainability and scalability.&lt;/p&gt;

&lt;p&gt;🎯 &lt;strong&gt;Why Are CRUD Operations So Important?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, let's answer this question:&lt;br&gt;
Why do we focus so much on CRUD operations? Where do we use them in real projects?&lt;br&gt;
The answer is simple: Everywhere.&lt;br&gt;
CRUD forms the backbone of data management in almost every application. Let’s see some real-world examples:&lt;br&gt;
      •   🎓 Educational Platforms: Add new students (Create), list them (Read), update their info (Update), or remove records (Delete).&lt;br&gt;
      •   🛒 E-commerce Websites: Add products (Create), display them to users (Read), update prices or stock (Update), and remove discontinued items (Delete).&lt;br&gt;
      •   📰 Content Management Systems (CMS): Publish new articles (Create), read posts (Read), edit them (Update), or delete old content (Delete).&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  •   💼 Business Applications: Manage employees, projects, and clients — CRUD is everywhere.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In short: if there’s data, CRUD operations are involved.&lt;br&gt;
Learning CRUD means learning how to build real-world, functional applications.&lt;/p&gt;

&lt;p&gt;🧩 Step 1: Setting Up the Controller&lt;br&gt;
The TeachersController class will handle all requests related to teachers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe7r8dkhcnrss2s8j03oz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe7r8dkhcnrss2s8j03oz.png" alt="Image description" width="800" height="78"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Explanation:&lt;br&gt;
      •   [Route("[controller]")]: Automatically sets the route to /teachers.&lt;br&gt;
      •   AppDbContext context: Injects our database connection.&lt;br&gt;
      •   ControllerBase: Provides built-in methods like Ok(), NotFound(), etc.&lt;/p&gt;

&lt;p&gt;➕ Step 2: Create (POST Request)&lt;br&gt;
Let's add a new teacher:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwn5kf08fns3czpi5qyd3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwn5kf08fns3czpi5qyd3.png" alt="Image description" width="749" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Line by Line:&lt;br&gt;
      •   [HttpPost]: Defines a POST endpoint.&lt;br&gt;
      •   [FromBody]: Parses incoming JSON data.&lt;br&gt;
      •   ModelState.IsValid: Validates the data.&lt;br&gt;
      •   We create a new Teacher object and save it to the database.&lt;br&gt;
      •   CreatedAtAction(): Returns 201 Created with the location of the new resource.&lt;br&gt;
✅ Create is done!&lt;/p&gt;

&lt;p&gt;📖 Step 3: Read (GET Requests)&lt;/p&gt;

&lt;p&gt;1️) List All Teachers&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Folvyjxi0dmpbz4no9wpc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Folvyjxi0dmpbz4no9wpc.png" alt="Image description" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Explanation:&lt;br&gt;
      •   We retrieve all teachers from the database.&lt;br&gt;
      •   Use DTO to return only needed fields.&lt;br&gt;
      •   Ok() sends a 200 response with the data.&lt;br&gt;
2) Get Teacher by ID&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F98d98dds5yjqqjjp5th1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F98d98dds5yjqqjjp5th1.png" alt="Image description" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Explanation:&lt;br&gt;
      •   Get the id from the URL.&lt;br&gt;
      •   Find(id): Search by primary key.&lt;br&gt;
      •   Return 404 if not found, otherwise return 200 with data.&lt;/p&gt;

&lt;p&gt;✅ Read is done!&lt;/p&gt;

&lt;p&gt;✏️ Step 4: Update (PUT Request)&lt;br&gt;
Now let’s update an existing teacher:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4sk2vd0hblbpgukf4j8p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4sk2vd0hblbpgukf4j8p.png" alt="Image description" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Explanation:&lt;br&gt;
      •   [HttpPut("{id}")]: Defines a PUT endpoint.&lt;br&gt;
      •   Validate input.&lt;br&gt;
      •   Find the existing teacher.&lt;br&gt;
      •   Update the teacher's name and save changes.&lt;br&gt;
      •   Return updated teacher with 200 response.&lt;/p&gt;

&lt;p&gt;✅ Update is done!&lt;/p&gt;

&lt;p&gt;🗑️ Step 5: Delete (DELETE Request)&lt;br&gt;
Finally, let’s delete a teacher:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr7koc6iwqg9ybye32xbk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr7koc6iwqg9ybye32xbk.png" alt="Image description" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Explanation:&lt;br&gt;
      •   [HttpDelete("{id}")]: Defines a DELETE endpoint.&lt;br&gt;
      •   Find the teacher by ID.&lt;br&gt;
      •   If not found, return 404.&lt;br&gt;
      •   Remove from the database and save changes.&lt;br&gt;
      •   NoContent(): Returns 204 No Content to indicate success.&lt;/p&gt;

&lt;p&gt;✅ Delete is done!&lt;/p&gt;

&lt;p&gt;🚀 Summary&lt;br&gt;
In this article, we built a fully functional CRUD API with ASP.NET Core, and explained every step.&lt;br&gt;
What we learned: &lt;br&gt;
✅ How to set up controllers&lt;br&gt;
✅ POST: Create new records&lt;br&gt;
✅ GET: Read data&lt;br&gt;
✅ PUT: Update existing records&lt;br&gt;
✅ DELETE: Remove records&lt;br&gt;
✅ How to use DTOs for clean and secure data responses&lt;br&gt;
✅ How CRUD operations power real-world applications&lt;br&gt;
And remember...&lt;br&gt;
Don't forget: it might feel difficult at first, but every line of code moves you forward. Keep learning! 🚀&lt;/p&gt;

</description>
      <category>backend</category>
      <category>programming</category>
      <category>aspnetcore</category>
      <category>csharp</category>
    </item>
  </channel>
</rss>
