Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Právě teď naše webové rozhraní API zpřístupňuje databázové entity klientovi. Klient obdrží data, která se mapují přímo na vaše databázové tabulky. To ale není vždy dobrý nápad. Někdy chcete změnit tvar dat, která odesíláte klientovi. Můžete například chtít:
- Odebrání cyklických odkazů (viz předchozí oddíl).
- Skryjte konkrétní vlastnosti, které klienti nemají zobrazit.
- Pro snížení velikosti dat vynechejte některé vlastnosti.
- Zploštěte grafy objektů, které obsahují vnořené objekty, aby byly pro klienty pohodlnější.
- Vyhněte se "přílišnému sdílení" zranitelností zabezpečení. (Informace o nadměrném zveřejňování najdete v tématu Ověření modelu.)
- Oddělte vrstvu služby od databázové vrstvy.
K tomu můžete definovat objekt pro přenos dat (DTO). DTO je objekt, který definuje, jak se budou data odesílat přes síť. Podívejme se, jak to funguje s entitou Book. Do složky Models přidejte dvě třídy 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; }
}
}
Třída BookDetailDto zahrnuje všechny vlastnosti modelu Kniha, s výjimkou toho, že AuthorName je řetězec, který bude obsahovat jméno autora. Třída BookDto obsahuje podmnožinu vlastností z BookDetailDto.
Dále nahraďte dvě metody GET ve BooksController třídě verzemi, které vracejí DTOs. Příkaz LINQ Select použijeme k převodu entit knihy na objekty 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);
}
Tady je SQL vygenerovaný novou GetBooks metodou. Vidíte, že EF přeloží LINQ Select do příkazu 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]
Nakonec upravte metodu PostBook tak, aby vrátila DTO.
[ResponseType(typeof(BookDto))]
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);
}
Poznámka:
V tomto kurzu převádíme do objektů DTO ručně v kódu. Další možností je použít knihovnu, jako je AutoMapper , která zpracovává převod automaticky.