diff --git a/docs/en/Tutorials/Part-10.md b/docs/en/Tutorials/Part-10.md index 04f6c6152c..d72505b309 100644 --- a/docs/en/Tutorials/Part-10.md +++ b/docs/en/Tutorials/Part-10.md @@ -141,72 +141,71 @@ using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Repositories; -namespace Acme.BookStore +namespace Acme.BookStore; + +public class BookStoreDataSeederContributor + : IDataSeedContributor, ITransientDependency { - public class BookStoreDataSeederContributor - : IDataSeedContributor, ITransientDependency + private readonly IRepository _bookRepository; + private readonly IAuthorRepository _authorRepository; + private readonly AuthorManager _authorManager; + + public BookStoreDataSeederContributor( + IRepository bookRepository, + IAuthorRepository authorRepository, + AuthorManager authorManager) + { + _bookRepository = bookRepository; + _authorRepository = authorRepository; + _authorManager = authorManager; + } + + public async Task SeedAsync(DataSeedContext context) { - private readonly IRepository _bookRepository; - private readonly IAuthorRepository _authorRepository; - private readonly AuthorManager _authorManager; - - public BookStoreDataSeederContributor( - IRepository bookRepository, - IAuthorRepository authorRepository, - AuthorManager authorManager) + if (await _bookRepository.GetCountAsync() > 0) { - _bookRepository = bookRepository; - _authorRepository = authorRepository; - _authorManager = authorManager; + return; } - public async Task SeedAsync(DataSeedContext context) - { - if (await _bookRepository.GetCountAsync() > 0) + var orwell = await _authorRepository.InsertAsync( + await _authorManager.CreateAsync( + "George Orwell", + new DateTime(1903, 06, 25), + "Orwell produced literary criticism and poetry, fiction and polemical journalism; and is best known for the allegorical novella Animal Farm (1945) and the dystopian novel Nineteen Eighty-Four (1949)." + ) + ); + + var douglas = await _authorRepository.InsertAsync( + await _authorManager.CreateAsync( + "Douglas Adams", + new DateTime(1952, 03, 11), + "Douglas Adams was an English author, screenwriter, essayist, humorist, satirist and dramatist. Adams was an advocate for environmentalism and conservation, a lover of fast cars, technological innovation and the Apple Macintosh, and a self-proclaimed 'radical atheist'." + ) + ); + + await _bookRepository.InsertAsync( + new Book { - return; - } - - var orwell = await _authorRepository.InsertAsync( - await _authorManager.CreateAsync( - "George Orwell", - new DateTime(1903, 06, 25), - "Orwell produced literary criticism and poetry, fiction and polemical journalism; and is best known for the allegorical novella Animal Farm (1945) and the dystopian novel Nineteen Eighty-Four (1949)." - ) - ); - - var douglas = await _authorRepository.InsertAsync( - await _authorManager.CreateAsync( - "Douglas Adams", - new DateTime(1952, 03, 11), - "Douglas Adams was an English author, screenwriter, essayist, humorist, satirist and dramatist. Adams was an advocate for environmentalism and conservation, a lover of fast cars, technological innovation and the Apple Macintosh, and a self-proclaimed 'radical atheist'." - ) - ); - - await _bookRepository.InsertAsync( - new Book - { - AuthorId = orwell.Id, // SET THE AUTHOR - Name = "1984", - Type = BookType.Dystopia, - PublishDate = new DateTime(1949, 6, 8), - Price = 19.84f - }, - autoSave: true - ); - - await _bookRepository.InsertAsync( - new Book - { - AuthorId = douglas.Id, // SET THE AUTHOR - Name = "The Hitchhiker's Guide to the Galaxy", - Type = BookType.ScienceFiction, - PublishDate = new DateTime(1995, 9, 27), - Price = 42.0f - }, - autoSave: true - ); - } + AuthorId = orwell.Id, // SET THE AUTHOR + Name = "1984", + Type = BookType.Dystopia, + PublishDate = new DateTime(1949, 6, 8), + Price = 19.84f + }, + autoSave: true + ); + + await _bookRepository.InsertAsync( + new Book + { + AuthorId = douglas.Id, // SET THE AUTHOR + Name = "The Hitchhiker's Guide to the Galaxy", + Type = BookType.ScienceFiction, + PublishDate = new DateTime(1995, 9, 27), + Price = 42.0f + }, + autoSave: true + ); } } ```` @@ -248,22 +247,21 @@ The final `BookDto` class should be following: using System; using Volo.Abp.Application.Dtos; -namespace Acme.BookStore.Books +namespace Acme.BookStore.Books; + +public class BookDto : AuditedEntityDto { - public class BookDto : AuditedEntityDto - { - public Guid AuthorId { get; set; } + public Guid AuthorId { get; set; } - public string AuthorName { get; set; } + public string AuthorName { get; set; } - public string Name { get; set; } + public string Name { get; set; } - public BookType Type { get; set; } + public BookType Type { get; set; } - public DateTime PublishDate { get; set; } + public DateTime PublishDate { get; set; } - public float Price { get; set; } - } + public float Price { get; set; } } ``` @@ -283,12 +281,11 @@ Create a new class, `AuthorLookupDto`, inside the `Books` folder of the `Acme.Bo using System; using Volo.Abp.Application.Dtos; -namespace Acme.BookStore.Books +namespace Acme.BookStore.Books; + +public class AuthorLookupDto : EntityDto { - public class AuthorLookupDto : EntityDto - { - public string Name { get; set; } - } + public string Name { get; set; } } ```` @@ -304,18 +301,17 @@ using System.Threading.Tasks; using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; -namespace Acme.BookStore.Books +namespace Acme.BookStore.Books; + +public interface IBookAppService : + ICrudAppService< //Defines CRUD methods + BookDto, //Used to show books + Guid, //Primary key of the book entity + PagedAndSortedResultRequestDto, //Used for paging/sorting + CreateUpdateBookDto> //Used to create/update a book { - public interface IBookAppService : - ICrudAppService< //Defines CRUD methods - BookDto, //Used to show books - Guid, //Primary key of the book entity - PagedAndSortedResultRequestDto, //Used for paging/sorting - CreateUpdateBookDto> //Used to create/update a book - { - // ADD the NEW METHOD - Task> GetAuthorLookupAsync(); - } + // ADD the NEW METHOD + Task> GetAuthorLookupAsync(); } ```` @@ -341,119 +337,118 @@ using Volo.Abp.Application.Services; using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Repositories; -namespace Acme.BookStore.Books +namespace Acme.BookStore.Books; + +[Authorize(BookStorePermissions.Books.Default)] +public class BookAppService : + CrudAppService< + Book, //The Book entity + BookDto, //Used to show books + Guid, //Primary key of the book entity + PagedAndSortedResultRequestDto, //Used for paging/sorting + CreateUpdateBookDto>, //Used to create/update a book + IBookAppService //implement the IBookAppService { - [Authorize(BookStorePermissions.Books.Default)] - public class BookAppService : - CrudAppService< - Book, //The Book entity - BookDto, //Used to show books - Guid, //Primary key of the book entity - PagedAndSortedResultRequestDto, //Used for paging/sorting - CreateUpdateBookDto>, //Used to create/update a book - IBookAppService //implement the IBookAppService + private readonly IAuthorRepository _authorRepository; + + public BookAppService( + IRepository repository, + IAuthorRepository authorRepository) + : base(repository) { - private readonly IAuthorRepository _authorRepository; + _authorRepository = authorRepository; + GetPolicyName = BookStorePermissions.Books.Default; + GetListPolicyName = BookStorePermissions.Books.Default; + CreatePolicyName = BookStorePermissions.Books.Create; + UpdatePolicyName = BookStorePermissions.Books.Edit; + DeletePolicyName = BookStorePermissions.Books.Create; + } - public BookAppService( - IRepository repository, - IAuthorRepository authorRepository) - : base(repository) + public override async Task GetAsync(Guid id) + { + //Get the IQueryable from the repository + var queryable = await Repository.GetQueryableAsync(); + + //Prepare a query to join books and authors + var query = from book in queryable + join author in await _authorRepository.GetQueryableAsync() on book.AuthorId equals author.Id + where book.Id == id + select new { book, author }; + + //Execute the query and get the book with author + var queryResult = await AsyncExecuter.FirstOrDefaultAsync(query); + if (queryResult == null) { - _authorRepository = authorRepository; - GetPolicyName = BookStorePermissions.Books.Default; - GetListPolicyName = BookStorePermissions.Books.Default; - CreatePolicyName = BookStorePermissions.Books.Create; - UpdatePolicyName = BookStorePermissions.Books.Edit; - DeletePolicyName = BookStorePermissions.Books.Create; + throw new EntityNotFoundException(typeof(Book), id); } - public override async Task GetAsync(Guid id) - { - //Get the IQueryable from the repository - var queryable = await Repository.GetQueryableAsync(); - - //Prepare a query to join books and authors - var query = from book in queryable - join author in await _authorRepository.GetQueryableAsync() on book.AuthorId equals author.Id - where book.Id == id - select new { book, author }; - - //Execute the query and get the book with author - var queryResult = await AsyncExecuter.FirstOrDefaultAsync(query); - if (queryResult == null) - { - throw new EntityNotFoundException(typeof(Book), id); - } + var bookDto = ObjectMapper.Map(queryResult.book); + bookDto.AuthorName = queryResult.author.Name; + return bookDto; + } - var bookDto = ObjectMapper.Map(queryResult.book); - bookDto.AuthorName = queryResult.author.Name; - return bookDto; - } + public override async Task> GetListAsync(PagedAndSortedResultRequestDto input) + { + //Get the IQueryable from the repository + var queryable = await Repository.GetQueryableAsync(); - public override async Task> GetListAsync(PagedAndSortedResultRequestDto input) - { - //Get the IQueryable from the repository - var queryable = await Repository.GetQueryableAsync(); + //Prepare a query to join books and authors + var query = from book in queryable + join author in await _authorRepository.GetQueryableAsync() on book.AuthorId equals author.Id + select new {book, author}; - //Prepare a query to join books and authors - var query = from book in queryable - join author in await _authorRepository.GetQueryableAsync() on book.AuthorId equals author.Id - select new {book, author}; + //Paging + query = query + .OrderBy(NormalizeSorting(input.Sorting)) + .Skip(input.SkipCount) + .Take(input.MaxResultCount); - //Paging - query = query - .OrderBy(NormalizeSorting(input.Sorting)) - .Skip(input.SkipCount) - .Take(input.MaxResultCount); + //Execute the query and get a list + var queryResult = await AsyncExecuter.ToListAsync(query); - //Execute the query and get a list - var queryResult = await AsyncExecuter.ToListAsync(query); + //Convert the query result to a list of BookDto objects + var bookDtos = queryResult.Select(x => + { + var bookDto = ObjectMapper.Map(x.book); + bookDto.AuthorName = x.author.Name; + return bookDto; + }).ToList(); - //Convert the query result to a list of BookDto objects - var bookDtos = queryResult.Select(x => - { - var bookDto = ObjectMapper.Map(x.book); - bookDto.AuthorName = x.author.Name; - return bookDto; - }).ToList(); + //Get the total count with another query + var totalCount = await Repository.GetCountAsync(); - //Get the total count with another query - var totalCount = await Repository.GetCountAsync(); + return new PagedResultDto( + totalCount, + bookDtos + ); + } - return new PagedResultDto( - totalCount, - bookDtos - ); - } + public async Task> GetAuthorLookupAsync() + { + var authors = await _authorRepository.GetListAsync(); - public async Task> GetAuthorLookupAsync() - { - var authors = await _authorRepository.GetListAsync(); + return new ListResultDto( + ObjectMapper.Map, List>(authors) + ); + } - return new ListResultDto( - ObjectMapper.Map, List>(authors) - ); + private static string NormalizeSorting(string sorting) + { + if (sorting.IsNullOrEmpty()) + { + return $"book.{nameof(Book.Name)}"; } - private static string NormalizeSorting(string sorting) + if (sorting.Contains("authorName", StringComparison.OrdinalIgnoreCase)) { - if (sorting.IsNullOrEmpty()) - { - return $"book.{nameof(Book.Name)}"; - } - - if (sorting.Contains("authorName", StringComparison.OrdinalIgnoreCase)) - { - return sorting.Replace( - "authorName", - "author.Name", - StringComparison.OrdinalIgnoreCase - ); - } - - return $"book.{sorting}"; + return sorting.Replace( + "authorName", + "author.Name", + StringComparison.OrdinalIgnoreCase + ); } + + return $"book.{sorting}"; } } ``` @@ -485,108 +480,107 @@ using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; using Volo.Abp.Domain.Repositories; -namespace Acme.BookStore.Books +namespace Acme.BookStore.Books; + +[Authorize(BookStorePermissions.Books.Default)] +public class BookAppService : + CrudAppService< + Book, //The Book entity + BookDto, //Used to show books + Guid, //Primary key of the book entity + PagedAndSortedResultRequestDto, //Used for paging/sorting + CreateUpdateBookDto>, //Used to create/update a book + IBookAppService //implement the IBookAppService { - [Authorize(BookStorePermissions.Books.Default)] - public class BookAppService : - CrudAppService< - Book, //The Book entity - BookDto, //Used to show books - Guid, //Primary key of the book entity - PagedAndSortedResultRequestDto, //Used for paging/sorting - CreateUpdateBookDto>, //Used to create/update a book - IBookAppService //implement the IBookAppService - { - private readonly IAuthorRepository _authorRepository; + private readonly IAuthorRepository _authorRepository; - public BookAppService( - IRepository repository, - IAuthorRepository authorRepository) - : base(repository) - { - _authorRepository = authorRepository; - GetPolicyName = BookStorePermissions.Books.Default; - GetListPolicyName = BookStorePermissions.Books.Default; - CreatePolicyName = BookStorePermissions.Books.Create; - UpdatePolicyName = BookStorePermissions.Books.Edit; - DeletePolicyName = BookStorePermissions.Books.Create; - } + public BookAppService( + IRepository repository, + IAuthorRepository authorRepository) + : base(repository) + { + _authorRepository = authorRepository; + GetPolicyName = BookStorePermissions.Books.Default; + GetListPolicyName = BookStorePermissions.Books.Default; + CreatePolicyName = BookStorePermissions.Books.Create; + UpdatePolicyName = BookStorePermissions.Books.Edit; + DeletePolicyName = BookStorePermissions.Books.Create; + } - public async override Task GetAsync(Guid id) - { - var book = await Repository.GetAsync(id); - var bookDto = ObjectMapper.Map(book); + public async override Task GetAsync(Guid id) + { + var book = await Repository.GetAsync(id); + var bookDto = ObjectMapper.Map(book); - var author = await _authorRepository.GetAsync(book.AuthorId); - bookDto.AuthorName = author.Name; + var author = await _authorRepository.GetAsync(book.AuthorId); + bookDto.AuthorName = author.Name; - return bookDto; - } + return bookDto; + } - public async override Task> - GetListAsync(PagedAndSortedResultRequestDto input) + public async override Task> + GetListAsync(PagedAndSortedResultRequestDto input) + { + //Set a default sorting, if not provided + if (input.Sorting.IsNullOrWhiteSpace()) { - //Set a default sorting, if not provided - if (input.Sorting.IsNullOrWhiteSpace()) - { - input.Sorting = nameof(Book.Name); - } + input.Sorting = nameof(Book.Name); + } - //Get the IQueryable from the repository - var queryable = await Repository.GetQueryableAsync(); + //Get the IQueryable from the repository + var queryable = await Repository.GetQueryableAsync(); - //Get the books - var books = await AsyncExecuter.ToListAsync( - queryable - .OrderBy(input.Sorting) - .Skip(input.SkipCount) - .Take(input.MaxResultCount) - ); + //Get the books + var books = await AsyncExecuter.ToListAsync( + queryable + .OrderBy(input.Sorting) + .Skip(input.SkipCount) + .Take(input.MaxResultCount) + ); - //Convert to DTOs - var bookDtos = ObjectMapper.Map, List>(books); + //Convert to DTOs + var bookDtos = ObjectMapper.Map, List>(books); - //Get a lookup dictionary for the related authors - var authorDictionary = await GetAuthorDictionaryAsync(books); + //Get a lookup dictionary for the related authors + var authorDictionary = await GetAuthorDictionaryAsync(books); - //Set AuthorName for the DTOs - bookDtos.ForEach(bookDto => bookDto.AuthorName = - authorDictionary[bookDto.AuthorId].Name); + //Set AuthorName for the DTOs + bookDtos.ForEach(bookDto => bookDto.AuthorName = + authorDictionary[bookDto.AuthorId].Name); - //Get the total count with another query (required for the paging) - var totalCount = await Repository.GetCountAsync(); + //Get the total count with another query (required for the paging) + var totalCount = await Repository.GetCountAsync(); - return new PagedResultDto( - totalCount, - bookDtos - ); - } + return new PagedResultDto( + totalCount, + bookDtos + ); + } - public async Task> GetAuthorLookupAsync() - { - var authors = await _authorRepository.GetListAsync(); + public async Task> GetAuthorLookupAsync() + { + var authors = await _authorRepository.GetListAsync(); - return new ListResultDto( - ObjectMapper.Map, List>(authors) - ); - } + return new ListResultDto( + ObjectMapper.Map, List>(authors) + ); + } - private async Task> - GetAuthorDictionaryAsync(List books) - { - var authorIds = books - .Select(b => b.AuthorId) - .Distinct() - .ToArray(); + private async Task> + GetAuthorDictionaryAsync(List books) + { + var authorIds = books + .Select(b => b.AuthorId) + .Distinct() + .ToArray(); - var queryable = await _authorRepository.GetQueryableAsync(); + var queryable = await _authorRepository.GetQueryableAsync(); - var authors = await AsyncExecuter.ToListAsync( - queryable.Where(a => authorIds.Contains(a.Id)) - ); + var authors = await AsyncExecuter.ToListAsync( + queryable.Where(a => authorIds.Contains(a.Id)) + ); - return authors.ToDictionary(x => x.Id, x => x); - } + return authors.ToDictionary(x => x.Id, x => x); } } ``` @@ -623,76 +617,76 @@ using Volo.Abp.Application.Dtos; using Volo.Abp.Validation; using Xunit; -namespace Acme.BookStore.Books -{ {{if DB=="Mongo"}} - [Collection(BookStoreTestConsts.CollectionDefinitionName)]{{end}} - public class BookAppService_Tests : BookStoreApplicationTestBase +namespace Acme.BookStore.Books; + + {{if DB=="Mongo"}} +[Collection(BookStoreTestConsts.CollectionDefinitionName)]{{end}} +public class BookAppService_Tests : BookStoreApplicationTestBase +{ + private readonly IBookAppService _bookAppService; + private readonly IAuthorAppService _authorAppService; + + public BookAppService_Tests() { - private readonly IBookAppService _bookAppService; - private readonly IAuthorAppService _authorAppService; + _bookAppService = GetRequiredService(); + _authorAppService = GetRequiredService(); + } - public BookAppService_Tests() - { - _bookAppService = GetRequiredService(); - _authorAppService = GetRequiredService(); - } + [Fact] + public async Task Should_Get_List_Of_Books() + { + //Act + var result = await _bookAppService.GetListAsync( + new PagedAndSortedResultRequestDto() + ); + + //Assert + result.TotalCount.ShouldBeGreaterThan(0); + result.Items.ShouldContain(b => b.Name == "1984" && + b.AuthorName == "George Orwell"); + } - [Fact] - public async Task Should_Get_List_Of_Books() - { - //Act - var result = await _bookAppService.GetListAsync( - new PagedAndSortedResultRequestDto() - ); + [Fact] + public async Task Should_Create_A_Valid_Book() + { + var authors = await _authorAppService.GetListAsync(new GetAuthorListDto()); + var firstAuthor = authors.Items.First(); - //Assert - result.TotalCount.ShouldBeGreaterThan(0); - result.Items.ShouldContain(b => b.Name == "1984" && - b.AuthorName == "George Orwell"); - } + //Act + var result = await _bookAppService.CreateAsync( + new CreateUpdateBookDto + { + AuthorId = firstAuthor.Id, + Name = "New test book 42", + Price = 10, + PublishDate = System.DateTime.Now, + Type = BookType.ScienceFiction + } + ); - [Fact] - public async Task Should_Create_A_Valid_Book() - { - var authors = await _authorAppService.GetListAsync(new GetAuthorListDto()); - var firstAuthor = authors.Items.First(); + //Assert + result.Id.ShouldNotBe(Guid.Empty); + result.Name.ShouldBe("New test book 42"); + } - //Act - var result = await _bookAppService.CreateAsync( + [Fact] + public async Task Should_Not_Create_A_Book_Without_Name() + { + var exception = await Assert.ThrowsAsync(async () => + { + await _bookAppService.CreateAsync( new CreateUpdateBookDto { - AuthorId = firstAuthor.Id, - Name = "New test book 42", + Name = "", Price = 10, - PublishDate = System.DateTime.Now, + PublishDate = DateTime.Now, Type = BookType.ScienceFiction } ); + }); - //Assert - result.Id.ShouldNotBe(Guid.Empty); - result.Name.ShouldBe("New test book 42"); - } - - [Fact] - public async Task Should_Not_Create_A_Book_Without_Name() - { - var exception = await Assert.ThrowsAsync(async () => - { - await _bookAppService.CreateAsync( - new CreateUpdateBookDto - { - Name = "", - Price = 10, - PublishDate = DateTime.Now, - Type = BookType.ScienceFiction - } - ); - }); - - exception.ValidationErrors - .ShouldContain(err => err.MemberNames.Any(m => m == "Name")); - } + exception.ValidationErrors + .ShouldContain(err => err.MemberNames.Any(m => m == "Name")); } } ``` @@ -751,61 +745,60 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; -namespace Acme.BookStore.Web.Pages.Books +namespace Acme.BookStore.Web.Pages.Books; + +public class CreateModalModel : BookStorePageModel { - public class CreateModalModel : BookStorePageModel - { - [BindProperty] - public CreateBookViewModel Book { get; set; } + [BindProperty] + public CreateBookViewModel Book { get; set; } - public List Authors { get; set; } + public List Authors { get; set; } - private readonly IBookAppService _bookAppService; + private readonly IBookAppService _bookAppService; - public CreateModalModel( - IBookAppService bookAppService) - { - _bookAppService = bookAppService; - } + public CreateModalModel( + IBookAppService bookAppService) + { + _bookAppService = bookAppService; + } - public async Task OnGetAsync() - { - Book = new CreateBookViewModel(); + public async Task OnGetAsync() + { + Book = new CreateBookViewModel(); - var authorLookup = await _bookAppService.GetAuthorLookupAsync(); - Authors = authorLookup.Items - .Select(x => new SelectListItem(x.Name, x.Id.ToString())) - .ToList(); - } + var authorLookup = await _bookAppService.GetAuthorLookupAsync(); + Authors = authorLookup.Items + .Select(x => new SelectListItem(x.Name, x.Id.ToString())) + .ToList(); + } - public async Task OnPostAsync() - { - await _bookAppService.CreateAsync( - ObjectMapper.Map(Book) - ); - return NoContent(); - } + public async Task OnPostAsync() + { + await _bookAppService.CreateAsync( + ObjectMapper.Map(Book) + ); + return NoContent(); + } - public class CreateBookViewModel - { - [SelectItems(nameof(Authors))] - [DisplayName("Author")] - public Guid AuthorId { get; set; } + public class CreateBookViewModel + { + [SelectItems(nameof(Authors))] + [DisplayName("Author")] + public Guid AuthorId { get; set; } - [Required] - [StringLength(128)] - public string Name { get; set; } + [Required] + [StringLength(128)] + public string Name { get; set; } - [Required] - public BookType Type { get; set; } = BookType.Undefined; + [Required] + public BookType Type { get; set; } = BookType.Undefined; - [Required] - [DataType(DataType.Date)] - public DateTime PublishDate { get; set; } = DateTime.Now; + [Required] + [DataType(DataType.Date)] + public DateTime PublishDate { get; set; } = DateTime.Now; - [Required] - public float Price { get; set; } - } + [Required] + public float Price { get; set; } } } ``` @@ -830,66 +823,65 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; -namespace Acme.BookStore.Web.Pages.Books +namespace Acme.BookStore.Web.Pages.Books; + +public class EditModalModel : BookStorePageModel { - public class EditModalModel : BookStorePageModel - { - [BindProperty] - public EditBookViewModel Book { get; set; } + [BindProperty] + public EditBookViewModel Book { get; set; } - public List Authors { get; set; } + public List Authors { get; set; } - private readonly IBookAppService _bookAppService; + private readonly IBookAppService _bookAppService; - public EditModalModel(IBookAppService bookAppService) - { - _bookAppService = bookAppService; - } + public EditModalModel(IBookAppService bookAppService) + { + _bookAppService = bookAppService; + } - public async Task OnGetAsync(Guid id) - { - var bookDto = await _bookAppService.GetAsync(id); - Book = ObjectMapper.Map(bookDto); + public async Task OnGetAsync(Guid id) + { + var bookDto = await _bookAppService.GetAsync(id); + Book = ObjectMapper.Map(bookDto); - var authorLookup = await _bookAppService.GetAuthorLookupAsync(); - Authors = authorLookup.Items - .Select(x => new SelectListItem(x.Name, x.Id.ToString())) - .ToList(); - } + var authorLookup = await _bookAppService.GetAuthorLookupAsync(); + Authors = authorLookup.Items + .Select(x => new SelectListItem(x.Name, x.Id.ToString())) + .ToList(); + } - public async Task OnPostAsync() - { - await _bookAppService.UpdateAsync( - Book.Id, - ObjectMapper.Map(Book) - ); + public async Task OnPostAsync() + { + await _bookAppService.UpdateAsync( + Book.Id, + ObjectMapper.Map(Book) + ); - return NoContent(); - } + return NoContent(); + } - public class EditBookViewModel - { - [HiddenInput] - public Guid Id { get; set; } + public class EditBookViewModel + { + [HiddenInput] + public Guid Id { get; set; } - [SelectItems(nameof(Authors))] - [DisplayName("Author")] - public Guid AuthorId { get; set; } + [SelectItems(nameof(Authors))] + [DisplayName("Author")] + public Guid AuthorId { get; set; } - [Required] - [StringLength(128)] - public string Name { get; set; } + [Required] + [StringLength(128)] + public string Name { get; set; } - [Required] - public BookType Type { get; set; } = BookType.Undefined; + [Required] + public BookType Type { get; set; } = BookType.Undefined; - [Required] - [DataType(DataType.Date)] - public DateTime PublishDate { get; set; } = DateTime.Now; + [Required] + [DataType(DataType.Date)] + public DateTime PublishDate { get; set; } = DateTime.Now; - [Required] - public float Price { get; set; } - } + [Required] + public float Price { get; set; } } } ``` diff --git a/docs/en/Tutorials/Part-2.md b/docs/en/Tutorials/Part-2.md index 026a527e72..d22e4b5062 100644 --- a/docs/en/Tutorials/Part-2.md +++ b/docs/en/Tutorials/Part-2.md @@ -178,14 +178,13 @@ Open the `Index.cshtml` and change the whole content as shown below: ```csharp using Microsoft.AspNetCore.Mvc.RazorPages; -namespace Acme.BookStore.Web.Pages.Books +namespace Acme.BookStore.Web.Pages.Books; + +public class IndexModel : PageModel { - public class IndexModel : PageModel + public void OnGet() { - public void OnGet() - { - } } } ``` diff --git a/docs/en/Tutorials/Part-3.md b/docs/en/Tutorials/Part-3.md index 15adab29cf..3e6fb13e38 100644 --- a/docs/en/Tutorials/Part-3.md +++ b/docs/en/Tutorials/Part-3.md @@ -283,35 +283,34 @@ using System.Threading.Tasks; using Acme.BookStore.Books; using Microsoft.AspNetCore.Mvc; -namespace Acme.BookStore.Web.Pages.Books +namespace Acme.BookStore.Web.Pages.Books; + +public class EditModalModel : BookStorePageModel { - public class EditModalModel : BookStorePageModel - { - [HiddenInput] - [BindProperty(SupportsGet = true)] - public Guid Id { get; set; } + [HiddenInput] + [BindProperty(SupportsGet = true)] + public Guid Id { get; set; } - [BindProperty] - public CreateUpdateBookDto Book { get; set; } + [BindProperty] + public CreateUpdateBookDto Book { get; set; } - private readonly IBookAppService _bookAppService; + private readonly IBookAppService _bookAppService; - public EditModalModel(IBookAppService bookAppService) - { - _bookAppService = bookAppService; - } + public EditModalModel(IBookAppService bookAppService) + { + _bookAppService = bookAppService; + } - public async Task OnGetAsync() - { - var bookDto = await _bookAppService.GetAsync(Id); - Book = ObjectMapper.Map(bookDto); - } + public async Task OnGetAsync() + { + var bookDto = await _bookAppService.GetAsync(Id); + Book = ObjectMapper.Map(bookDto); + } - public async Task OnPostAsync() - { - await _bookAppService.UpdateAsync(Id, Book); - return NoContent(); - } + public async Task OnPostAsync() + { + await _bookAppService.UpdateAsync(Id, Book); + return NoContent(); } } ```` @@ -327,14 +326,13 @@ To be able to map the `BookDto` to `CreateUpdateBookDto`, configure a new mappin ````csharp using AutoMapper; -namespace Acme.BookStore.Web +namespace Acme.BookStore.Web; + +public class BookStoreWebAutoMapperProfile : Profile { - public class BookStoreWebAutoMapperProfile : Profile + public BookStoreWebAutoMapperProfile() { - public BookStoreWebAutoMapperProfile() - { - CreateMap(); - } + CreateMap(); } } ```` @@ -1323,14 +1321,13 @@ Open the `BookStoreBlazorAutoMapperProfile` inside the `Acme.BookStore.Blazor` p using Acme.BookStore.Books; using AutoMapper; -namespace Acme.BookStore.Blazor +namespace Acme.BookStore.Blazor; + +public class BookStoreBlazorAutoMapperProfile : Profile { - public class BookStoreBlazorAutoMapperProfile : Profile + public BookStoreBlazorAutoMapperProfile() { - public BookStoreBlazorAutoMapperProfile() - { - CreateMap(); - } + CreateMap(); } } ```` diff --git a/docs/en/Tutorials/Part-4.md b/docs/en/Tutorials/Part-4.md index d956a299db..6ff2c38a8d 100644 --- a/docs/en/Tutorials/Part-4.md +++ b/docs/en/Tutorials/Part-4.md @@ -85,30 +85,30 @@ using Volo.Abp.Application.Dtos; using Volo.Abp.Validation; using Xunit; -namespace Acme.BookStore.Books -{ {{if DB=="Mongo"}} - [Collection(BookStoreTestConsts.CollectionDefinitionName)]{{end}} - public class BookAppService_Tests : BookStoreApplicationTestBase - { - private readonly IBookAppService _bookAppService; +namespace Acme.BookStore.Books; - public BookAppService_Tests() - { - _bookAppService = GetRequiredService(); - } + {{if DB=="Mongo"}} +[Collection(BookStoreTestConsts.CollectionDefinitionName)]{{end}} +public class BookAppService_Tests : BookStoreApplicationTestBase +{ + private readonly IBookAppService _bookAppService; - [Fact] - public async Task Should_Get_List_Of_Books() - { - //Act - var result = await _bookAppService.GetListAsync( - new PagedAndSortedResultRequestDto() - ); + public BookAppService_Tests() + { + _bookAppService = GetRequiredService(); + } - //Assert - result.TotalCount.ShouldBeGreaterThan(0); - result.Items.ShouldContain(b => b.Name == "1984"); - } + [Fact] + public async Task Should_Get_List_Of_Books() + { + //Act + var result = await _bookAppService.GetListAsync( + new PagedAndSortedResultRequestDto() + ); + + //Assert + result.TotalCount.ShouldBeGreaterThan(0); + result.Items.ShouldContain(b => b.Name == "1984"); } } ```` @@ -176,69 +176,69 @@ using Volo.Abp.Application.Dtos; using Volo.Abp.Validation; using Xunit; -namespace Acme.BookStore.Books -{ {{if DB=="Mongo"}} - [Collection(BookStoreTestConsts.CollectionDefinitionName)]{{end}} - public class BookAppService_Tests : BookStoreApplicationTestBase +namespace Acme.BookStore.Books; + +{{if DB=="Mongo"}} +[Collection(BookStoreTestConsts.CollectionDefinitionName)]{{end}} +public class BookAppService_Tests : BookStoreApplicationTestBase +{ + private readonly IBookAppService _bookAppService; + + public BookAppService_Tests() { - private readonly IBookAppService _bookAppService; + _bookAppService = GetRequiredService(); + } - public BookAppService_Tests() - { - _bookAppService = GetRequiredService(); - } + [Fact] + public async Task Should_Get_List_Of_Books() + { + //Act + var result = await _bookAppService.GetListAsync( + new PagedAndSortedResultRequestDto() + ); - [Fact] - public async Task Should_Get_List_Of_Books() - { - //Act - var result = await _bookAppService.GetListAsync( - new PagedAndSortedResultRequestDto() - ); + //Assert + result.TotalCount.ShouldBeGreaterThan(0); + result.Items.ShouldContain(b => b.Name == "1984"); + } + + [Fact] + public async Task Should_Create_A_Valid_Book() + { + //Act + var result = await _bookAppService.CreateAsync( + new CreateUpdateBookDto + { + Name = "New test book 42", + Price = 10, + PublishDate = DateTime.Now, + Type = BookType.ScienceFiction + } + ); - //Assert - result.TotalCount.ShouldBeGreaterThan(0); - result.Items.ShouldContain(b => b.Name == "1984"); - } - - [Fact] - public async Task Should_Create_A_Valid_Book() + //Assert + result.Id.ShouldNotBe(Guid.Empty); + result.Name.ShouldBe("New test book 42"); + } + + [Fact] + public async Task Should_Not_Create_A_Book_Without_Name() + { + var exception = await Assert.ThrowsAsync(async () => { - //Act - var result = await _bookAppService.CreateAsync( + await _bookAppService.CreateAsync( new CreateUpdateBookDto { - Name = "New test book 42", + Name = "", Price = 10, PublishDate = DateTime.Now, Type = BookType.ScienceFiction } ); + }); - //Assert - result.Id.ShouldNotBe(Guid.Empty); - result.Name.ShouldBe("New test book 42"); - } - - [Fact] - public async Task Should_Not_Create_A_Book_Without_Name() - { - var exception = await Assert.ThrowsAsync(async () => - { - await _bookAppService.CreateAsync( - new CreateUpdateBookDto - { - Name = "", - Price = 10, - PublishDate = DateTime.Now, - Type = BookType.ScienceFiction - } - ); - }); - - exception.ValidationErrors - .ShouldContain(err => err.MemberNames.Any(mem => mem == "Name")); - } + exception.ValidationErrors + .ShouldContain(err => err.MemberNames.Any(mem => mem == "Name")); } } ```` diff --git a/docs/en/Tutorials/Part-5.md b/docs/en/Tutorials/Part-5.md index 970f46b43c..4a6bebe958 100644 --- a/docs/en/Tutorials/Part-5.md +++ b/docs/en/Tutorials/Part-5.md @@ -55,19 +55,18 @@ A permission must have a unique name (a `string`). The best way is to define it Open the `BookStorePermissions` class inside the `Acme.BookStore.Application.Contracts` project (in the `Permissions` folder) and change the content as shown below: ````csharp -namespace Acme.BookStore.Permissions +namespace Acme.BookStore.Permissions; + +public static class BookStorePermissions { - public static class BookStorePermissions + public const string GroupName = "BookStore"; + + public static class Books { - public const string GroupName = "BookStore"; - - public static class Books - { - public const string Default = GroupName + ".Books"; - public const string Create = Default + ".Create"; - public const string Edit = Default + ".Edit"; - public const string Delete = Default + ".Delete"; - } + public const string Default = GroupName + ".Books"; + public const string Create = Default + ".Create"; + public const string Edit = Default + ".Edit"; + public const string Delete = Default + ".Delete"; } } ```` @@ -85,24 +84,23 @@ using Acme.BookStore.Localization; using Volo.Abp.Authorization.Permissions; using Volo.Abp.Localization; -namespace Acme.BookStore.Permissions +namespace Acme.BookStore.Permissions; + +public class BookStorePermissionDefinitionProvider : PermissionDefinitionProvider { - public class BookStorePermissionDefinitionProvider : PermissionDefinitionProvider + public override void Define(IPermissionDefinitionContext context) { - public override void Define(IPermissionDefinitionContext context) - { - var bookStoreGroup = context.AddGroup(BookStorePermissions.GroupName, L("Permission:BookStore")); - - var booksPermission = bookStoreGroup.AddPermission(BookStorePermissions.Books.Default, L("Permission:Books")); - booksPermission.AddChild(BookStorePermissions.Books.Create, L("Permission:Books.Create")); - booksPermission.AddChild(BookStorePermissions.Books.Edit, L("Permission:Books.Edit")); - booksPermission.AddChild(BookStorePermissions.Books.Delete, L("Permission:Books.Delete")); - } - - private static LocalizableString L(string name) - { - return LocalizableString.Create(name); - } + var bookStoreGroup = context.AddGroup(BookStorePermissions.GroupName, L("Permission:BookStore")); + + var booksPermission = bookStoreGroup.AddPermission(BookStorePermissions.Books.Default, L("Permission:Books")); + booksPermission.AddChild(BookStorePermissions.Books.Create, L("Permission:Books.Create")); + booksPermission.AddChild(BookStorePermissions.Books.Edit, L("Permission:Books.Edit")); + booksPermission.AddChild(BookStorePermissions.Books.Delete, L("Permission:Books.Delete")); + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); } } ```` @@ -148,26 +146,25 @@ using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; using Volo.Abp.Domain.Repositories; -namespace Acme.BookStore.Books +namespace Acme.BookStore.Books; + +public class BookAppService : + CrudAppService< + Book, //The Book entity + BookDto, //Used to show books + Guid, //Primary key of the book entity + PagedAndSortedResultRequestDto, //Used for paging/sorting + CreateUpdateBookDto>, //Used to create/update a book + IBookAppService //implement the IBookAppService { - public class BookAppService : - CrudAppService< - Book, //The Book entity - BookDto, //Used to show books - Guid, //Primary key of the book entity - PagedAndSortedResultRequestDto, //Used for paging/sorting - CreateUpdateBookDto>, //Used to create/update a book - IBookAppService //implement the IBookAppService + public BookAppService(IRepository repository) + : base(repository) { - public BookAppService(IRepository repository) - : base(repository) - { - GetPolicyName = BookStorePermissions.Books.Default; - GetListPolicyName = BookStorePermissions.Books.Default; - CreatePolicyName = BookStorePermissions.Books.Create; - UpdatePolicyName = BookStorePermissions.Books.Edit; - DeletePolicyName = BookStorePermissions.Books.Delete; - } + GetPolicyName = BookStorePermissions.Books.Default; + GetListPolicyName = BookStorePermissions.Books.Default; + CreatePolicyName = BookStorePermissions.Books.Create; + UpdatePolicyName = BookStorePermissions.Books.Edit; + DeletePolicyName = BookStorePermissions.Books.Delete; } } ```` diff --git a/docs/en/Tutorials/Part-6.md b/docs/en/Tutorials/Part-6.md index 36f1bc6d0a..40b334808c 100644 --- a/docs/en/Tutorials/Part-6.md +++ b/docs/en/Tutorials/Part-6.md @@ -60,45 +60,44 @@ using JetBrains.Annotations; using Volo.Abp; using Volo.Abp.Domain.Entities.Auditing; -namespace Acme.BookStore.Authors +namespace Acme.BookStore.Authors; + +public class Author : FullAuditedAggregateRoot { - public class Author : FullAuditedAggregateRoot - { - public string Name { get; private set; } - public DateTime BirthDate { get; set; } - public string ShortBio { get; set; } + public string Name { get; private set; } + public DateTime BirthDate { get; set; } + public string ShortBio { get; set; } - private Author() - { - /* This constructor is for deserialization / ORM purpose */ - } + private Author() + { + /* This constructor is for deserialization / ORM purpose */ + } - internal Author( - Guid id, - [NotNull] string name, - DateTime birthDate, - [CanBeNull] string shortBio = null) - : base(id) - { - SetName(name); - BirthDate = birthDate; - ShortBio = shortBio; - } + internal Author( + Guid id, + [NotNull] string name, + DateTime birthDate, + [CanBeNull] string shortBio = null) + : base(id) + { + SetName(name); + BirthDate = birthDate; + ShortBio = shortBio; + } - internal Author ChangeName([NotNull] string name) - { - SetName(name); - return this; - } + internal Author ChangeName([NotNull] string name) + { + SetName(name); + return this; + } - private void SetName([NotNull] string name) - { - Name = Check.NotNullOrWhiteSpace( - name, - nameof(name), - maxLength: AuthorConsts.MaxNameLength - ); - } + private void SetName([NotNull] string name) + { + Name = Check.NotNullOrWhiteSpace( + name, + nameof(name), + maxLength: AuthorConsts.MaxNameLength + ); } } ```` @@ -113,13 +112,13 @@ namespace Acme.BookStore.Authors `AuthorConsts` is a simple class that is located under the `Authors` namespace (folder) of the `Acme.BookStore.Domain.Shared` project: ````csharp -namespace Acme.BookStore.Authors +namespace Acme.BookStore.Authors; + +public static class AuthorConsts { - public static class AuthorConsts - { - public const int MaxNameLength = 64; - } + public const int MaxNameLength = 64; } + ```` Created this class inside the `Acme.BookStore.Domain.Shared` project since we will re-use it on the [Data Transfer Objects](../Data-Transfer-Objects.md) (DTOs) later. @@ -135,53 +134,52 @@ using JetBrains.Annotations; using Volo.Abp; using Volo.Abp.Domain.Services; -namespace Acme.BookStore.Authors +namespace Acme.BookStore.Authors; + +public class AuthorManager : DomainService { - public class AuthorManager : DomainService + private readonly IAuthorRepository _authorRepository; + + public AuthorManager(IAuthorRepository authorRepository) { - private readonly IAuthorRepository _authorRepository; + _authorRepository = authorRepository; + } - public AuthorManager(IAuthorRepository authorRepository) - { - _authorRepository = authorRepository; - } + public async Task CreateAsync( + [NotNull] string name, + DateTime birthDate, + [CanBeNull] string shortBio = null) + { + Check.NotNullOrWhiteSpace(name, nameof(name)); - public async Task CreateAsync( - [NotNull] string name, - DateTime birthDate, - [CanBeNull] string shortBio = null) + var existingAuthor = await _authorRepository.FindByNameAsync(name); + if (existingAuthor != null) { - Check.NotNullOrWhiteSpace(name, nameof(name)); - - var existingAuthor = await _authorRepository.FindByNameAsync(name); - if (existingAuthor != null) - { - throw new AuthorAlreadyExistsException(name); - } - - return new Author( - GuidGenerator.Create(), - name, - birthDate, - shortBio - ); + throw new AuthorAlreadyExistsException(name); } - public async Task ChangeNameAsync( - [NotNull] Author author, - [NotNull] string newName) - { - Check.NotNull(author, nameof(author)); - Check.NotNullOrWhiteSpace(newName, nameof(newName)); + return new Author( + GuidGenerator.Create(), + name, + birthDate, + shortBio + ); + } - var existingAuthor = await _authorRepository.FindByNameAsync(newName); - if (existingAuthor != null && existingAuthor.Id != author.Id) - { - throw new AuthorAlreadyExistsException(newName); - } + public async Task ChangeNameAsync( + [NotNull] Author author, + [NotNull] string newName) + { + Check.NotNull(author, nameof(author)); + Check.NotNullOrWhiteSpace(newName, nameof(newName)); - author.ChangeName(newName); + var existingAuthor = await _authorRepository.FindByNameAsync(newName); + if (existingAuthor != null && existingAuthor.Id != author.Id) + { + throw new AuthorAlreadyExistsException(newName); } + + author.ChangeName(newName); } } ```` @@ -195,15 +193,14 @@ Both methods checks if there is already an author with the given name and throws ````csharp using Volo.Abp; -namespace Acme.BookStore.Authors +namespace Acme.BookStore.Authors; + +public class AuthorAlreadyExistsException : BusinessException { - public class AuthorAlreadyExistsException : BusinessException + public AuthorAlreadyExistsException(string name) + : base(BookStoreDomainErrorCodes.AuthorAlreadyExists) { - public AuthorAlreadyExistsException(string name) - : base(BookStoreDomainErrorCodes.AuthorAlreadyExists) - { - WithData("name", name); - } + WithData("name", name); } } ```` @@ -213,12 +210,11 @@ namespace Acme.BookStore.Authors Open the `BookStoreDomainErrorCodes` in the `Acme.BookStore.Domain.Shared` project and change as shown below: ````csharp -namespace Acme.BookStore +namespace Acme.BookStore; + +public static class BookStoreDomainErrorCodes { - public static class BookStoreDomainErrorCodes - { - public const string AuthorAlreadyExists = "BookStore:00001"; - } + public const string AuthorAlreadyExists = "BookStore:00001"; } ```` @@ -240,19 +236,18 @@ using System.Collections.Generic; using System.Threading.Tasks; using Volo.Abp.Domain.Repositories; -namespace Acme.BookStore.Authors -{ - public interface IAuthorRepository : IRepository - { - Task FindByNameAsync(string name); +namespace Acme.BookStore.Authors; - Task> GetListAsync( - int skipCount, - int maxResultCount, - string sorting, - string filter = null - ); - } +public interface IAuthorRepository : IRepository +{ + Task FindByNameAsync(string name); + + Task> GetListAsync( + int skipCount, + int maxResultCount, + string sorting, + string filter = null + ); } ```` diff --git a/docs/en/Tutorials/Part-7.md b/docs/en/Tutorials/Part-7.md index d60d030f13..82f01bf963 100644 --- a/docs/en/Tutorials/Part-7.md +++ b/docs/en/Tutorials/Part-7.md @@ -121,41 +121,40 @@ using Microsoft.EntityFrameworkCore; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; -namespace Acme.BookStore.Authors +namespace Acme.BookStore.Authors; + +public class EfCoreAuthorRepository + : EfCoreRepository, + IAuthorRepository { - public class EfCoreAuthorRepository - : EfCoreRepository, - IAuthorRepository + public EfCoreAuthorRepository( + IDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } + + public async Task FindByNameAsync(string name) { - public EfCoreAuthorRepository( - IDbContextProvider dbContextProvider) - : base(dbContextProvider) - { - } - - public async Task FindByNameAsync(string name) - { - var dbSet = await GetDbSetAsync(); - return await dbSet.FirstOrDefaultAsync(author => author.Name == name); - } - - public async Task> GetListAsync( - int skipCount, - int maxResultCount, - string sorting, - string filter = null) - { - var dbSet = await GetDbSetAsync(); - return await dbSet - .WhereIf( - !filter.IsNullOrWhiteSpace(), - author => author.Name.Contains(filter) - ) - .OrderBy(sorting) - .Skip(skipCount) - .Take(maxResultCount) - .ToListAsync(); - } + var dbSet = await GetDbSetAsync(); + return await dbSet.FirstOrDefaultAsync(author => author.Name == name); + } + + public async Task> GetListAsync( + int skipCount, + int maxResultCount, + string sorting, + string filter = null) + { + var dbSet = await GetDbSetAsync(); + return await dbSet + .WhereIf( + !filter.IsNullOrWhiteSpace(), + author => author.Name.Contains(filter) + ) + .OrderBy(sorting) + .Skip(skipCount) + .Take(maxResultCount) + .ToListAsync(); } } ```` @@ -182,42 +181,41 @@ using MongoDB.Driver.Linq; using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.MongoDB; -namespace Acme.BookStore.Authors +namespace Acme.BookStore.Authors; + +public class MongoDbAuthorRepository + : MongoDbRepository, + IAuthorRepository { - public class MongoDbAuthorRepository - : MongoDbRepository, - IAuthorRepository + public MongoDbAuthorRepository( + IMongoDbContextProvider dbContextProvider + ) : base(dbContextProvider) { - public MongoDbAuthorRepository( - IMongoDbContextProvider dbContextProvider - ) : base(dbContextProvider) - { - } - - public async Task FindByNameAsync(string name) - { - var queryable = await GetMongoQueryableAsync(); - return await queryable.FirstOrDefaultAsync(author => author.Name == name); - } - - public async Task> GetListAsync( - int skipCount, - int maxResultCount, - string sorting, - string filter = null) - { - var queryable = await GetMongoQueryableAsync(); - return await queryable - .WhereIf>( - !filter.IsNullOrWhiteSpace(), - author => author.Name.Contains(filter) - ) - .OrderBy(sorting) - .As>() - .Skip(skipCount) - .Take(maxResultCount) - .ToListAsync(); - } + } + + public async Task FindByNameAsync(string name) + { + var queryable = await GetMongoQueryableAsync(); + return await queryable.FirstOrDefaultAsync(author => author.Name == name); + } + + public async Task> GetListAsync( + int skipCount, + int maxResultCount, + string sorting, + string filter = null) + { + var queryable = await GetMongoQueryableAsync(); + return await queryable + .WhereIf>( + !filter.IsNullOrWhiteSpace(), + author => author.Name.Contains(filter) + ) + .OrderBy(sorting) + .As>() + .Skip(skipCount) + .Take(maxResultCount) + .ToListAsync(); } } ``` diff --git a/docs/en/Tutorials/Part-8.md b/docs/en/Tutorials/Part-8.md index cdde623a08..f8615c2137 100644 --- a/docs/en/Tutorials/Part-8.md +++ b/docs/en/Tutorials/Part-8.md @@ -50,20 +50,19 @@ using System.Threading.Tasks; using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; -namespace Acme.BookStore.Authors +namespace Acme.BookStore.Authors; + +public interface IAuthorAppService : IApplicationService { - public interface IAuthorAppService : IApplicationService - { - Task GetAsync(Guid id); + Task GetAsync(Guid id); - Task> GetListAsync(GetAuthorListDto input); + Task> GetListAsync(GetAuthorListDto input); - Task CreateAsync(CreateAuthorDto input); + Task CreateAsync(CreateAuthorDto input); - Task UpdateAsync(Guid id, UpdateAuthorDto input); + Task UpdateAsync(Guid id, UpdateAuthorDto input); - Task DeleteAsync(Guid id); - } + Task DeleteAsync(Guid id); } ```` @@ -80,16 +79,15 @@ This interface is using the DTOs defined below (create them for your project). using System; using Volo.Abp.Application.Dtos; -namespace Acme.BookStore.Authors +namespace Acme.BookStore.Authors; + +public class AuthorDto : EntityDto { - public class AuthorDto : EntityDto - { - public string Name { get; set; } + public string Name { get; set; } - public DateTime BirthDate { get; set; } + public DateTime BirthDate { get; set; } - public string ShortBio { get; set; } - } + public string ShortBio { get; set; } } ```` @@ -100,12 +98,11 @@ namespace Acme.BookStore.Authors ````csharp using Volo.Abp.Application.Dtos; -namespace Acme.BookStore.Authors +namespace Acme.BookStore.Authors; + +public class GetAuthorListDto : PagedAndSortedResultRequestDto { - public class GetAuthorListDto : PagedAndSortedResultRequestDto - { - public string Filter { get; set; } - } + public string Filter { get; set; } } ```` @@ -120,19 +117,18 @@ namespace Acme.BookStore.Authors using System; using System.ComponentModel.DataAnnotations; -namespace Acme.BookStore.Authors -{ - public class CreateAuthorDto - { - [Required] - [StringLength(AuthorConsts.MaxNameLength)] - public string Name { get; set; } +namespace Acme.BookStore.Authors; - [Required] - public DateTime BirthDate { get; set; } - - public string ShortBio { get; set; } - } +public class CreateAuthorDto +{ + [Required] + [StringLength(AuthorConsts.MaxNameLength)] + public string Name { get; set; } + + [Required] + public DateTime BirthDate { get; set; } + + public string ShortBio { get; set; } } ```` @@ -144,19 +140,18 @@ Data annotation attributes can be used to validate the DTO. See the [validation using System; using System.ComponentModel.DataAnnotations; -namespace Acme.BookStore.Authors -{ - public class UpdateAuthorDto - { - [Required] - [StringLength(AuthorConsts.MaxNameLength)] - public string Name { get; set; } +namespace Acme.BookStore.Authors; - [Required] - public DateTime BirthDate { get; set; } - - public string ShortBio { get; set; } - } +public class UpdateAuthorDto +{ + [Required] + [StringLength(AuthorConsts.MaxNameLength)] + public string Name { get; set; } + + [Required] + public DateTime BirthDate { get; set; } + + public string ShortBio { get; set; } } ```` @@ -176,24 +171,23 @@ using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Dtos; using Volo.Abp.Domain.Repositories; -namespace Acme.BookStore.Authors -{ - [Authorize(BookStorePermissions.Authors.Default)] - public class AuthorAppService : BookStoreAppService, IAuthorAppService - { - private readonly IAuthorRepository _authorRepository; - private readonly AuthorManager _authorManager; +namespace Acme.BookStore.Authors; - public AuthorAppService( - IAuthorRepository authorRepository, - AuthorManager authorManager) - { - _authorRepository = authorRepository; - _authorManager = authorManager; - } +[Authorize(BookStorePermissions.Authors.Default)] +public class AuthorAppService : BookStoreAppService, IAuthorAppService +{ + private readonly IAuthorRepository _authorRepository; + private readonly AuthorManager _authorManager; - //...SERVICE METHODS WILL COME HERE... + public AuthorAppService( + IAuthorRepository authorRepository, + AuthorManager authorManager) + { + _authorRepository = authorRepository; + _authorManager = authorManager; } + + //...SERVICE METHODS WILL COME HERE... } ```` @@ -327,28 +321,27 @@ You can't compile the code since it is expecting some constants declared in the Open the `BookStorePermissions` class inside the `Acme.BookStore.Application.Contracts` project (in the `Permissions` folder) and change the content as shown below: ````csharp -namespace Acme.BookStore.Permissions +namespace Acme.BookStore.Permissions; + +public static class BookStorePermissions { - public static class BookStorePermissions - { - public const string GroupName = "BookStore"; + public const string GroupName = "BookStore"; - public static class Books - { - public const string Default = GroupName + ".Books"; - public const string Create = Default + ".Create"; - public const string Edit = Default + ".Edit"; - public const string Delete = Default + ".Delete"; - } - - // *** ADDED a NEW NESTED CLASS *** - public static class Authors - { - public const string Default = GroupName + ".Authors"; - public const string Create = Default + ".Create"; - public const string Edit = Default + ".Edit"; - public const string Delete = Default + ".Delete"; - } + public static class Books + { + public const string Default = GroupName + ".Books"; + public const string Create = Default + ".Create"; + public const string Edit = Default + ".Edit"; + public const string Delete = Default + ".Delete"; + } + + // *** ADDED a NEW NESTED CLASS *** + public static class Authors + { + public const string Default = GroupName + ".Authors"; + public const string Create = Default + ".Create"; + public const string Edit = Default + ".Edit"; + public const string Delete = Default + ".Delete"; } } ```` @@ -400,72 +393,71 @@ using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Repositories; -namespace Acme.BookStore +namespace Acme.BookStore; + +public class BookStoreDataSeederContributor + : IDataSeedContributor, ITransientDependency { - public class BookStoreDataSeederContributor - : IDataSeedContributor, ITransientDependency + private readonly IRepository _bookRepository; + private readonly IAuthorRepository _authorRepository; + private readonly AuthorManager _authorManager; + + public BookStoreDataSeederContributor( + IRepository bookRepository, + IAuthorRepository authorRepository, + AuthorManager authorManager) + { + _bookRepository = bookRepository; + _authorRepository = authorRepository; + _authorManager = authorManager; + } + + public async Task SeedAsync(DataSeedContext context) { - private readonly IRepository _bookRepository; - private readonly IAuthorRepository _authorRepository; - private readonly AuthorManager _authorManager; - - public BookStoreDataSeederContributor( - IRepository bookRepository, - IAuthorRepository authorRepository, - AuthorManager authorManager) + if (await _bookRepository.GetCountAsync() <= 0) { - _bookRepository = bookRepository; - _authorRepository = authorRepository; - _authorManager = authorManager; + await _bookRepository.InsertAsync( + new Book + { + Name = "1984", + Type = BookType.Dystopia, + PublishDate = new DateTime(1949, 6, 8), + Price = 19.84f + }, + autoSave: true + ); + + await _bookRepository.InsertAsync( + new Book + { + Name = "The Hitchhiker's Guide to the Galaxy", + Type = BookType.ScienceFiction, + PublishDate = new DateTime(1995, 9, 27), + Price = 42.0f + }, + autoSave: true + ); } - public async Task SeedAsync(DataSeedContext context) - { - if (await _bookRepository.GetCountAsync() <= 0) - { - await _bookRepository.InsertAsync( - new Book - { - Name = "1984", - Type = BookType.Dystopia, - PublishDate = new DateTime(1949, 6, 8), - Price = 19.84f - }, - autoSave: true - ); - - await _bookRepository.InsertAsync( - new Book - { - Name = "The Hitchhiker's Guide to the Galaxy", - Type = BookType.ScienceFiction, - PublishDate = new DateTime(1995, 9, 27), - Price = 42.0f - }, - autoSave: true - ); - } + // ADDED SEED DATA FOR AUTHORS - // ADDED SEED DATA FOR AUTHORS + if (await _authorRepository.GetCountAsync() <= 0) + { + await _authorRepository.InsertAsync( + await _authorManager.CreateAsync( + "George Orwell", + new DateTime(1903, 06, 25), + "Orwell produced literary criticism and poetry, fiction and polemical journalism; and is best known for the allegorical novella Animal Farm (1945) and the dystopian novel Nineteen Eighty-Four (1949)." + ) + ); - if (await _authorRepository.GetCountAsync() <= 0) - { - await _authorRepository.InsertAsync( - await _authorManager.CreateAsync( - "George Orwell", - new DateTime(1903, 06, 25), - "Orwell produced literary criticism and poetry, fiction and polemical journalism; and is best known for the allegorical novella Animal Farm (1945) and the dystopian novel Nineteen Eighty-Four (1949)." - ) - ); - - await _authorRepository.InsertAsync( - await _authorManager.CreateAsync( - "Douglas Adams", - new DateTime(1952, 03, 11), - "Douglas Adams was an English author, screenwriter, essayist, humorist, satirist and dramatist. Adams was an advocate for environmentalism and conservation, a lover of fast cars, technological innovation and the Apple Macintosh, and a self-proclaimed 'radical atheist'." - ) - ); - } + await _authorRepository.InsertAsync( + await _authorManager.CreateAsync( + "Douglas Adams", + new DateTime(1952, 03, 11), + "Douglas Adams was an English author, screenwriter, essayist, humorist, satirist and dramatist. Adams was an advocate for environmentalism and conservation, a lover of fast cars, technological innovation and the Apple Macintosh, and a self-proclaimed 'radical atheist'." + ) + ); } } } @@ -491,73 +483,73 @@ using System.Threading.Tasks; using Shouldly; using Xunit; -namespace Acme.BookStore.Authors -{ {{if DB=="Mongo"}} - [Collection(BookStoreTestConsts.CollectionDefinitionName)]{{end}} - public class AuthorAppService_Tests : BookStoreApplicationTestBase +namespace Acme.BookStore.Authors; + + {{if DB=="Mongo"}} +[Collection(BookStoreTestConsts.CollectionDefinitionName)]{{end}} +public class AuthorAppService_Tests : BookStoreApplicationTestBase +{ + private readonly IAuthorAppService _authorAppService; + + public AuthorAppService_Tests() { - private readonly IAuthorAppService _authorAppService; + _authorAppService = GetRequiredService(); + } - public AuthorAppService_Tests() - { - _authorAppService = GetRequiredService(); - } + [Fact] + public async Task Should_Get_All_Authors_Without_Any_Filter() + { + var result = await _authorAppService.GetListAsync(new GetAuthorListDto()); - [Fact] - public async Task Should_Get_All_Authors_Without_Any_Filter() - { - var result = await _authorAppService.GetListAsync(new GetAuthorListDto()); + result.TotalCount.ShouldBeGreaterThanOrEqualTo(2); + result.Items.ShouldContain(author => author.Name == "George Orwell"); + result.Items.ShouldContain(author => author.Name == "Douglas Adams"); + } - result.TotalCount.ShouldBeGreaterThanOrEqualTo(2); - result.Items.ShouldContain(author => author.Name == "George Orwell"); - result.Items.ShouldContain(author => author.Name == "Douglas Adams"); - } + [Fact] + public async Task Should_Get_Filtered_Authors() + { + var result = await _authorAppService.GetListAsync( + new GetAuthorListDto {Filter = "George"}); - [Fact] - public async Task Should_Get_Filtered_Authors() - { - var result = await _authorAppService.GetListAsync( - new GetAuthorListDto {Filter = "George"}); + result.TotalCount.ShouldBeGreaterThanOrEqualTo(1); + result.Items.ShouldContain(author => author.Name == "George Orwell"); + result.Items.ShouldNotContain(author => author.Name == "Douglas Adams"); + } - result.TotalCount.ShouldBeGreaterThanOrEqualTo(1); - result.Items.ShouldContain(author => author.Name == "George Orwell"); - result.Items.ShouldNotContain(author => author.Name == "Douglas Adams"); - } + [Fact] + public async Task Should_Create_A_New_Author() + { + var authorDto = await _authorAppService.CreateAsync( + new CreateAuthorDto + { + Name = "Edward Bellamy", + BirthDate = new DateTime(1850, 05, 22), + ShortBio = "Edward Bellamy was an American author..." + } + ); + + authorDto.Id.ShouldNotBe(Guid.Empty); + authorDto.Name.ShouldBe("Edward Bellamy"); + } - [Fact] - public async Task Should_Create_A_New_Author() + [Fact] + public async Task Should_Not_Allow_To_Create_Duplicate_Author() + { + await Assert.ThrowsAsync(async () => { - var authorDto = await _authorAppService.CreateAsync( + await _authorAppService.CreateAsync( new CreateAuthorDto { - Name = "Edward Bellamy", - BirthDate = new DateTime(1850, 05, 22), - ShortBio = "Edward Bellamy was an American author..." + Name = "Douglas Adams", + BirthDate = DateTime.Now, + ShortBio = "..." } ); - - authorDto.Id.ShouldNotBe(Guid.Empty); - authorDto.Name.ShouldBe("Edward Bellamy"); - } - - [Fact] - public async Task Should_Not_Allow_To_Create_Duplicate_Author() - { - await Assert.ThrowsAsync(async () => - { - await _authorAppService.CreateAsync( - new CreateAuthorDto - { - Name = "Douglas Adams", - BirthDate = DateTime.Now, - ShortBio = "..." - } - ); - }); - } - - //TODO: Test other methods... + }); } + + //TODO: Test other methods... } ```` diff --git a/docs/en/Tutorials/Part-9.md b/docs/en/Tutorials/Part-9.md index c85895a2bc..4e27655d64 100644 --- a/docs/en/Tutorials/Part-9.md +++ b/docs/en/Tutorials/Part-9.md @@ -95,14 +95,13 @@ This is a simple page similar to the Books page we had created before. It import ````csharp using Microsoft.AspNetCore.Mvc.RazorPages; -namespace Acme.BookStore.Web.Pages.Authors +namespace Acme.BookStore.Web.Pages.Authors; + +public class IndexModel : PageModel { - public class IndexModel : PageModel + public void OnGet() { - public void OnGet() - { - } } } ```` @@ -302,45 +301,44 @@ using Acme.BookStore.Authors; using Microsoft.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; -namespace Acme.BookStore.Web.Pages.Authors +namespace Acme.BookStore.Web.Pages.Authors; + +public class CreateModalModel : BookStorePageModel { - public class CreateModalModel : BookStorePageModel - { - [BindProperty] - public CreateAuthorViewModel Author { get; set; } + [BindProperty] + public CreateAuthorViewModel Author { get; set; } - private readonly IAuthorAppService _authorAppService; + private readonly IAuthorAppService _authorAppService; - public CreateModalModel(IAuthorAppService authorAppService) - { - _authorAppService = authorAppService; - } + public CreateModalModel(IAuthorAppService authorAppService) + { + _authorAppService = authorAppService; + } - public void OnGet() - { - Author = new CreateAuthorViewModel(); - } + public void OnGet() + { + Author = new CreateAuthorViewModel(); + } - public async Task OnPostAsync() - { - var dto = ObjectMapper.Map(Author); - await _authorAppService.CreateAsync(dto); - return NoContent(); - } + public async Task OnPostAsync() + { + var dto = ObjectMapper.Map(Author); + await _authorAppService.CreateAsync(dto); + return NoContent(); + } - public class CreateAuthorViewModel - { - [Required] - [StringLength(AuthorConsts.MaxNameLength)] - public string Name { get; set; } + public class CreateAuthorViewModel + { + [Required] + [StringLength(AuthorConsts.MaxNameLength)] + public string Name { get; set; } - [Required] - [DataType(DataType.Date)] - public DateTime BirthDate { get; set; } + [Required] + [DataType(DataType.Date)] + public DateTime BirthDate { get; set; } - [TextArea] - public string ShortBio { get; set; } - } + [TextArea] + public string ShortBio { get; set; } } } ``` @@ -359,18 +357,17 @@ using Acme.BookStore.Authors; // ADDED NAMESPACE IMPORT using Acme.BookStore.Books; using AutoMapper; -namespace Acme.BookStore.Web +namespace Acme.BookStore.Web; + +public class BookStoreWebAutoMapperProfile : Profile { - public class BookStoreWebAutoMapperProfile : Profile + public BookStoreWebAutoMapperProfile() { - public BookStoreWebAutoMapperProfile() - { - CreateMap(); + CreateMap(); - // ADD a NEW MAPPING - CreateMap(); - } + // ADD a NEW MAPPING + CreateMap(); } } ```` @@ -420,52 +417,51 @@ using Acme.BookStore.Authors; using Microsoft.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; -namespace Acme.BookStore.Web.Pages.Authors +namespace Acme.BookStore.Web.Pages.Authors; + +public class EditModalModel : BookStorePageModel { - public class EditModalModel : BookStorePageModel - { - [BindProperty] - public EditAuthorViewModel Author { get; set; } + [BindProperty] + public EditAuthorViewModel Author { get; set; } - private readonly IAuthorAppService _authorAppService; + private readonly IAuthorAppService _authorAppService; - public EditModalModel(IAuthorAppService authorAppService) - { - _authorAppService = authorAppService; - } + public EditModalModel(IAuthorAppService authorAppService) + { + _authorAppService = authorAppService; + } - public async Task OnGetAsync(Guid id) - { - var authorDto = await _authorAppService.GetAsync(id); - Author = ObjectMapper.Map(authorDto); - } + public async Task OnGetAsync(Guid id) + { + var authorDto = await _authorAppService.GetAsync(id); + Author = ObjectMapper.Map(authorDto); + } - public async Task OnPostAsync() - { - await _authorAppService.UpdateAsync( - Author.Id, - ObjectMapper.Map(Author) - ); + public async Task OnPostAsync() + { + await _authorAppService.UpdateAsync( + Author.Id, + ObjectMapper.Map(Author) + ); - return NoContent(); - } + return NoContent(); + } - public class EditAuthorViewModel - { - [HiddenInput] - public Guid Id { get; set; } + public class EditAuthorViewModel + { + [HiddenInput] + public Guid Id { get; set; } - [Required] - [StringLength(AuthorConsts.MaxNameLength)] - public string Name { get; set; } + [Required] + [StringLength(AuthorConsts.MaxNameLength)] + public string Name { get; set; } - [Required] - [DataType(DataType.Date)] - public DateTime BirthDate { get; set; } + [Required] + [DataType(DataType.Date)] + public DateTime BirthDate { get; set; } - [TextArea] - public string ShortBio { get; set; } - } + [TextArea] + public string ShortBio { get; set; } } } ``` @@ -482,22 +478,21 @@ using Acme.BookStore.Authors; using Acme.BookStore.Books; using AutoMapper; -namespace Acme.BookStore.Web +namespace Acme.BookStore.Web; + +public class BookStoreWebAutoMapperProfile : Profile { - public class BookStoreWebAutoMapperProfile : Profile + public BookStoreWebAutoMapperProfile() { - public BookStoreWebAutoMapperProfile() - { - CreateMap(); + CreateMap(); - CreateMap(); + CreateMap(); - // ADD THESE NEW MAPPINGS - CreateMap(); - CreateMap(); - } + // ADD THESE NEW MAPPINGS + CreateMap(); + CreateMap(); } } ``` @@ -1052,142 +1047,141 @@ using Blazorise.DataGrid; using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Dtos; -namespace Acme.BookStore.Blazor.Pages +namespace Acme.BookStore.Blazor.Pages; + +public partial class Authors { - public partial class Authors - { - private IReadOnlyList AuthorList { get; set; } + private IReadOnlyList AuthorList { get; set; } - private int PageSize { get; } = LimitedResultRequestDto.DefaultMaxResultCount; - private int CurrentPage { get; set; } - private string CurrentSorting { get; set; } - private int TotalCount { get; set; } + private int PageSize { get; } = LimitedResultRequestDto.DefaultMaxResultCount; + private int CurrentPage { get; set; } + private string CurrentSorting { get; set; } + private int TotalCount { get; set; } - private bool CanCreateAuthor { get; set; } - private bool CanEditAuthor { get; set; } - private bool CanDeleteAuthor { get; set; } + private bool CanCreateAuthor { get; set; } + private bool CanEditAuthor { get; set; } + private bool CanDeleteAuthor { get; set; } - private CreateAuthorDto NewAuthor { get; set; } + private CreateAuthorDto NewAuthor { get; set; } - private Guid EditingAuthorId { get; set; } - private UpdateAuthorDto EditingAuthor { get; set; } + private Guid EditingAuthorId { get; set; } + private UpdateAuthorDto EditingAuthor { get; set; } - private Modal CreateAuthorModal { get; set; } - private Modal EditAuthorModal { get; set; } + private Modal CreateAuthorModal { get; set; } + private Modal EditAuthorModal { get; set; } - private Validations CreateValidationsRef; - - private Validations EditValidationsRef; - - public Authors() - { - NewAuthor = new CreateAuthorDto(); - EditingAuthor = new UpdateAuthorDto(); - } + private Validations CreateValidationsRef; + + private Validations EditValidationsRef; + + public Authors() + { + NewAuthor = new CreateAuthorDto(); + EditingAuthor = new UpdateAuthorDto(); + } - protected override async Task OnInitializedAsync() - { - await SetPermissionsAsync(); - await GetAuthorsAsync(); - } + protected override async Task OnInitializedAsync() + { + await SetPermissionsAsync(); + await GetAuthorsAsync(); + } - private async Task SetPermissionsAsync() - { - CanCreateAuthor = await AuthorizationService - .IsGrantedAsync(BookStorePermissions.Authors.Create); + private async Task SetPermissionsAsync() + { + CanCreateAuthor = await AuthorizationService + .IsGrantedAsync(BookStorePermissions.Authors.Create); - CanEditAuthor = await AuthorizationService - .IsGrantedAsync(BookStorePermissions.Authors.Edit); + CanEditAuthor = await AuthorizationService + .IsGrantedAsync(BookStorePermissions.Authors.Edit); - CanDeleteAuthor = await AuthorizationService - .IsGrantedAsync(BookStorePermissions.Authors.Delete); - } + CanDeleteAuthor = await AuthorizationService + .IsGrantedAsync(BookStorePermissions.Authors.Delete); + } - private async Task GetAuthorsAsync() - { - var result = await AuthorAppService.GetListAsync( - new GetAuthorListDto - { - MaxResultCount = PageSize, - SkipCount = CurrentPage * PageSize, - Sorting = CurrentSorting - } - ); + private async Task GetAuthorsAsync() + { + var result = await AuthorAppService.GetListAsync( + new GetAuthorListDto + { + MaxResultCount = PageSize, + SkipCount = CurrentPage * PageSize, + Sorting = CurrentSorting + } + ); - AuthorList = result.Items; - TotalCount = (int)result.TotalCount; - } + AuthorList = result.Items; + TotalCount = (int)result.TotalCount; + } - private async Task OnDataGridReadAsync(DataGridReadDataEventArgs e) - { - CurrentSorting = e.Columns - .Where(c => c.SortDirection != SortDirection.Default) - .Select(c => c.Field + (c.SortDirection == SortDirection.Descending ? " DESC" : "")) - .JoinAsString(","); - CurrentPage = e.Page - 1; + private async Task OnDataGridReadAsync(DataGridReadDataEventArgs e) + { + CurrentSorting = e.Columns + .Where(c => c.SortDirection != SortDirection.Default) + .Select(c => c.Field + (c.SortDirection == SortDirection.Descending ? " DESC" : "")) + .JoinAsString(","); + CurrentPage = e.Page - 1; - await GetAuthorsAsync(); + await GetAuthorsAsync(); - await InvokeAsync(StateHasChanged); - } + await InvokeAsync(StateHasChanged); + } - private void OpenCreateAuthorModal() - { - CreateValidationsRef.ClearAll(); - - NewAuthor = new CreateAuthorDto(); - CreateAuthorModal.Show(); - } + private void OpenCreateAuthorModal() + { + CreateValidationsRef.ClearAll(); + + NewAuthor = new CreateAuthorDto(); + CreateAuthorModal.Show(); + } - private void CloseCreateAuthorModal() - { - CreateAuthorModal.Hide(); - } + private void CloseCreateAuthorModal() + { + CreateAuthorModal.Hide(); + } - private void OpenEditAuthorModal(AuthorDto author) - { - EditValidationsRef.ClearAll(); - - EditingAuthorId = author.Id; - EditingAuthor = ObjectMapper.Map(author); - EditAuthorModal.Show(); - } + private void OpenEditAuthorModal(AuthorDto author) + { + EditValidationsRef.ClearAll(); + + EditingAuthorId = author.Id; + EditingAuthor = ObjectMapper.Map(author); + EditAuthorModal.Show(); + } - private async Task DeleteAuthorAsync(AuthorDto author) + private async Task DeleteAuthorAsync(AuthorDto author) + { + var confirmMessage = L["AuthorDeletionConfirmationMessage", author.Name]; + if (!await Message.Confirm(confirmMessage)) { - var confirmMessage = L["AuthorDeletionConfirmationMessage", author.Name]; - if (!await Message.Confirm(confirmMessage)) - { - return; - } - - await AuthorAppService.DeleteAsync(author.Id); - await GetAuthorsAsync(); + return; } - private void CloseEditAuthorModal() - { - EditAuthorModal.Hide(); - } + await AuthorAppService.DeleteAsync(author.Id); + await GetAuthorsAsync(); + } - private async Task CreateAuthorAsync() + private void CloseEditAuthorModal() + { + EditAuthorModal.Hide(); + } + + private async Task CreateAuthorAsync() + { + if (await CreateValidationsRef.ValidateAll()) { - if (await CreateValidationsRef.ValidateAll()) - { - await AuthorAppService.CreateAsync(NewAuthor); - await GetAuthorsAsync(); - CreateAuthorModal.Hide(); - } + await AuthorAppService.CreateAsync(NewAuthor); + await GetAuthorsAsync(); + CreateAuthorModal.Hide(); } + } - private async Task UpdateAuthorAsync() + private async Task UpdateAuthorAsync() + { + if (await EditValidationsRef.ValidateAll()) { - if (await EditValidationsRef.ValidateAll()) - { - await AuthorAppService.UpdateAsync(EditingAuthorId, EditingAuthor); - await GetAuthorsAsync(); - EditAuthorModal.Hide(); - } + await AuthorAppService.UpdateAsync(EditingAuthorId, EditingAuthor); + await GetAuthorsAsync(); + EditAuthorModal.Hide(); } } }