@ -63,18 +63,17 @@ The main entity of the application is the `Book`. Create a `Books` folder (names
using System;
using Volo.Abp.Domain.Entities.Auditing;
namespace Acme.BookStore.Books
namespace Acme.BookStore.Books;
public class Book : AuditedAggregateRoot<Guid>
{
public class Book : AuditedAggregateRoot<Guid>
{
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; }
}
````
@ -89,20 +88,19 @@ namespace Acme.BookStore.Books
The `Book` entity uses the `BookType` enum. Create a `Books` folder (namespace) in the `Acme.BookStore.Domain.Shared` project and add a `BookType` inside it:
````csharp
namespace Acme.BookStore.Books
namespace Acme.BookStore.Books;
public enum BookType
{
public enum BookType
{
Undefined,
Adventure,
Biography,
Dystopia,
Fantastic,
Horror,
Science,
ScienceFiction,
Poetry
}
Undefined,
Adventure,
Biography,
Dystopia,
Fantastic,
Horror,
Science,
ScienceFiction,
Poetry
}
````
@ -150,34 +148,33 @@ Navigate to the `OnModelCreating` method in the `BookStoreDbContext` class and a
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<Guid>
{
public class BookDto : AuditedEntityDto<Guid>
{
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<Guid>
{
public class AuthorLookupDto : EntityDto<Guid>
{
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
@ -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()
{
}
}
}
```
@ -537,7 +536,7 @@ Open the `/src/app/book/book.component.html` and replace the content as shown be
Now you can see the final result on your browser:


{{else if UI == "Blazor" || UI == "BlazorServer"}}
@ -581,7 +580,7 @@ context.Menu.AddItem(
Run the project, login to the application with the username `admin` and the password `1q2w3E*` and see that the new menu item has been added to the main menu:
@ -1252,7 +1250,7 @@ Open the `Books.razor` and add the following `DataGridEntityActionsColumn` secti
The `DataGridEntityActionsColumn` component is used to show an "Actions" dropdown for each row in the `DataGrid`. The `DataGridEntityActionsColumn` shows a **single button** instead of a dropdown if there is only one available action inside it:
@ -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"));
`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.
@ -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 async Task SeedAsync(DataSeedContext context)
{
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,74 @@ using System.Threading.Tasks;
@ -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()
{
}
}
}
````
@ -248,11 +247,11 @@ context.Menu.AddItem(
Run and login to the application. **You can not see the menu item since you don't have permission yet.** Go to the `Identity/Roles` page, click to the *Actions* button and select the *Permissions* action for the **admin role**:
As you see, the admin role has no *Author Management* permissions yet. Click to the checkboxes and save the modal to grant the necessary permissions. You will see the *Authors* menu item under the *Book Store* in the main menu, after **refreshing the page**:
@ -833,11 +828,11 @@ This page uses some localization keys we need to declare. Open the `en.json` fil
Run and login to the application. **You can not see the menu item since you don't have permission yet.** Go to the `identity/roles` page, click to the *Actions* button and select the *Permissions* action for the **admin role**:
As you see, the admin role has no *Author Management* permissions yet. Click to the checkboxes and save the modal to grant the necessary permissions. You will see the *Authors* menu item under the *Book Store* in the main menu, after **refreshing the page**:
@ -1240,11 +1232,11 @@ We should complete the localizations we've used above. Open the `en.json` file u
Run and login to the application. **If you don't see the Authors menu item under the Book Store menu, that means you don't have the permission yet.** Go to the `identity/roles` page, click to the *Actions* button and select the *Permissions* action for the **admin role**:
As you see, the admin role has no *Author Management* permissions yet. Click to the checkboxes and save the modal to grant the necessary permissions. You will see the *Authors* menu item under the *Book Store* in the main menu, after **refreshing the page**: