第 4 章 資源操作
4.1 項(xiàng)目創(chuàng)建
從本章起,我們將創(chuàng)建一個(gè)在線圖書館項(xiàng)目,通過這個(gè) Web API 應(yīng)用程序來實(shí)際地熟悉并掌握如何使用 ASP.NET Core 創(chuàng)建 RESTful API 應(yīng)用
這個(gè)項(xiàng)目由兩個(gè)實(shí)體,作者和圖書組成,我們將使用數(shù)據(jù)傳輸對(duì)象(DTO)來表示這兩種資源
新建一個(gè) ASP.NET Core 項(xiàng)目 Library.API,項(xiàng)目模板選擇 API
創(chuàng)建兩個(gè) DTO
namespace Library.API.Models
{
public class AuthorDto
{
public Guid Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
}
}
namespace Library.API.Models
{
public class BookDto
{
public Guid Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int Pages { get; set; }
public Guid AuthorId { get; set; }
}
}
4.2 使用內(nèi)存數(shù)據(jù)
創(chuàng)建內(nèi)存數(shù)據(jù)源 LibraryMockData,專門用于提供模擬數(shù)據(jù)
namespace Library.API.Data
{
public class LibraryMockData
{
// 獲取 LibraryMockData 實(shí)例
public static LibraryMockData Current { get; } = new LibraryMockData();
public List<AuthorDto> Authors { get; set; }
public List<BookDto> Books { get; set; }
public LibraryMockData()
{
var authorId1 = Guid.NewGuid();
var authorId2 = Guid.NewGuid();
Authors = new List<AuthorDto>
{
new AuthorDto
{
Id = authorId1,
Name = "Author 1",
Age = 46,
Email = "Author.com",
},
new AuthorDto
{
Id = authorId2,
Name = "Author 2",
Age = 38,
Email = "Author2.com",
}
};
Books = new List<BookDto>
{
new BookDto
{
Id = Guid.NewGuid(),
Title = "Book 1",
Description = "Description of Book 1",
Pages = 281,
AuthorId = authorId1,
}, new BookDto
{
Id = Guid.NewGuid(),
Title = "Book 2",
Description = "Description of Book 2",
Pages = 370,
AuthorId = authorId2,
}
};
}
}
}
接下來,我們使用倉儲(chǔ)模式來訪問 LibraryMockData 類中的數(shù)據(jù)
倉儲(chǔ)模式作為領(lǐng)域動(dòng)態(tài)設(shè)計(jì)(DDD)的一部分,用于解耦業(yè)務(wù)邏輯層與數(shù)據(jù)訪問層
實(shí)現(xiàn)倉儲(chǔ)模式的方法有許多種,最簡(jiǎn)單的一種是對(duì)每一個(gè)與數(shù)據(jù)庫交互的業(yè)務(wù)對(duì)象創(chuàng)建一個(gè)倉儲(chǔ)接口以及實(shí)現(xiàn),還有一種就是創(chuàng)建一個(gè)通用的倉儲(chǔ)接口,所有其他倉儲(chǔ)接口都繼承這個(gè)接口,下面的例子就是通用的倉儲(chǔ)接口
namespace Library.API.Services
{
public interface IRepositoryBase<T>
{
IEnumerable<T> FindAll();
IEnumerable<T> FindByCondition(Expression<Func<T, bool>> expression);
void Create(T entity);
void Update(T entity);
void Delete(T entity);
void Save();
}
}
本章使用第一種方法來實(shí)現(xiàn)倉儲(chǔ)模式,創(chuàng)建倉儲(chǔ)接口
namespace Library.API.Services
{
public interface IAuthorRepository
{
IEnumerable<AuthorDto> GetAuthors();
AuthorDto GetAuthor(Guid authorId);
bool IsAuthorExists(Guid authorId);
}
}
namespace Library.API.Services
{
public interface IBookRepository
{
IEnumerable<BookDto> GetBooksForAuthor(Guid authorId);
BookDto GetBookForAuthor(Guid authorId, Guid bookId);
}
}
接下來創(chuàng)建接口的具體倉儲(chǔ)實(shí)現(xiàn)
namespace Library.API.Services
{
public class AuthorMockRepository : IAuthorRepository
{
public IEnumerable<AuthorDto> GetAuthors()
{
return LibraryMockData.Current.Authors;
}
public AuthorDto GetAuthor(Guid authorId)
{
var author = LibraryMockData.Current.Authors.FirstOrDefault(au => au.Id == authorId);
return author;
}
public bool IsAuthorExists(Guid authorId)
{
return LibraryMockData.Current.Authors.Any(au => au.Id == authorId);
}
}
}
namespace Library.API.Services
{
public class BookMockRepository : IBookRepository
{
public IEnumerable<BookDto> GetBooksForAuthor(Guid authorId)
{
return LibraryMockData.Current.Books.Where(b => b.AuthorId == authorId).ToList();
}
public BookDto GetBookForAuthor(Guid authorId, Guid bookId)
{
return LibraryMockData.Current.Books.FirstOrDefault(b => b.AuthorId == authorId && b.Id == bookId);
}
}
}
為了在程序中使用上述兩個(gè)倉儲(chǔ)接口,還需要在 ConfigureServices 方法中注入
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddScoped<IAuthorRepository, AuthorMockRepository>();
services.AddScoped<IBookRepository, BookMockRepository>();
}
4.3 創(chuàng)建控制器
首先從依賴注入容器中獲取之前定義的倉儲(chǔ)接口
namespace Library.API.Controllers
{
[Route("api/authors")]
[ApiController]
public class AuthorController : ControllerBase
{
public IAuthorRepository AuthorRepository { get; }
public AuthorController(IAuthorRepository authorRepository)
{
AuthorRepository = authorRepository;
}
}
}
4.4 獲取資源
獲取集合
[HttpGet]
public ActionResult<List<AuthorDto>> GetAuthors()
{
return AuthorRepository.GetAuthors().ToList();
}
獲取單個(gè)資源
[HttpGet("{authorId}")]
public ActionResult<AuthorDto> GetAuthor(Guid authorId)
{
var author = AuthorRepository.GetAuthor(authorId);
if (author == null)
{
return NotFound();
}
else
{
return author;
}
}
獲取父/子形式資源
namespace Library.API.Controllers
{
[Route("api/authors/{authorId}/books")]
[ApiController]
public class BookController : ControllerBase
{
public IAuthorRepository AuthorRepository { get; }
public IBookRepository BookRepository { get; }
public BookController(IAuthorRepository authorRepository, IBookRepository bookRepository)
{
AuthorRepository = authorRepository;
BookRepository = bookRepository;
}
[HttpGet]
public ActionResult<List<BookDto>> GetBooks(Guid authorId)
{
if (!AuthorRepository.IsAuthorExists(authorId))
{
return NotFound();
}
return BookRepository.GetBooksForAuthor(authorId).ToList();
}
}
}
獲取某一個(gè)具體的子級(jí)資源
[HttpGet("{bookId}")]
public ActionResult<BookDto> GetBook(Guid authorId, Guid bookId)
{
if (!AuthorRepository.IsAuthorExists(authorId))
{
return NotFound();
}
var targetBook = BookRepository.GetBookForAuthor(authorId, bookId);
if (targetBook == null)
{
return NotFound();
}
return targetBook;
}
本文摘自 :https://blog.51cto.com/u