@@ -18,15 +18,15 @@ In this article, I will focus on how to implement a modular structure. I will no
1818Let's dive into the steps to create the ` BookTracking ` module.
1919
2020### 1. Add Core Project:
21- Add class library project named ` BookTracking.Core ` inside ` BookTracking ` folder. This project will contain the domain entities for the ` BookTracking ` module.
21+ Add class library project named ` BookTracking.Core ` inside ` BookTracking ` folder. This project will contain the domain entities for the ` BookTracking ` module. Setting the project location to ` {SolutionPath}/modules/BookTracking ` ensures proper organization.
2222
2323Add following nuget packages to the ` BookTracking.Core ` project:
2424
2525``` xml
2626<ItemGroup >
2727 <PackageReference Include =" Abp.AspNetZeroCore" Version =" 5.0.0" />
28- <PackageReference Include =" Abp.AutoMapper" Version =" 9.2.2 " />
29- <PackageReference Include =" Abp.ZeroCore.EntityFrameworkCore" Version =" 9.2.2 " />
28+ <PackageReference Include =" Abp.AutoMapper" Version =" 9.3.0 " />
29+ <PackageReference Include =" Abp.ZeroCore.EntityFrameworkCore" Version =" 9.3.0 " />
3030</ItemGroup >
3131```
3232
@@ -172,24 +172,24 @@ using Abp.Localization.Dictionaries;
172172using Abp .Localization .Dictionaries .Xml ;
173173using Abp .Reflection .Extensions ;
174174
175- namespace BookTracking .Core .Localization
175+ namespace BookTracking .Core .Localization ;
176+
177+ public static class BookTrackingLocalizationConfigurer
176178{
177- public static class BookTrackingLocalizationConfigurer
179+ public static void Configure ( ILocalizationConfiguration localizationConfiguration )
178180 {
179- public static void Configure (ILocalizationConfiguration localizationConfiguration )
180- {
181- localizationConfiguration .Sources .Add (
182- new DictionaryBasedLocalizationSource (
183- BookTrackingConsts .LocalizationSourceName ,
184- new XmlEmbeddedFileLocalizationDictionaryProvider (
185- typeof (BookTrackingLocalizationConfigurer ).GetAssembly (),
186- " BookTracking.Core.Localization"
187- )
181+ localizationConfiguration .Sources .Add (
182+ new DictionaryBasedLocalizationSource (
183+ BookTrackingConsts .LocalizationSourceName ,
184+ new XmlEmbeddedFileLocalizationDictionaryProvider (
185+ typeof (BookTrackingLocalizationConfigurer ).GetAssembly (),
186+ " BookTracking.Core.Localization"
188187 )
189- );
190- }
188+ )
189+ );
191190 }
192191}
192+
193193```
194194
195195* Let's configure csproj file of the ` BookTracking.Core ` project to include the localization files. Add the following code to the ` BookTracking.Core.csproj ` file:
@@ -278,7 +278,7 @@ public class Book : Entity, IMayHaveTenant
278278### 2. Add Business Logic Project:
279279Inside the ` BookTracking ` folder, add a new class library project named ` BookTracking.Application ` . This project will handle the business logic for the ` BookTracking ` module.
280280
281- Add reference to the ` BookTracking.Core ` project in the ` BookTracking.Application ` project.
281+ Add reference to the ` BookTracking.Core ` project in the ` BookTracking.Application ` project. When adding the reference, make sure to select the ` BookTracking.Core ` project under the modules directory.
282282
283283#### DTO's
284284
@@ -308,6 +308,49 @@ public class BookListDto : EntityDto
308308}
309309```
310310
311+ * BookEditDto.cs*
312+ ``` csharp
313+ using Abp .Application .Services .Dto ;
314+
315+ namespace BookTracking .Application .Books .Dto ;
316+
317+ public class BookEditDto : NullableIdDto
318+ {
319+ public string Name { get ; set ; }
320+
321+ public string Author { get ; set ; }
322+
323+ public string Description { get ; set ; }
324+
325+ public string ISBN { get ; set ; }
326+
327+ public int TotalPages { get ; set ; }
328+ }
329+ ```
330+
331+ * CreateOrEditBookInput.cs*
332+ ``` csharp
333+ using Abp .Application .Services .Dto ;
334+
335+ namespace BookTracking .Application .Books .Dto ;
336+
337+ public class CreateOrEditBookInput
338+ {
339+ [Required ]
340+ public BookEditDto Book { get ; set ; }
341+ }
342+ ```
343+
344+ * GetBookForEditOutput.cs*
345+ ``` csharp
346+ namespace BookTracking .Application .Books .Dto ;
347+
348+ public class GetBookForEditOutput
349+ {
350+ public BookEditDto Book { get ; set ; }
351+ }
352+ ```
353+
311354* GetBooksInput.cs*
312355``` csharp
313356using Abp .Application .Services .Dto ;
@@ -336,9 +379,9 @@ public interface IBookAppService : IApplicationService
336379{
337380 Task <PagedResultDto <BookListDto >> GetBooks (GetBooksInput input );
338381
339- Task <CreateOrEditBookDto > GetUserForEdit (int id );
382+ Task <GetBookForEditOutput > GetBookForEdit (int id );
340383
341- Task CreateOrEditBook (CreateOrEditBookDto input );
384+ Task CreateOrEditBook (CreateOrEditBookInput input );
342385
343386 Task DeleteBook (int id );
344387}
@@ -348,7 +391,6 @@ public interface IBookAppService : IApplicationService
348391``` csharp
349392using Abp .Application .Services .Dto ;
350393using Abp .Domain .Repositories ;
351- using Abp .Extensions ;
352394using Abp .Linq .Extensions ;
353395using BookTracking .Application .Books .Dto ;
354396using BookTracking .Core .Books ;
@@ -357,7 +399,6 @@ using Abp.Application.Services;
357399using Abp .UI ;
358400using Microsoft .EntityFrameworkCore ;
359401
360-
361402namespace BookTracking .Application .Books ;
362403
363404public class BookAppService (IRepository <Book , int > bookRepository ) : ApplicationService , IBookAppService
@@ -378,16 +419,16 @@ public class BookAppService(IRepository<Book, int> bookRepository) : Application
378419 return new PagedResultDto <BookListDto >(totalCount , bookList );
379420 }
380421
381- public async Task <CreateOrEditBookDto > GetUserForEdit (int id )
422+ public async Task <GetBookForEditOutput > GetBookForEdit (int id )
382423 {
383424 var book = await bookRepository .GetAsync (id );
384425
385- return ObjectMapper .Map <CreateOrEditBookDto >(book );
426+ return ObjectMapper .Map <GetBookForEditOutput >(book );
386427 }
387428
388- public async Task CreateOrEditBook (CreateOrEditBookDto input )
429+ public async Task CreateOrEditBook (CreateOrEditBookInput input )
389430 {
390- if (input .Id .HasValue )
431+ if (input .Book . Id .HasValue )
391432 {
392433 await UpdateBook (input );
393434 }
@@ -409,16 +450,16 @@ public class BookAppService(IRepository<Book, int> bookRepository) : Application
409450 await bookRepository .DeleteAsync (book );
410451 }
411452
412- private async Task CreateBook (CreateOrEditBookDto input )
453+ private async Task CreateBook (CreateOrEditBookInput input )
413454 {
414455 var book = ObjectMapper .Map <Book >(input );
415456
416457 await bookRepository .InsertAsync (book );
417458 }
418459
419- private async Task UpdateBook (CreateOrEditBookDto input )
460+ private async Task UpdateBook (CreateOrEditBookInput input )
420461 {
421- var book = await bookRepository .GetAsync (input .Id ! .Value );
462+ var book = await bookRepository .GetAsync (input .Book . Id ! .Value );
422463
423464 ObjectMapper .Map (input , book );
424465
@@ -437,16 +478,15 @@ using AutoMapper;
437478using BookTracking .Application .Books .Dto ;
438479using BookTracking .Core .Books ;
439480
440- namespace BookTracking .Application
481+ namespace BookTracking .Application ;
482+
483+ internal static class BookTrackingDtoMapper
441484{
442- internal static class BookTrackingDtoMapper
485+ public static void CreateMappings ( IMapperConfigurationExpression configuration )
443486 {
444- public static void CreateMappings (IMapperConfigurationExpression configuration )
445- {
446- configuration .CreateMap <Book , BookListDto >().ReverseMap ();
447- configuration .CreateMap <Book , CreateOrEditBookDto >().ReverseMap ();
448-
449- }
487+ configuration .CreateMap <Book , BookListDto >().ReverseMap ();
488+ configuration .CreateMap <Book , CreateOrEditBookInput >().ReverseMap ();
489+
450490 }
451491}
452492```
@@ -461,27 +501,25 @@ using Abp.Reflection.Extensions;
461501using BookTracking .Core .Authorization ;
462502using BookTracking .Core ;
463503
464- namespace BookTracking .Application
504+ namespace BookTracking .Application ;
505+ /// <summary >
506+ /// Application layer module of the application.
507+ /// </summary >
508+ [DependsOn (typeof (BookTrackingCoreModule ))]
509+ public class BookTrackingApplicationModule : AbpModule
465510{
466- /// <summary >
467- /// Application layer module of the application.
468- /// </summary >
469- [DependsOn (typeof (BookTrackingCoreModule ))]
470- public class BookTrackingApplicationModule : AbpModule
511+ public override void PreInitialize ()
471512 {
472- public override void PreInitialize ()
473- {
474- // Adding authorization providers
475- Configuration .Authorization .Providers .Add <BookTrackingAuthorizationProvider >();
513+ // Adding authorization providers
514+ Configuration .Authorization .Providers .Add <BookTrackingAuthorizationProvider >();
476515
477- // Adding custom AutoMapper configuration
478- Configuration .Modules .AbpAutoMapper ().Configurators .Add (BookTrackingDtoMapper .CreateMappings );
479- }
516+ // Adding custom AutoMapper configuration
517+ Configuration .Modules .AbpAutoMapper ().Configurators .Add (BookTrackingDtoMapper .CreateMappings );
518+ }
480519
481- public override void Initialize ()
482- {
483- IocManager .RegisterAssemblyByConvention (typeof (BookTrackingApplicationModule ).GetAssembly ());
484- }
520+ public override void Initialize ()
521+ {
522+ IocManager .RegisterAssemblyByConvention (typeof (BookTrackingApplicationModule ).GetAssembly ());
485523 }
486524}
487525```
@@ -569,13 +607,15 @@ Create a sub folder named `Books` inside `Models` in the `BookTracking.Mvc` proj
569607
570608* CreateOrEditBookModalViewModel.cs*
571609``` csharp
610+ using Abp .AutoMapper ;
572611using BookTracking .Application .Books .Dto ;
573612
574613namespace BookTracking .Mvc .Models .Books ;
575614
576- public class CreateOrEditBookModalViewModel
615+ [AutoMapFrom (typeof (GetBookForEditOutput ))]
616+ public class CreateOrEditBookModalViewModel : GetBookForEditOutput
577617{
578- public CreateOrEditBookDto Book { get ; set ; }
618+ public bool IsEditMode => Book . Id . HasValue ;
579619}
580620```
581621
@@ -592,16 +632,15 @@ using Abp.Runtime.Session;
592632using BookTracking .Core ;
593633using Microsoft .AspNetCore .Mvc .Razor .Internal ;
594634
595- namespace BookTracking .Mvc .Views
635+ namespace BookTracking .Mvc .Views ;
636+
637+ public abstract class BookTrackingRazorPage <TModel > : AbpRazorPage <TModel >
596638{
597- public abstract class BookTrackingRazorPage <TModel > : AbpRazorPage <TModel >
639+ [RazorInject ] public IAbpSession AbpSession { get ; set ; }
640+
641+ protected BookTrackingRazorPage ()
598642 {
599- [RazorInject ] public IAbpSession AbpSession { get ; set ; }
600-
601- protected BookTrackingRazorPage ()
602- {
603- LocalizationSourceName = BookTrackingConsts .LocalizationSourceName ;
604- }
643+ LocalizationSourceName = BookTrackingConsts .LocalizationSourceName ;
605644 }
606645}
607646```
@@ -760,7 +799,6 @@ Let's add a controller to the `BookTracking.Mvc` project:
760799
761800* BooksController.cs*
762801``` csharp
763- using Abp .Application .Services .Dto ;
764802using Abp .AspNetCore .Mvc .Controllers ;
765803using BookTracking .Application .Books ;
766804using BookTracking .Application .Books .Dto ;
@@ -777,23 +815,27 @@ public class BooksController : AbpController
777815 {
778816 _bookAppService = bookAppService ;
779817 }
780-
818+
781819 public IActionResult Index ()
782820 {
783821 return View ();
784822 }
785-
823+
786824 public async Task <IActionResult > CreateOrEditModal (int ? id )
787825 {
788826 var viewModel = new CreateOrEditBookModalViewModel ();
789-
827+
790828 if (id .HasValue )
791829 {
792- viewModel . Book = await _bookAppService .GetUserForEdit (id .Value );
793- } else {
794- viewModel .Book = new CreateOrEditBookDto ( );
830+ var book = await _bookAppService .GetBookForEdit (id .Value );
831+
832+ viewModel .Book = ObjectMapper . Map < BookEditDto >( book );
795833 }
796-
834+ else
835+ {
836+ viewModel .Book = new BookEditDto ();
837+ }
838+
797839 return PartialView (" _CreateOrEditModal" , viewModel );
798840 }
799841}
@@ -975,6 +1017,8 @@ Add js files to the `Views/Books` folder.
9751017
9761018#### MVC Module
9771019
1020+ Create the following class under the ` BookTracking.Mvc ` project.
1021+
9781022* BookTrackingWebModule.cs*
9791023``` csharp
9801024using System .Reflection ;
@@ -1098,9 +1142,9 @@ public virtual DbSet<Book> Books { get; set; }
10981142public override void SetNavigation (INavigationProviderContext context )
10991143{
11001144
1101- var menu = context .Manager .Menus [MenuName ] = context .Manager .Menus .ContainsKey (MenuName )
1102- ? context .Manager .Menus [MenuName ]
1103- : new MenuDefinition (MenuName , new FixedLocalizableString (" Main Menu" ));
1145+ var menu = context .Manager .Menus [MenuName ] = context .Manager .Menus .ContainsKey (MenuName )
1146+ ? context .Manager .Menus [MenuName ]
1147+ : new MenuDefinition (MenuName , new FixedLocalizableString (" Main Menu" ));
11041148
11051149// other codes
11061150 }
0 commit comments