در این قسمت آموزش ASP MVC WEB Api به ساخت اشیاء انتقال داده یا DTOها خواهیم پرداخت .
پست های قبلی آموزش ASP MVC Web Api
- آموزش APS.NET Web Api 2 با انتیتی فریم ورک ۶ (Entity Framework)
- افزودن مدل و کنترلرها – آموزش ASP.net Web API
- Seed کردن ساختمان داده – آموزش API
- روابط موجود در انتیتی – آموزش تصویری WEB API
- ساخت اشیاء انتقال داده یا DTOها
- ساخت اپلیکیشن سمت کاربر با فرمت Javascript
- ساخت رابط کاربری (UI)
در حال حاضر، API تحت وب ما ساختمان داده انتیتی را در دسترس برنامه سمت کاربر قرار میدهد. کاربر دادههایی که مستقیما در جدولهای ساختمان داده قرار دارند را دریافت میکند. هرچند، این مسئله همیشه هم خوب نیست. گاهی اوقات شما میخواهید شکل دادهای که به مشتری میفرستید را تغییر دهید. برای مثال، میخواهید:
- Circular references را حذف کنید (قسمت قبل را مشاهده کنید)
- ویژگی هایی خاصی که نمیخواهید مشتری آنها را ببیند را پنهان کنید.
- برخی ویژگیها را حذف کنید تا اندازه payload کاهش یابد.
- گراف ها و نمودارهای اشیاء را به منظور درک ساده تر آنها توسط کاربر، ساده کنید.
- از آسیب پذیری over-posting جلوگیری کنید .
- لایه سرویس را از لایه پایگاه داده جدا کنید.
برای انجام این کار میتوانید یک شی انتقال داده یا DTO تعریف کنید. DTO شیء ایست که نحوه انتقال داده ها را بر روی شبکه مشخص میکند. بیایید ببینیم چگونه DTO با Book Entity کار میکند. در پوشههای Folder، دو کلاس DTO اضافه کنید.
namespace BookService.Models { public class BookDTO { public int Id { get; set; } public string Title { get; set; } public string AuthorName { get; set; } } } namespace BookService.Models { public class BookDetailDTO { public int Id { get; set; } public string Title { get; set; } public int Year { get; set; } public decimal Price { get; set; } public string AuthorName { get; set; } public string Genre { get; set; } } }
کلاس BookDetailDTO شامل تمامی ویژگیهای مدل کتاب است. به جز AuthorName که نام نویسنده را در خود دارد. کلاس BookDTO شامل زیرمجموعه ویژگیهای BookDetailDTO است.
آموزش ASP MVC WEB Api
در این مرحله، متدهای GET در کلاس BookController را با ورژنهای شامل DTO جایگزین کنید. ما از LINQ با عنوان Select استفاده میکنیم تا انتیتیهای Book را به DTO تبدیل کنیم.
// GET api/Books public IQueryable<BookDTO> GetBooks() { var books = from b in db.Books select new BookDTO() { Id = b.Id, Title = b.Title, AuthorName = b.Author.Name }; return books; } // GET api/Books/5 [ResponseType(typeof(BookDetailDTO))] public async Task<IHttpActionResult> GetBook(int id) { var book = await db.Books.Include(b => b.Author).Select(b => new BookDetailDTO() { Id = b.Id, Title = b.Title, Year = b.Year, Price = b.Price, AuthorName = b.Author.Name, Genre = b.Genre }).SingleOrDefaultAsync(b => b.Id == id); if (book == null) { return NotFound(); } return Ok(book); }
در اینجا SQL به دست آمده از متد جدید GetBooks را مشاهده میکنید. میتوانید ببینید که EF، بخش LINQ به نام Select را به عبارت SQL SELECT ترجمه میکند.
SELECT [Extent1].[Id] AS [Id], [Extent1].[Title] AS [Title], [Extent2].[Name] AS [Name] FROM [dbo].[Books] AS [Extent1] INNER JOIN [dbo].[Authors] AS [Extent2] ON [Extent1].[AuthorId] = [Extent2].[Id]
در آخر، متد PostBook را اصلاح کنید تا DTO برگشت داده شود .
[ResponseType(typeof(Book))] public async Task<IHttpActionResult> PostBook(Book book) { if (!ModelState.IsValid) { return BadRequest(ModelState); } db.Books.Add(book); await db.SaveChangesAsync(); // New code: // Load author name db.Entry(book).Reference(x => x.Author).Load(); var dto = new BookDTO() { Id = book.Id, Title = book.Title, AuthorName = book.Author.Name }; return CreatedAtRoute("DefaultApi", new { id = book.Id }, dto); }