Repository navigation
BookStore tutorial: Blazorise code samples still use the Blazorise 1.x API and do not compile with Blazorise 2.x #26311
Description
Is there an existing issue for this?
- I have searched the existing issues
Description
The Blazorise code samples in the BookStore tutorial (docs/en/tutorials/book-store/) were written against Blazorise 1.x. Since the Blazorise 2.0 upgrade they no longer compile, and two of the changes also cause silent runtime bugs.
Affected parts: 02, 03, 05, 09, 10 (the BlazorUI == "Blazorise" variants).
The changes required by Blazorise 2.0/2.3.0 are:
| Blazorise 1.x | Blazorise 2.x |
|---|---|
<TextEdit> / <MemoEdit> / <DateEdit> / <NumericEdit> |
<TextInput> / <MemoInput> / <DateInput> / <NumericInput> |
@bind-Text (TextEdit, MemoEdit) |
@bind-Value |
@bind-Date (DateEdit) |
@bind-Value |
@bind-SelectedValue (Select) |
@bind-Value |
context.X inside <DisplayTemplate> |
context.Item.X |
<DataGrid CurrentPage="..."> |
<DataGrid Page="..."> |
Width="150px" |
Width="Width.Px(150)" |
<ModalContent IsCentered="true"> |
Centered="true" on <Modal> |
Modal.Show() / Modal.Hide() (void) |
return Task, must be awaited |
Two of these fail silently rather than at compile time:
- The enum column is localized with
@L[$"Enum:BookType.{context.Type:D}"]. TheDformat specifier renders the enum name (ScienceFiction), but the localization keys are numeric (Enum:BookType.0...Enum:BookType.8, see part-02.md#L119-L127), so the cell shows the raw key instead of the translated text. It must be@L[$"Enum:BookType.{(int)context.Item.Type}"]. - The Edit modal binds
<Validations Model="@NewEntity">while its fields bindEditingEntity, so the edit form validates the create model and can never validate successfully.
The same context -> context.Item change is needed for the Clicked and ConfirmationMessage handlers of EntityAction / DropdownItem, and for the DataGridEntityActionsColumn in part-03 and part-05.
Reproduction Steps
-
Create a solution:
abp new Acme.BookStore -u blazor-server(or follow part-01 of the tutorial to create the same solution by hand). -
Follow part-03 "Book Creation Modal" (Blazorise variant) and paste the sample into
Books.razor. -
The project does not build. Typical errors:
- The component
TextEditcould not be found (Razor markup element with unexpected name). - The
Selectcomponent does not have a property matching the nameSelectedValue. - The
DateInput/TextInputcomponent does not have a property matching the nameDate/Text. - The
DataGridcomponent does not have a property matching the nameCurrentPage. - The
ModalContentcomponent does not have a property matching the nameIsCentered. - Cannot convert from
stringtoIFluentSizing(DataGridColumn.Width).
- The component
The same errors occur in part-02 (book list), part-05 (authorization), part-09 (authors) and part-10 (author selection).
Expected behavior
The samples compile and behave as the surrounding text describes.
The code generated by abp new is already correct and does compile: see src/Acme.BookStore.Blazor/Components/Pages/Books.razor and Authors.razor in the generated solution, which use <TextInput @bind-Value>, <DateInput @bind-Value>, <NumericInput @bind-Value>, <MemoInput @bind-Value>, <Select @bind-Value>, Page="CurrentPage", Centered="true" on <Modal>, and context.Item.
Actual behavior
Compile errors as listed above, plus:
- The book list "Type" column renders
Enum:BookType.ScienceFictioninstead of the localized text ("Science fiction"). - The Edit modal reports a validation error on the Name field even when it is filled in, because the create model is being validated.
Regression?
The samples were correct for Blazorise 1.x. They broke with the Blazorise 2.0 upgrade (PR #24906) and were not updated for Blazorise 2.3.0 (PR #25992). The migration guide documents exactly these changes (sections 2, 3, 5.1, 5.2, 5.3 and 6).
Known Workarounds
No response
Version
10.7.0
User Interface
Blazor Server
Database Provider
EF Core (Default)
Tiered or separate authentication server
None (Default)
Operation System
Linux
Other information
Affected lines
part-02.md
| Line | Current | Should be |
|---|---|---|
| L587 | @L[$"Enum:BookType.{context.Type}"] |
@L[$"Enum:BookType.{(int)context.Item.Type}"] |
| L594 | @context.PublishDate.ToShortDateString() |
@context.Item.PublishDate.ToShortDateString() |
| L605 | @context.CreationTime.ToLongDateString() |
@context.Item.CreationTime.ToLongDateString() |
part-03.md
| Line | Current | Should be |
|---|---|---|
| L1150 | <Modal @ref="@CreateModal"> |
<Modal @ref="@CreateModal" Centered="true"> |
| L1152 | <ModalContent IsCentered="true"> |
<ModalContent> |
| L1163 | <TextEdit @bind-Text="@NewEntity.Name"> |
<TextInput @bind-Value="@NewEntity.Name"> |
| L1172 | <Select TValue="BookType" @bind-SelectedValue="@NewEntity.Type"> |
<Select TValue="BookType" @bind-Value="@NewEntity.Type"> |
| L1183 | <DateEdit TValue="DateTime" @bind-Date="NewEntity.PublishDate"/> |
<DateInput TValue="DateTime" @bind-Value="NewEntity.PublishDate"/> |
| L1187 | <NumericEdit TValue="float" @bind-Value="NewEntity.Price"/> |
<NumericInput TValue="float" @bind-Value="NewEntity.Price"/> |
| L1284 | Clicked="() => OpenEditModalAsync(context)" |
Clicked="() => OpenEditModalAsync(context.Item)" |
| L1327 | <Modal @ref="@EditModal"> |
<Modal @ref="@EditModal" Centered="true"> |
| L1329 | <ModalContent IsCentered="true"> |
<ModalContent> |
| L1340 | <TextEdit @bind-Text="@EditingEntity.Name"> |
<TextInput @bind-Value="@EditingEntity.Name"> |
| L1349 | <Select TValue="BookType" @bind-SelectedValue="@EditingEntity.Type"> |
<Select TValue="BookType" @bind-Value="@EditingEntity.Type"> |
| L1360 | <DateEdit TValue="DateTime" @bind-Date="EditingEntity.PublishDate"/> |
<DateInput TValue="DateTime" @bind-Value="EditingEntity.PublishDate"/> |
| L1364 | <NumericEdit TValue="float" @bind-Value="EditingEntity.Price"/> |
<NumericInput TValue="float" @bind-Value="EditingEntity.Price"/> |
| L1464 | Clicked="() => DeleteEntityAsync(context)" |
Clicked="() => DeleteEntityAsync(context.Item)" |
| L1465 | ConfirmationMessage="() => GetDeleteConfirmationMessage(context)" |
ConfirmationMessage="() => GetDeleteConfirmationMessage(context.Item)" |
| L1529 | CurrentPage="CurrentPage" |
Page="CurrentPage" |
| L1539 | Clicked="() => OpenEditModalAsync(context)" |
Clicked="() => OpenEditModalAsync(context.Item)" |
| L1542 | Clicked="() => DeleteEntityAsync(context)" |
Clicked="() => DeleteEntityAsync(context.Item)" |
| L1543 | ConfirmationMessage="()=>GetDeleteConfirmationMessage(context)" |
ConfirmationMessage="()=>GetDeleteConfirmationMessage(context.Item)" |
| L1554 | @L[$"Enum:BookType.{context.Type:D}"] |
@L[$"Enum:BookType.{(int)context.Item.Type}"] |
| L1561 | @context.PublishDate.ToShortDateString() |
@context.Item.PublishDate.ToShortDateString() |
| L1572 | @context.CreationTime.ToLongDateString() |
@context.Item.CreationTime.ToLongDateString() |
| L1580 | <Modal @ref="@CreateModal"> |
<Modal @ref="@CreateModal" Centered="true"> |
| L1582 | <ModalContent IsCentered="true"> |
<ModalContent> |
| L1593 | <TextEdit @bind-Text="@NewEntity.Name"> |
<TextInput @bind-Value="@NewEntity.Name"> |
| L1602 | <Select TValue="BookType" @bind-SelectedValue="@NewEntity.Type"> |
<Select TValue="BookType" @bind-Value="@NewEntity.Type"> |
| L1613 | <DateEdit TValue="DateTime" @bind-Date="NewEntity.PublishDate"/> |
<DateInput TValue="DateTime" @bind-Value="NewEntity.PublishDate"/> |
| L1617 | <NumericEdit TValue="float" @bind-Value="NewEntity.Price"/> |
<NumericInput TValue="float" @bind-Value="NewEntity.Price"/> |
| L1633 | <Modal @ref="@EditModal"> |
<Modal @ref="@EditModal" Centered="true"> |
| L1635 | <ModalContent IsCentered="true"> |
<ModalContent> |
| L1646 | <TextEdit @bind-Text="@EditingEntity.Name"> |
<TextInput @bind-Value="@EditingEntity.Name"> |
| L1655 | <Select TValue="BookType" @bind-SelectedValue="@EditingEntity.Type"> |
<Select TValue="BookType" @bind-Value="@EditingEntity.Type"> |
| L1666 | <DateEdit TValue="DateTime" @bind-Date="EditingEntity.PublishDate"/> |
<DateInput TValue="DateTime" @bind-Value="EditingEntity.PublishDate"/> |
| L1670 | <NumericEdit TValue="float" @bind-Value="EditingEntity.Price"/> |
<NumericInput TValue="float" @bind-Value="EditingEntity.Price"/> |
part-05.md
| Line | Current | Should be |
|---|---|---|
| L471 | Clicked="() => OpenEditModalAsync(context)" |
Clicked="() => OpenEditModalAsync(context.Item)" |
| L475 | Clicked="() => DeleteEntityAsync(context)" |
Clicked="() => DeleteEntityAsync(context.Item)" |
| L476 | ConfirmationMessage="()=>GetDeleteConfirmationMessage(context)" |
ConfirmationMessage="()=>GetDeleteConfirmationMessage(context.Item)" |
part-09.md
| Line | Current | Should be |
|---|---|---|
| L876 | Width="150px" |
Width="Width.Px(150)" |
| L889 | Clicked="() => OpenEditAuthorModal(context)" |
Clicked="() => OpenEditAuthorModal(context.Item)" |
| L895 | Clicked="() => DeleteAuthorAsync(context)" |
Clicked="() => DeleteAuthorAsync(context.Item)" |
| L910 | @context.BirthDate.ToShortDateString() |
@context.Item.BirthDate.ToShortDateString() |
| L918 | <Modal @ref="CreateAuthorModal"> |
<Modal @ref="CreateAuthorModal" Centered="true"> |
| L920 | <ModalContent IsCentered="true"> |
<ModalContent> |
| L931 | <TextEdit @bind-Text="@NewAuthor.Name"> |
<TextInput @bind-Value="@NewAuthor.Name"> |
| L940 | <DateEdit TValue="DateTime" @bind-Date="@NewAuthor.BirthDate"/> |
<DateInput TValue="DateTime" @bind-Value="@NewAuthor.BirthDate"/> |
| L945 | <MemoEdit Rows="5" @bind-Text="@NewAuthor.ShortBio"> |
<MemoInput Rows="5" @bind-Value="@NewAuthor.ShortBio"> |
| L970 | <Modal @ref="EditAuthorModal"> |
<Modal @ref="EditAuthorModal" Centered="true"> |
| L972 | <ModalContent IsCentered="true"> |
<ModalContent> |
| L983 | <TextEdit @bind-Text="@EditingAuthor.Name"> |
<TextInput @bind-Value="@EditingAuthor.Name"> |
| L992 | <DateEdit TValue="DateTime" @bind-Date="@EditingAuthor.BirthDate"/> |
<DateInput TValue="DateTime" @bind-Value="@EditingAuthor.BirthDate"/> |
| L997 | <MemoEdit Rows="5" @bind-Text="@EditingAuthor.ShortBio"> |
<MemoInput Rows="5" @bind-Value="@EditingAuthor.ShortBio"> |
| L1246 | CreateAuthorModal.Show(); |
await CreateAuthorModal.Show(); (method must become async Task) |
| L1251 | CreateAuthorModal.Hide(); |
await CreateAuthorModal.Hide(); (method must become async Task) |
| L1260 | EditAuthorModal.Show(); |
await EditAuthorModal.Show(); (method must become async Task) |
| L1284 | EditAuthorModal.Hide(); |
await EditAuthorModal.Hide(); (method must become async Task) |
| L1295 | CreateAuthorModal.Hide(); |
await CreateAuthorModal.Hide(); |
| L1312 | EditAuthorModal.Hide(); |
await EditAuthorModal.Hide(); |
part-10.md
| Line | Current | Should be |
|---|---|---|
| L1282 | <Select TValue="Guid" @bind-SelectedValue="@NewEntity.AuthorId"> |
<Select TValue="Guid" @bind-Value="@NewEntity.AuthorId"> |
| L1327 | <Select TValue="Guid" @bind-SelectedValue="@EditingEntity.AuthorId"> |
<Select TValue="Guid" @bind-Value="@EditingEntity.AuthorId"> |
I'm happy to submit a PR.
Activity
Bahaaio commentedon Oct 20, 2026
A note on the error messages: the exact compiler output will vary with the Blazorise/.NET version and with which error is reported first, so some of the messages I listed may not all appear.
maliming commentedon Oct 21, 2026
hi
We will fix it in #26317
Thanks.