Browse Source

Merge branch 'dev' into gterdem/article_revision

pull/14878/head
Galip Tolga Erdem 4 years ago
parent
commit
e44c09a3da
  1. 71
      docs/en/Community-Articles/2022-11-28-ef-bulk-operations/POST.md
  2. 53
      docs/en/Dependency-Injection.md
  3. 8
      docs/en/Migration-Guides/Abp-7_0.md
  4. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
  5. 20
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs
  6. 3
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFramework.cs
  7. 40
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs
  8. 34
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/MauiBlazorChangeApplicationIdGuidStep.cs
  9. 50
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/MauiBlazorPortChangeForSeparatedAuthServersStep.cs
  10. 1
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Maui/MauiChangePortStep.cs

71
docs/en/Community-Articles/2022-11-28-ef-bulk-operations/POST.md

@ -0,0 +1,71 @@
# Bulk Operations with Entity Framework Core 7.0
Entity Framework tracks all the entity changes and applies those changes to the database one by one when the `SaveChanges()` method is called. There was no way to execute bulk operations in Entity Framework Core without a dependency.
As you know the [Entity Framework Extensions](https://entityframework-extensions.net/bulk-savechanges) library was doing it but it was not free.
There was no other solution until now. [Bulk Operations](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-7.0/whatsnew#executeupdate-and-executedelete-bulk-updates) are now available in Entity Framework Core with .NET 7.
With .NET 7, there are two new methods such as `ExecuteUpdate` and `ExecuteDelete` available to execute bulk operations. It's a similar usage with the Entity Framework Core Extensions library if you're familiar with it.
You can visit the microsoft example [here](https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-7.0/whatsnew#executeupdate-and-executedelete-bulk-updates) about how to use it.
It can be easily used with the DbContext.
```csharp
await context.Tags.Where(t => t.Text.Contains(".NET")).ExecuteDeleteAsync();
```
## Using with ABP Framework
ABP Framework provides an abstraction over database operations and implements generic repository pattern. So, DbContext can't be accessed outside of [repositories](https://docs.abp.io/en/abp/latest/Repositories).
You can use the `ExecuteUpdate` and `ExecuteDelete` methods inside a repository.
```csharp
public class BookEntityFrameworkCoreRepository : EfCoreRepository<BookStoreDbContext, Book, Guid>, IBookRepository
{
public BookEntityFrameworkCoreRepository(IDbContextProvider<BookStoreDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public async Task UpdateListingAsync()
{
var dbSet = await GetDbSetAsync();
await dbSet
.Where(x => x.IsListed && x.PublishedOn.Year <= 2022)
.ExecuteUpdateAsync(s => s.SetProperty(x => x.IsListed, x => false));
}
public async Task DeleteOldBooksAsync()
{
var dbSet = await GetDbSetAsync();
await dbSet
.Where(x => x.PublishedOn.Year <= 2000)
.ExecuteDeleteAsync();
}
}
```
There is no need to take an action for bulk inserting. You can use the `InsertManyAsync` method of the repository instead of creating a new method for it if you don't have custom logic. It'll use a new bulk inserting feature automatically since it's available in EF Core 7.0.
```csharp
public class MyDomainService : DomainService
{
protected IRepository<Book, Guid> BookRepository { get; }
public MyDomainService(IRepository<Book, Guid> bookRepository)
{
BookRepository = bookRepository;
}
public async Task CreateBooksAsync(List<Book> books)
{
// It'll use bulk inserting automatically.
await BookRepository.InsertManyAsync(books);
}
}
```
> If you use `ExecuteDeleteAsync` or `ExecuteUpdateAsync`, then ABP's soft delete and auditing features can not work. Because these ABP features work with EF Core's change tracking system and these new methods doesn't work with the change tracking system. So, use them carefully.

53
docs/en/Dependency-Injection.md

@ -2,7 +2,7 @@
ABP's Dependency Injection system is developed based on Microsoft's [dependency injection extension](https://medium.com/volosoft/asp-net-core-dependency-injection-best-practices-tips-tricks-c6e9c67f9d96) library (Microsoft.Extensions.DependencyInjection nuget package). So, it's documentation is valid in ABP too. ABP's Dependency Injection system is developed based on Microsoft's [dependency injection extension](https://medium.com/volosoft/asp-net-core-dependency-injection-best-practices-tips-tricks-c6e9c67f9d96) library (Microsoft.Extensions.DependencyInjection nuget package). So, it's documentation is valid in ABP too.
> While ABP has no core dependency to any 3rd-party DI provider, it's required to use a provider that supports dynamic proxying and some other advanced features to make some ABP features properly work. Startup templates come with Autofac installed. See [Autofac integration](Autofac-Integration.md) document for more information. > While ABP has no core dependency to any 3rd-party DI provider. However, it's required to use a provider that supports dynamic proxying and some other advanced features to make some ABP features properly work. Startup templates come with [Autofac](https://autofac.org/) installed. See [Autofac integration](Autofac-Integration.md) document for more information.
## Modularity ## Modularity
@ -20,24 +20,24 @@ public class BlogModule : AbpModule
## Conventional Registration ## Conventional Registration
ABP introduces conventional service registration. You need not do anything to register a service by convention. It's automatically done. If you want to disable it, you can set `SkipAutoServiceRegistration` to `true` by overriding the `PreConfigureServices` method. ABP introduces conventional service registration. You need not do anything to register a service by convention. It's automatically done. If you want to disable it, you can set `SkipAutoServiceRegistration` to `true` in the constructor of your module class. Example:
````C# ````C#
public class BlogModule : AbpModule public class BlogModule : AbpModule
{ {
public override void PreConfigureServices(ServiceConfigurationContext context) public BlogModule()
{ {
SkipAutoServiceRegistration = true; SkipAutoServiceRegistration = true;
} }
} }
```` ````
Once you skip auto registration, you should manually register your services. In that case, ``AddAssemblyOf`` extension method can help you to register all your services by convention. Example: Once you skip the auto registration, you should manually register your services. In that case, ``AddAssemblyOf`` extension method can help you to register all your services by convention. Example:
````c# ````c#
public class BlogModule : AbpModule public class BlogModule : AbpModule
{ {
public override void PreConfigureServices(ServiceConfigurationContext context) public BlogModule()
{ {
SkipAutoServiceRegistration = true; SkipAutoServiceRegistration = true;
} }
@ -105,9 +105,7 @@ Example:
[Dependency(ServiceLifetime.Transient, ReplaceServices = true)] [Dependency(ServiceLifetime.Transient, ReplaceServices = true)]
public class TaxCalculator public class TaxCalculator
{ {
} }
```` ````
``Dependency`` attribute has a higher priority than other dependency interfaces if it defines the ``Lifetime`` property. ``Dependency`` attribute has a higher priority than other dependency interfaces if it defines the ``Lifetime`` property.
@ -120,7 +118,6 @@ public class TaxCalculator
[ExposeServices(typeof(ITaxCalculator))] [ExposeServices(typeof(ITaxCalculator))]
public class TaxCalculator: ICalculator, ITaxCalculator, ICanCalculate, ITransientDependency public class TaxCalculator: ICalculator, ITaxCalculator, ICanCalculate, ITransientDependency
{ {
} }
```` ````
@ -179,7 +176,11 @@ public class MyModule : AbpModule
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
//Replacing the IConnectionStringResolver service //Replacing the IConnectionStringResolver service
context.Services.Replace(ServiceDescriptor.Transient<IConnectionStringResolver, MyConnectionStringResolver>()); context.Services.Replace(
ServiceDescriptor.Transient<
IConnectionStringResolver,
MyConnectionStringResolver
>());
} }
} }
```` ````
@ -202,7 +203,7 @@ public class TaxAppService : ApplicationService
_taxCalculator = taxCalculator; _taxCalculator = taxCalculator;
} }
public void DoSomething() public async Task DoSomethingAsync()
{ {
//...use _taxCalculator... //...use _taxCalculator...
} }
@ -227,7 +228,7 @@ public class MyService : ITransientDependency
Logger = NullLogger<MyService>.Instance; Logger = NullLogger<MyService>.Instance;
} }
public void DoSomething() public async Task DoSomethingAsync()
{ {
//...use Logger to write logs... //...use Logger to write logs...
} }
@ -244,17 +245,21 @@ One restriction of property injection is that you cannot use the dependency in y
Property injection is also useful when you want to design a base class that has some common services injected by default. If you're going to use constructor injection, all derived classes should also inject depended services into their own constructors which makes development harder. However, be very careful using property injection for non-optional services as it makes it harder to clearly see the requirements of a class. Property injection is also useful when you want to design a base class that has some common services injected by default. If you're going to use constructor injection, all derived classes should also inject depended services into their own constructors which makes development harder. However, be very careful using property injection for non-optional services as it makes it harder to clearly see the requirements of a class.
#### DisablePropertyInjectionAttribute #### DisablePropertyInjection Attribute
You can use `[DisablePropertyInjection]` attribute on class or properties to disable property injection for the whole class or some specific properties. You can use `[DisablePropertyInjection]` attribute on classes or their properties to disable property injection for the whole class or some specific properties.
````C# ````C#
// Disabling for all properties of the MyService class
[DisablePropertyInjection] [DisablePropertyInjection]
public class MyService : ITransientDependency public class MyService : ITransientDependency
{ {
public ILogger<MyService> Logger { get; set; }
public ITaxCalculator TaxCalculator { get; set; } public ITaxCalculator TaxCalculator { get; set; }
} }
// Disabling only for the TaxCalculator property
public class MyService : ITransientDependency public class MyService : ITransientDependency
{ {
public ILogger<MyService> Logger { get; set; } public ILogger<MyService> Logger { get; set; }
@ -262,17 +267,21 @@ public class MyService : ITransientDependency
[DisablePropertyInjection] [DisablePropertyInjection]
public ITaxCalculator TaxCalculator { get; set; } public ITaxCalculator TaxCalculator { get; set; }
} }
```` ````
### Resolve Service from IServiceProvider ### Resolve Service from IServiceProvider
You may want to resolve a service directly from ``IServiceProvider``. In that case, you can inject IServiceProvider into your class and use ``GetService`` method as shown below: You may want to resolve a service directly from ``IServiceProvider``. In that case, you can inject `IServiceProvider` into your class and use the ``GetService`` or the `GetRequiredService` method as shown below:
````C# ````C#
public class MyService : ITransientDependency public class MyService : ITransientDependency
{ {
public ILogger<MyService> Logger { get; set; } private readonly ITaxCalculator _taxCalculator;
public MyService(IServiceProvider serviceProvider)
{
_taxCalculator = serviceProvider.GetRequiredService<ITaxCalculator>();
}
} }
```` ````
@ -374,15 +383,15 @@ IEnumerable<IExternalLogger> services = _serviceProvider.GetServices<IExternalLo
### Releasing/Disposing Services ### Releasing/Disposing Services
If you used a constructor or property injection, you don't need to be concerned about releasing the service's resources. However, if you have resolved a service from ``IServiceProvider``, you might, in some cases, need to take care about releasing the service resources. If you used a constructor or property injection, you don't need to be concerned about releasing the service's resources. However, if you have resolved a service from ``IServiceProvider``, in some cases, you might need to take care about releasing the service resources.
ASP.NET Core releases all services at the end of a current HTTP request, even if you directly resolved from ``IServiceProvider`` (assuming you injected IServiceProvider). But, there are several cases where you may want to release/dispose manually resolved services: ASP.NET Core releases all services at the end of a current HTTP request, even if you directly resolved from ``IServiceProvider`` (assuming you injected `IServiceProvider`). But, there are several cases where you may want to release/dispose manually resolved services:
* Your code is executed outside of AspNet Core request and the executer hasn't handled the service scope. * Your code is executed outside of ASP.NET Core request and the executer hasn't handled the service scope.
* You only have a reference to the root service provider. * You only have a reference to the root service provider.
* You may want to immediately release & dispose services (for example, you may creating too many services with big memory usage and don't want to overuse memory). * You may want to immediately release & dispose services (for example, you may creating too many services with big memory usages and don't want to overuse the memory).
In any case, you can use such a 'using' code block to safely and immediately release services: In any case, you can create a service scope block to safely and immediately release services:
````C# ````C#
using (var scope = _serviceProvider.CreateScope()) using (var scope = _serviceProvider.CreateScope())
@ -392,7 +401,7 @@ using (var scope = _serviceProvider.CreateScope())
} }
```` ````
Both services are released when the created scope is disposed (at the end of the using block). Both services are released when the created scope is disposed (at the end of the `using` block).
## Advanced Features ## Advanced Features

