Skip to content

Commit 6408b73

Browse files
committed
Minor changes
1 parent 9283839 commit 6408b73

File tree

1 file changed

+118
-74
lines changed

1 file changed

+118
-74
lines changed

blog-posts/en/modular-monolith-application.md

Lines changed: 118 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ In this article, I will focus on how to implement a modular structure. I will no
1818
Let'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

2323
Add 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;
172172
using Abp.Localization.Dictionaries.Xml;
173173
using 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:
279279
Inside 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
313356
using 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
349392
using Abp.Application.Services.Dto;
350393
using Abp.Domain.Repositories;
351-
using Abp.Extensions;
352394
using Abp.Linq.Extensions;
353395
using BookTracking.Application.Books.Dto;
354396
using BookTracking.Core.Books;
@@ -357,7 +399,6 @@ using Abp.Application.Services;
357399
using Abp.UI;
358400
using Microsoft.EntityFrameworkCore;
359401

360-
361402
namespace BookTracking.Application.Books;
362403

363404
public 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;
437478
using BookTracking.Application.Books.Dto;
438479
using 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;
461501
using BookTracking.Core.Authorization;
462502
using 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;
572611
using BookTracking.Application.Books.Dto;
573612

574613
namespace 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;
592632
using BookTracking.Core;
593633
using 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;
764802
using Abp.AspNetCore.Mvc.Controllers;
765803
using BookTracking.Application.Books;
766804
using 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
9801024
using System.Reflection;
@@ -1098,9 +1142,9 @@ public virtual DbSet<Book> Books { get; set; }
10981142
public 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

Comments
 (0)