"
ASP.NET (snapshot 2017) Microsoft documentation and samples

Create Data Transfer Objects (DTOs)

by Mike Wasson

Download Completed Project

Right now, our web API exposes the database entities to the client. The client receives data that maps directly to your database tables. However, that’s not always a good idea. Sometimes you want to change the shape of the data that you send to client. For example, you might want to:

To accomplish this, you can define a data transfer object (DTO). A DTO is an object that defines how the data will be sent over the network. Let’s see how that works with the Book entity. In the Models folder, add two DTO classes:

[!code-csharpMain]

   1:  namespace BookService.Models
   2:  {
   3:      public class BookDTO
   4:      {
   5:          public int Id { get; set; }
   6:          public string Title { get; set; }
   7:          public string AuthorName { get; set; }
   8:      }
   9:  }
  10:   
  11:  namespace BookService.Models
  12:  {
  13:      public class BookDetailDTO
  14:      {
  15:          public int Id { get; set; }
  16:          public string Title { get; set; }
  17:          public int Year { get; set; }
  18:          public decimal Price { get; set; }
  19:          public string AuthorName { get; set; }
  20:          public string Genre { get; set; }
  21:      }
  22:  }

The BookDetailDTO class includes all of the properties from the Book model, except that AuthorName is a string that will hold the author name. The BookDTO class contains a subset of properties from BookDetailDTO.

Next, replace the two GET methods in the BooksController class, with versions that return DTOs. We’ll use the LINQ Select statement to convert from Book entities into DTOs.

[!code-csharpMain]

   1:  // GET api/Books
   2:  public IQueryable<BookDTO> GetBooks()
   3:  {
   4:      var books = from b in db.Books
   5:                  select new BookDTO()
   6:                  {
   7:                      Id = b.Id,
   8:                      Title = b.Title,
   9:                      AuthorName = b.Author.Name
  10:                  };
  11:   
  12:      return books;
  13:  }
  14:   
  15:  // GET api/Books/5
  16:  [ResponseType(typeof(BookDetailDTO))]
  17:  public async Task<IHttpActionResult> GetBook(int id)
  18:  {
  19:      var book = await db.Books.Include(b => b.Author).Select(b =>
  20:          new BookDetailDTO()
  21:          {
  22:              Id = b.Id,
  23:              Title = b.Title,
  24:              Year = b.Year,
  25:              Price = b.Price,
  26:              AuthorName = b.Author.Name,
  27:              Genre = b.Genre
  28:          }).SingleOrDefaultAsync(b => b.Id == id);
  29:      if (book == null)
  30:      {
  31:          return NotFound();
  32:      }
  33:   
  34:      return Ok(book);
  35:  }

Here is the SQL generated by the new GetBooks method. You can see that EF translates the LINQ Select into a SQL SELECT statement.

[!code-sqlMain]

   1:  SELECT 
   2:      [Extent1].[Id] AS [Id], 
   3:      [Extent1].[Title] AS [Title], 
   4:      [Extent2].[Name] AS [Name]
   5:      FROM  [dbo].[Books] AS [Extent1]
   6:      INNER JOIN [dbo].[Authors] AS [Extent2] ON [Extent1].[AuthorId] = [Extent2].[Id]

Finally, modify the PostBook method to return a DTO.

[!code-csharpMain]

   1:  [ResponseType(typeof(Book))]
   2:  public async Task<IHttpActionResult> PostBook(Book book)
   3:  {
   4:      if (!ModelState.IsValid)
   5:      {
   6:          return BadRequest(ModelState);
   7:      }
   8:   
   9:      db.Books.Add(book);
  10:      await db.SaveChangesAsync();
  11:   
  12:      // New code:
  13:      // Load author name
  14:      db.Entry(book).Reference(x => x.Author).Load();
  15:   
  16:      var dto = new BookDTO()
  17:      {
  18:          Id = book.Id,
  19:          Title = book.Title,
  20:          AuthorName = book.Author.Name
  21:      };
  22:   
  23:      return CreatedAtRoute("DefaultApi", new { id = book.Id }, dto);
  24:  }

[!NOTE] In this tutorial, we’re converting to DTOs manually in code. Another option is to use a library like AutoMapper that handles the conversion automatically.

Previous Next



Comments ( )
Link to this page: //www.vb-net.com/AspNet-DocAndSamples-2017/aspnet/web-api/overview/data/using-web-api-with-entity-framework/part-5.htm
< THANKS ME>