8
docs/en/Migration-Guides/Abp-7_0.md

@ -101,3 +101,11 @@ See https://github.com/abpframework/abp/pull/13644 for more info.
We've already done this for our themes. We've already done this for our themes.
See https://github.com/abpframework/abp/pull/13845 for more info. See https://github.com/abpframework/abp/pull/13845 for more info.
## Replaced `BlogPostPublicDto` with `BlogPostCommonDto`
- In the CMS Kit Module, `BlogPostPublicDto` has been moved to `Volo.CmsKit.Common.Application.Contracts` from `Volo.CmsKit.Public.Application.Contracts` and renamed to `BlogPostCommonDto`.
- See the [PR#13499](https://github.com/abpframework/abp/pull/13499) for more information.
> You can ignore this if you don't use CMS Kit Module.

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs

@ -111,7 +111,7 @@ public class NewCommand : ProjectCreationCommandBase, IConsoleCommand, ITransien
var skipBundling = commandLineArgs.Options.ContainsKey(Options.SkipBundling.Long) || commandLineArgs.Options.ContainsKey(Options.SkipBundling.Short); var skipBundling = commandLineArgs.Options.ContainsKey(Options.SkipBundling.Long) || commandLineArgs.Options.ContainsKey(Options.SkipBundling.Short);
if (!skipBundling) if (!skipBundling)
{ {
await RunBundleForBlazorWasmTemplateAsync(projectArgs); await RunBundleForBlazorWasmOrMauiBlazorTemplateAsync(projectArgs);
} }
await ConfigurePwaSupportForAngular(projectArgs); await ConfigurePwaSupportForAngular(projectArgs);

20
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs

@ -118,7 +118,7 @@ public abstract class ProjectCreationCommandBase
Logger.LogInformation("DBMS: " + databaseManagementSystem); Logger.LogInformation("DBMS: " + databaseManagementSystem);
} }
var uiFramework = GetUiFramework(commandLineArgs); var uiFramework = GetUiFramework(commandLineArgs, template);
if (uiFramework != UiFramework.NotSpecified) if (uiFramework != UiFramework.NotSpecified)
{ {
Logger.LogInformation("UI Framework: " + uiFramework); Logger.LogInformation("UI Framework: " + uiFramework);
@ -413,22 +413,24 @@ public abstract class ProjectCreationCommandBase
} }
} }
protected async Task RunBundleForBlazorWasmTemplateAsync(ProjectBuildArgs projectArgs) protected async Task RunBundleForBlazorWasmOrMauiBlazorTemplateAsync(ProjectBuildArgs projectArgs)
{ {
if (AppTemplateBase.IsAppTemplate(projectArgs.TemplateName) && projectArgs.UiFramework == UiFramework.Blazor) if (AppTemplateBase.IsAppTemplate(projectArgs.TemplateName) && projectArgs.UiFramework is UiFramework.Blazor or UiFramework.MauiBlazor)
{ {
Logger.LogInformation("Generating bundles for Blazor Wasm..."); var isWebassembly = projectArgs.UiFramework == UiFramework.Blazor;
var message = isWebassembly ? "Generating bundles for Blazor Wasm" : "Generating bundles for MAUI Blazor";
Logger.LogInformation($"{message}...");
await EventBus.PublishAsync(new ProjectCreationProgressEvent await EventBus.PublishAsync(new ProjectCreationProgressEvent
{ {
Message = "Generating bundles for Blazor Wasm" Message = message
}, false); }, false);
var directory = Path.GetDirectoryName( var directory = Path.GetDirectoryName(
Directory.GetFiles(projectArgs.OutputFolder, "*.Blazor.csproj", SearchOption.AllDirectories).First() Directory.GetFiles(projectArgs.OutputFolder, isWebassembly? "*.Blazor.csproj" :"*.MauiBlazor.csproj", SearchOption.AllDirectories).First()
); );
await _bundlingService.BundleAsync(directory, true); await _bundlingService.BundleAsync(directory, true, projectType: isWebassembly ? BundlingConsts.WebAssembly : BundlingConsts.MauiBlazor);
} }
} }
@ -531,7 +533,7 @@ public abstract class ProjectCreationCommandBase
} }
} }
protected virtual UiFramework GetUiFramework(CommandLineArgs commandLineArgs) protected virtual UiFramework GetUiFramework(CommandLineArgs commandLineArgs, string template = "app")
{ {
if (commandLineArgs.Options.ContainsKey("no-ui")) if (commandLineArgs.Options.ContainsKey("no-ui"))
{ {
@ -554,6 +556,8 @@ public abstract class ProjectCreationCommandBase
return UiFramework.Blazor; return UiFramework.Blazor;
case "blazor-server": case "blazor-server":
return UiFramework.BlazorServer; return UiFramework.BlazorServer;
case "maui-blazor" when template == AppProTemplate.TemplateName:
return UiFramework.MauiBlazor;
default: default:
throw new CliUsageException(ExceptionMessageHelper.GetInvalidOptionExceptionMessage("UI Framework")); throw new CliUsageException(ExceptionMessageHelper.GetInvalidOptionExceptionMessage("UI Framework"));
} }

3
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFramework.cs

@ -7,5 +7,6 @@ public enum UiFramework
Mvc = 2, Mvc = 2,
Angular = 3, Angular = 3,
Blazor = 4, Blazor = 4,
BlazorServer = 5 BlazorServer = 5,
MauiBlazor = 6
} }

