Post Action с классом модели против DTO - PullRequest
0 голосов
/ 27 августа 2018

В этом MSDN ссылка объясняется, почему рекомендуется использовать классы DTO для веб-API.Это понятно, что меня смущает то, что на той же странице метод post использует класс модели вместо простого класса 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);
}

Я предполагаю, что мой вопрос: Следует опубликовать /Операция Put требует модели или параметра DTO?

Обновление : Из ответов похоже, что использование dto рекомендуется даже в случае действия post / put, это приведет к другому вопросухотя, как отобразить из dto в класс Model в случае действия post?Допустим, мы используем AutoMapper, я нашел много ссылок, таких как this и this , которые предостерегают от использования его в обратном отображении (то есть dto => класс модели).

Ответы [ 3 ]

0 голосов
/ 27 августа 2018

Во-первых, да, вы всегда должны использовать DTO.Независимо от того, имеете ли вы дело с обычным веб-сайтом или API, вы не должны никогда напрямую сохранять объект, созданный из почтовых данных.Это открывает огромную дыру в безопасности, где люди могут манипулировать почтовыми данными и создавать всевозможные неприятности.По иронии судьбы, вы можете связать свой класс сущностей, но если вы это сделаете, вам никогда не следует сохранять этот экземпляр, а создавать новый экземпляр, отображать данные из опубликованного экземпляра, а затем сохранять созданный вами экземпляр - важныйчасть никогда не сохраняет опубликованный экземпляр.Использование модели представления / DTO только делает более очевидным, что вы должны выполнять отображение в уравнении, и, как таковой, это рекомендуемый подход.

Что касается AutoMapper, рекомендуется не использовать для обратного отображенияпотому что существует множество нюансов, связанных с отображением того, что будет сохранено в базе данных.Особенно, когда у вас есть ORM, такие как Entity Framework.Вы можете использовать AutoMapper, но вам просто нужно знать обо всех этих нюансах и обрабатывать их соответствующим образом.Вообще говоря, в этих сценариях, вероятно, в любом случае проще выполнить сопоставление вручную, так как оно обычно включает в себя так много настроек для чего-то вроде AutoMapper, что вы не экономите много времени в долгосрочной перспективе.Ручное отображение так же, как звучит.Если вы создаете новый Book, то вы просто создаете новый экземпляр Book.Если вы изменяете существующий Book, вы извлекаете его экземпляр из базы данных.В любом случае, теперь у вас есть экземпляр Book и экземпляр чего-то вроде BookDTO, который был создан из почтовых данных.Тогда вы просто:

book.Title = bookDto.Tile;
// etc.

Для чего-то вроде отношений с автором вам может потребоваться выполнить дополнительные запросы.Например:

var author = _context.Authors.SingleOrDefault(x => x.Name == bookDto.AuthorName);
book.Author = author;
0 голосов
/ 27 августа 2018

Краткий ответ: на ваше усмотрение.

Более длинный ответ: я хотел бы рассматривать DTO как способ для слоя (например, службы), получающего данные или представляющего данные извне в простой / плоской структуре данных,По этому определению модель в Web Api - это просто тип DTO, в котором вы можете добавить атрибуты проверки (например, Required, MinLength и т. Д.) С тем удобством, что контроллер api может выполнить проверку для вас, проверив ModelState.IsValid (и этоошибки).Но вы также можете добавить эти атрибуты в класс DTO.Так что на самом деле это не большая разница.

0 голосов
/ 27 августа 2018

Для моих личных проектов и проектов на работе я ввел в действие соглашения, согласно которым мы должны использовать объекты DTO с добавлением либо Request, либо Response, чтобы обеспечить удобство обслуживания и чистую поверхность API, понятную для всех.

public CreateBookResponse CreateBook(CreateBookRequest request)
{
}

Кроме того, в некоторых случаях мы используем HttpResponseMessage, IActionResult или другие возвращаемые значения в зависимости от необходимости веб-службы, но четкое определение объектов запроса и ответа делаетвсем нашим разработчикам, даже с разными навыками, такими как ASP, очень легко понять результирующие структуры JSON.

Я бы посоветовал не подвергать бизнес-объекты или объекты доступа к данным напрямую.Каждый из них имеет свою цель в архитектуре вашего приложения, и вы, возможно, раскрываете слишком много деталей, или вам трудно поддерживать сквозные вопросы.

...