@@ -18,15 +18,15 @@ In this article, I will focus on how to implement a modular structure. I will no
18
18
Let's dive into the steps to create the ` BookTracking ` module.
19
19
20
20
### 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.
22
22
23
23
Add following nuget packages to the ` BookTracking.Core ` project:
24
24
25
25
``` xml
26
26
<ItemGroup >
27
27
<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 " />
30
30
</ItemGroup >
31
31
```
32
32
@@ -172,24 +172,24 @@ using Abp.Localization.Dictionaries;
172
172
using Abp .Localization .Dictionaries .Xml ;
173
173
using Abp .Reflection .Extensions ;
174
174
175
- namespace BookTracking .Core .Localization
175
+ namespace BookTracking .Core .Localization ;
176
+
177
+ public static class BookTrackingLocalizationConfigurer
176
178
{
177
- public static class BookTrackingLocalizationConfigurer
179
+ public static void Configure ( ILocalizationConfiguration localizationConfiguration )
178
180
{
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"
188
187
)
189
- );
190
- }
188
+ )
189
+ );
191
190
}
192
191
}
192
+
193
193
```
194
194
195
195
* 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
278
278
### 2. Add Business Logic Project:
279
279
Inside the ` BookTracking ` folder, add a new class library project named ` BookTracking.Application ` . This project will handle the business logic for the ` BookTracking ` module.
280
280
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.
282
282
283
283
#### DTO's
284
284
@@ -308,6 +308,49 @@ public class BookListDto : EntityDto
308
308
}
309
309
```
310
310
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
+
311
354
* GetBooksInput.cs*
312
355
``` csharp
313
356
using Abp .Application .Services .Dto ;
@@ -336,9 +379,9 @@ public interface IBookAppService : IApplicationService
336
379
{
337
380
Task <PagedResultDto <BookListDto >> GetBooks (GetBooksInput input );
338
381
339
- Task <CreateOrEditBookDto > GetUserForEdit (int id );
382
+ Task <GetBookForEditOutput > GetBookForEdit (int id );
340
383
341
- Task CreateOrEditBook (CreateOrEditBookDto input );
384
+ Task CreateOrEditBook (CreateOrEditBookInput input );
342
385
343
386
Task DeleteBook (int id );
344
387
}
@@ -348,7 +391,6 @@ public interface IBookAppService : IApplicationService
348
391
``` csharp
349
392
using Abp .Application .Services .Dto ;
350
393
using Abp .Domain .Repositories ;
351
- using Abp .Extensions ;
352
394
using Abp .Linq .Extensions ;
353
395
using BookTracking .Application .Books .Dto ;
354
396
using BookTracking .Core .Books ;
@@ -357,7 +399,6 @@ using Abp.Application.Services;
357
399
using Abp .UI ;
358
400
using Microsoft .EntityFrameworkCore ;
359
401
360
-
361
402
namespace BookTracking .Application .Books ;
362
403
363
404
public class BookAppService (IRepository <Book , int > bookRepository ) : ApplicationService , IBookAppService
@@ -378,16 +419,16 @@ public class BookAppService(IRepository<Book, int> bookRepository) : Application
378
419
return new PagedResultDto <BookListDto >(totalCount , bookList );
379
420
}
380
421
381
- public async Task <CreateOrEditBookDto > GetUserForEdit (int id )
422
+ public async Task <GetBookForEditOutput > GetBookForEdit (int id )
382
423
{
383
424
var book = await bookRepository .GetAsync (id );
384
425
385
- return ObjectMapper .Map <CreateOrEditBookDto >(book );
426
+ return ObjectMapper .Map <GetBookForEditOutput >(book );
386
427
}
387
428
388
- public async Task CreateOrEditBook (CreateOrEditBookDto input )
429
+ public async Task CreateOrEditBook (CreateOrEditBookInput input )
389
430
{
390
- if (input .Id .HasValue )
431
+ if (input .Book . Id .HasValue )
391
432
{
392
433
await UpdateBook (input );
393
434
}
@@ -409,16 +450,16 @@ public class BookAppService(IRepository<Book, int> bookRepository) : Application
409
450
await bookRepository .DeleteAsync (book );
410
451
}
411
452
412
- private async Task CreateBook (CreateOrEditBookDto input )
453
+ private async Task CreateBook (CreateOrEditBookInput input )
413
454
{
414
455
var book = ObjectMapper .Map <Book >(input );
415
456
416
457
await bookRepository .InsertAsync (book );
417
458
}
418
459
419
- private async Task UpdateBook (CreateOrEditBookDto input )
460
+ private async Task UpdateBook (CreateOrEditBookInput input )
420
461
{
421
- var book = await bookRepository .GetAsync (input .Id ! .Value );
462
+ var book = await bookRepository .GetAsync (input .Book . Id ! .Value );
422
463
423
464
ObjectMapper .Map (input , book );
424
465
@@ -437,16 +478,15 @@ using AutoMapper;
437
478
using BookTracking .Application .Books .Dto ;
438
479
using BookTracking .Core .Books ;
439
480
440
- namespace BookTracking .Application
481
+ namespace BookTracking .Application ;
482
+
483
+ internal static class BookTrackingDtoMapper
441
484
{
442
- internal static class BookTrackingDtoMapper
485
+ public static void CreateMappings ( IMapperConfigurationExpression configuration )
443
486
{
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
+
450
490
}
451
491
}
452
492
```
@@ -461,27 +501,25 @@ using Abp.Reflection.Extensions;
461
501
using BookTracking .Core .Authorization ;
462
502
using BookTracking .Core ;
463
503
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
465
510
{
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 ()
471
512
{
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 >();
476
515
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
+ }
480
519
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 ());
485
523
}
486
524
}
487
525
```
@@ -569,13 +607,15 @@ Create a sub folder named `Books` inside `Models` in the `BookTracking.Mvc` proj
569
607
570
608
* CreateOrEditBookModalViewModel.cs*
571
609
``` csharp
610
+ using Abp .AutoMapper ;
572
611
using BookTracking .Application .Books .Dto ;
573
612
574
613
namespace BookTracking .Mvc .Models .Books ;
575
614
576
- public class CreateOrEditBookModalViewModel
615
+ [AutoMapFrom (typeof (GetBookForEditOutput ))]
616
+ public class CreateOrEditBookModalViewModel : GetBookForEditOutput
577
617
{
578
- public CreateOrEditBookDto Book { get ; set ; }
618
+ public bool IsEditMode => Book . Id . HasValue ;
579
619
}
580
620
```
581
621
@@ -592,16 +632,15 @@ using Abp.Runtime.Session;
592
632
using BookTracking .Core ;
593
633
using Microsoft .AspNetCore .Mvc .Razor .Internal ;
594
634
595
- namespace BookTracking .Mvc .Views
635
+ namespace BookTracking .Mvc .Views ;
636
+
637
+ public abstract class BookTrackingRazorPage <TModel > : AbpRazorPage <TModel >
596
638
{
597
- public abstract class BookTrackingRazorPage <TModel > : AbpRazorPage <TModel >
639
+ [RazorInject ] public IAbpSession AbpSession { get ; set ; }
640
+
641
+ protected BookTrackingRazorPage ()
598
642
{
599
- [RazorInject ] public IAbpSession AbpSession { get ; set ; }
600
-
601
- protected BookTrackingRazorPage ()
602
- {
603
- LocalizationSourceName = BookTrackingConsts .LocalizationSourceName ;
604
- }
643
+ LocalizationSourceName = BookTrackingConsts .LocalizationSourceName ;
605
644
}
606
645
}
607
646
```
@@ -760,7 +799,6 @@ Let's add a controller to the `BookTracking.Mvc` project:
760
799
761
800
* BooksController.cs*
762
801
``` csharp
763
- using Abp .Application .Services .Dto ;
764
802
using Abp .AspNetCore .Mvc .Controllers ;
765
803
using BookTracking .Application .Books ;
766
804
using BookTracking .Application .Books .Dto ;
@@ -777,23 +815,27 @@ public class BooksController : AbpController
777
815
{
778
816
_bookAppService = bookAppService ;
779
817
}
780
-
818
+
781
819
public IActionResult Index ()
782
820
{
783
821
return View ();
784
822
}
785
-
823
+
786
824
public async Task <IActionResult > CreateOrEditModal (int ? id )
787
825
{
788
826
var viewModel = new CreateOrEditBookModalViewModel ();
789
-
827
+
790
828
if (id .HasValue )
791
829
{
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 );
795
833
}
796
-
834
+ else
835
+ {
836
+ viewModel .Book = new BookEditDto ();
837
+ }
838
+
797
839
return PartialView (" _CreateOrEditModal" , viewModel );
798
840
}
799
841
}
@@ -975,6 +1017,8 @@ Add js files to the `Views/Books` folder.
975
1017
976
1018
#### MVC Module
977
1019
1020
+ Create the following class under the ` BookTracking.Mvc ` project.
1021
+
978
1022
* BookTrackingWebModule.cs*
979
1023
``` csharp
980
1024
using System .Reflection ;
@@ -1098,9 +1142,9 @@ public virtual DbSet<Book> Books { get; set; }
1098
1142
public override void SetNavigation (INavigationProviderContext context )
1099
1143
{
1100
1144
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" ));
1104
1148
1105
1149
// other codes
1106
1150
}
0 commit comments