40
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs

@ -132,7 +132,11 @@ public abstract class AppTemplateBase : TemplateInfo
case UiFramework.BlazorServer: case UiFramework.BlazorServer:
ConfigureWithBlazorServerUi(context, steps); ConfigureWithBlazorServerUi(context, steps);
break; break;
case UiFramework.MauiBlazor:
ConfigureWithMauiBlazorUi(context, steps);
break;
case UiFramework.Mvc: case UiFramework.Mvc:
case UiFramework.NotSpecified: case UiFramework.NotSpecified:
ConfigureWithMvcUi(context, steps); ConfigureWithMvcUi(context, steps);
@ -510,6 +514,37 @@ public abstract class AppTemplateBase : TemplateInfo
} }
} }
protected void ConfigureWithMauiBlazorUi(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)
{
context.Symbols.Add("ui:maui-blazor");
steps.Add(new MauiBlazorChangeApplicationIdGuidStep());
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web.Host"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web.Tests", projectFolderPath: "/aspnet-core/test/MyCompanyName.MyProjectName.Web.Tests"));
if (context.BuildArgs.ExtraProperties.ContainsKey("separate-identity-server") ||
context.BuildArgs.ExtraProperties.ContainsKey("separate-auth-server"))
{
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.HttpApi.HostWithIds"));
steps.Add(new MauiBlazorPortChangeForSeparatedAuthServersStep());
steps.Add(new AppTemplateChangeDbMigratorPortSettingsStep("44300"));
if (context.BuildArgs.MobileApp == MobileApp.ReactNative)
{
steps.Add(new ReactEnvironmentFilePortChangeForSeparatedAuthServersStep());
}
}
else
{
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.HttpApi.Host"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.IdentityServer"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.AuthServer"));
steps.Add(new TemplateProjectRenameStep("MyCompanyName.MyProjectName.HttpApi.HostWithIds", "MyCompanyName.MyProjectName.HttpApi.Host"));
steps.Add(new AppTemplateChangeConsoleTestClientPortSettingsStep("44305"));
}
}
protected void RemoveUnnecessaryPorts(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps) protected void RemoveUnnecessaryPorts(ProjectBuildContext context, List<ProjectBuildPipelineStep> steps)
{ {
steps.Add(new RemoveUnnecessaryPortsStep()); steps.Add(new RemoveUnnecessaryPortsStep());
@ -599,7 +634,8 @@ public abstract class AppTemplateBase : TemplateInfo
{ {
if ((context.BuildArgs.UiFramework == UiFramework.Mvc if ((context.BuildArgs.UiFramework == UiFramework.Mvc
|| context.BuildArgs.UiFramework == UiFramework.Blazor || context.BuildArgs.UiFramework == UiFramework.Blazor
|| context.BuildArgs.UiFramework == UiFramework.BlazorServer) && || context.BuildArgs.UiFramework == UiFramework.BlazorServer
|| context.BuildArgs.UiFramework == UiFramework.MauiBlazor) &&
context.BuildArgs.MobileApp == MobileApp.None) context.BuildArgs.MobileApp == MobileApp.None)
{ {
steps.Add(new MoveFolderStep("/aspnet-core/", "/")); steps.Add(new MoveFolderStep("/aspnet-core/", "/"));

34
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/MauiBlazorChangeApplicationIdGuidStep.cs

@ -0,0 +1,34 @@
using System;
using System.Linq;
using System.Xml;
using Volo.Abp.Cli.ProjectBuilding.Building;
using Volo.Abp.Cli.Utils;
namespace Volo.Abp.Cli.ProjectBuilding.Templates.App;
public class MauiBlazorChangeApplicationIdGuidStep: ProjectBuildPipelineStep
{
public override void Execute(ProjectBuildContext context)
{
var projectFile = context.Files.FirstOrDefault(f => f.Name.EndsWith("MyCompanyName.MyProjectName.MauiBlazor.csproj"));
if (projectFile == null)
{
return;
}
using (var stream = StreamHelper.GenerateStreamFromString(projectFile.Content))
{
var doc = new XmlDocument { PreserveWhitespace = true };
doc.Load(stream);
var node = doc.SelectSingleNode("/Project/PropertyGroup/ApplicationIdGuid");
if (node != null)
{
node.InnerText = Guid.NewGuid().ToString();
}
projectFile.SetContent(doc.OuterXml);
}
}
}

50
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/MauiBlazorPortChangeForSeparatedAuthServersStep.cs

@ -0,0 +1,50 @@
using System;
using System.Linq;
using Volo.Abp.Cli.ProjectBuilding.Building;
namespace Volo.Abp.Cli.ProjectBuilding.Templates.App;
public class MauiBlazorPortChangeForSeparatedAuthServersStep: ProjectBuildPipelineStep
{
public override void Execute(ProjectBuildContext context)
{
var appsettingsFile = context.Files.FirstOrDefault(x =>
!x.IsDirectory &&
x.Name.EndsWith("aspnet-core/src/MyCompanyName.MyProjectName.MauiBlazor/appsettings.json",
StringComparison.InvariantCultureIgnoreCase)
);
if(appsettingsFile == null)
{
return;
}
appsettingsFile.NormalizeLineEndings();
var lines = appsettingsFile.GetLines();
for (var i = 1; i < lines.Length; i++)
{
var line = lines[i];
var previousLine = lines[i-1];
if (line.Contains("Authority") && line.Contains("localhost"))
{
line = line.Replace("44305", "44301");
}
else if (previousLine.Contains("AbpAccountPublic") && line.Contains("BaseUrl") && line.Contains("localhost"))
{
line = line.Replace("44305", "44301");
}
else if (previousLine.Contains("Default") && line.Contains("BaseUrl") && line.Contains("localhost"))
{
line = line.Replace("44305", "44300");
}
lines[i] = line;
}
appsettingsFile.SetLines(lines);
}
}

1
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Maui/MauiChangePortStep.cs

@ -53,6 +53,7 @@ public class MauiChangePortStep : ProjectBuildPipelineStep
{ {
case UiFramework.Angular: case UiFramework.Angular:
case UiFramework.Blazor: case UiFramework.Blazor:
case UiFramework.MauiBlazor:
authServerPort = "44305"; authServerPort = "44305";
apiHostPort = "44305"; apiHostPort = "44305";
break; break;

Loading…
Cancel
Save