migrate-aspnetboilerplate-to-abp
Migrate existing ASP.NET Boilerplate projects to ABP.IO framework with step-by-step guidance, code transformation, and best practices.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Migrate existing ASP.NET Boilerplate projects to ABP.IO framework with step-by-step guidance, code transformation, and best practices.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
Complete ASP.NET Core REST API development with best practices, security, testing, and deployment patterns
Complete Blazor component development with modern patterns, state management, and best practices
Create a new ABP.IO project using CLI commands with proper template selection, configuration, and setup. Supports all ABP templates including layered, single-layer, microservice, and modular architectures.
Create a new ABP.IO project with proper template selection, configuration, and setup. Supports all ABP templates including layered, single-layer, microservice, and modular architectures.
Create a new ASP.NET Boilerplate project with proper template selection, configuration, and setup. Supports all ASP.NET Boilerplate templates including MVC, Angular, and module-zero templates.
Master asynchronous programming in C# with proper async/await patterns, error handling, and performance optimization
| name | migrate-aspnetboilerplate-to-abp |
| description | Migrate existing ASP.NET Boilerplate projects to ABP.IO framework with step-by-step guidance, code transformation, and best practices. |
Migrate existing ASP.NET Boilerplate projects to the modern ABP.IO framework with comprehensive guidance and automated transformation steps.
Your goal is to guide the migration of an existing ASP.NET Boilerplate project to ABP.IO framework, ensuring minimal disruption and maximum compatibility.
Before starting migration, verify:
Good Candidates for Migration:
Challenging Migrations:
# Install ABP CLI
dotnet tool install -g Volo.Abp.Cli
# Verify installation
abp --version
# Create complete backup
cp -r MyProject MyProject_backup_$(date +%Y%m%d)
# Git tag current state
git tag aspnetboilerplate_final
git push origin aspnetboilerplate_final
Create dependency inventory:
# List current packages
dotnet list package
# Analyze third-party dependencies
# Document custom modifications
# Note breaking changes needed
Based on project analysis, select appropriate ABP template:
# For standard web applications
abp new MyCompany.MyProject -t app -u mvc -d ef
# For applications with Angular
abp new MyCompany.MyProject -t app -u angular -d ef --tiered
# For simple applications
abp new MyCompany.MyProject -t app-nolayers -u mvc -d ef
# Navigate to new project
cd MyCompany.MyProject
# Restore packages
dotnet restore
# Create initial database
dotnet ef database update
# Run application to verify
dotnet run --project src/MyCompany.MyProject.Web
Entity Migration Pattern:
// ASP.NET Boilerplate Entity
public class Product : FullAuditedEntity
{
public string Name { get; set; }
public decimal Price { get; set; }
public ProductCategory Category { get; set; }
}
// ABP Entity
public class Product : FullAuditedAggregateRoot<Guid>
{
public string Name { get; set; }
public decimal Price { get; set; }
public ProductCategory Category { get; set; }
protected Product() { }
public Product(
Guid id,
string name,
decimal price,
ProductCategory category) : base(id)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name));
Price = price;
Category = category;
}
}
Value Object Migration:
// ASP.NET Boilerplate
public class Address
{
public string Street { get; set; }
public string City { get; set; }
public string Country { get; set; }
}
// ABP Value Object
public class Address : ValueObject
{
public string Street { get; set; }
public string City { get; set; }
public string Country { get; set; }
protected override IEnumerable<object> GetEqualityComponents()
{
yield return Street;
yield return City;
yield return Country;
}
}
Repository Migration:
// ASP.NET Boilerplate Repository Interface
public interface IProductRepository : IRepository<Product>
{
List<Product> GetProductsByCategory(int categoryId);
}
// ABP Repository Interface
public interface IProductRepository : IRepository<Product, Guid>
{
Task<List<Product>> GetProductsByCategoryAsync(Guid categoryId);
}
Application Service Migration:
// ASP.NET Boilerplate Application Service
public class ProductAppService : ApplicationService, IProductAppService
{
private readonly IRepository<Product> _productRepository;
public ProductAppService(IRepository<Product> productRepository)
{
_productRepository = productRepository;
}
public ListResultDto<ProductDto> GetAll(GetAllProductsInput input)
{
var products = _productRepository.GetAllList();
return new ListResultDto<ProductDto>(
ObjectMapper.Map<List<Product>, List<ProductDto>>(products)
);
}
}
// ABP Application Service
public class ProductAppService : ApplicationService, IProductAppService
{
private readonly IRepository<Product, Guid> _productRepository;
public ProductAppService(IRepository<Product, Guid> productRepository)
{
_productRepository = productRepository;
}
public async Task<PagedResultDto<ProductDto>> GetListAsync(GetProductsInput input)
{
var queryable = await _productRepository.GetQueryableAsync();
var products = await AsyncExecuter.ToListAsync(
queryable
.WhereIf(!input.Filter.IsNullOrWhiteSpace(),
p => p.Name.Contains(input.Filter))
.OrderBy(p => p.Name)
.PageBy(input.SkipCount, input.MaxResultCount)
);
var totalCount = await AsyncExecuter.CountAsync(
queryable.WhereIf(!input.Filter.IsNullOrWhiteSpace(),
p => p.Name.Contains(input.Filter))
);
return new PagedResultDto<ProductDto>(
totalCount,
ObjectMapper.Map<List<Product>, List<ProductDto>>(products)
);
}
}
DTO Migration:
// ASP.NET Boilerplate DTO
public class ProductDto : EntityDto
{
public string Name { get; set; }
public decimal Price { get; set; }
}
// ABP DTO
public class ProductDto : EntityDto<Guid>
{
public string Name { get; set; }
public decimal Price { get; set; }
}
public class CreateUpdateProductDto
{
[Required]
[StringLength(ProductConsts.MaxNameLength)]
public string Name { get; set; }
[Range(0.01, 10000.00)]
public decimal Price { get; set; }
}
Entity Framework Configuration:
// ASP.NET Boilerplate Configuration
public class ProductConfiguration : IEntityTypeConfiguration<Product>
{
public void Configure(EntityTypeBuilder<Product> builder)
{
builder.ToTable("Products");
builder.Property(p => p.Name)
.IsRequired()
.HasMaxLength(128);
builder.Property(p => p.Price)
.HasColumnType("decimal(18,2)");
}
}
// ABP Configuration (similar but with updated namespaces)
public class ProductConfiguration : IEntityTypeConfiguration<Product>
{
public void Configure(EntityTypeBuilder<Product> builder)
{
builder.ToTable(MyProjectConsts.DbTablePrefix + "Products", MyProjectConsts.DbSchema);
builder.Property(x => x.Name)
.IsRequired()
.HasMaxLength(ProductConsts.MaxNameLength);
builder.Property(x => x.Price)
.HasColumnType("decimal(18,2)");
}
}
Controller Migration:
// ASP.NET Boilerplate Controller
public class ProductsController : AbpController
{
private readonly IProductAppService _productAppService;
public ProductsController(IProductAppService productAppService)
{
_productAppService = productAppService;
}
public ActionResult Index()
{
var products = _productAppService.GetAll(new GetAllProductsInput());
return View(products);
}
}
// ABP Controller
public class ProductsController : AbpControllerBase
{
private readonly IProductAppService _productAppService;
public ProductsController(IProductAppService productAppService)
{
_productAppService = productAppService;
}
public async Task<IActionResult> Index()
{
var products = await _productAppService.GetListAsync(new GetProductsInput());
return View(products);
}
}
// ASP.NET Boilerplate namespaces
using Abp.Application.Services;
using Abp.Domain.Repositories;
using Abp.Authorization;
using Abp.UI;
using Abp.Domain.Entities;
using Abp.EntityFrameworkCore;
using Abp.AspNetCore.Mvc.Controllers;
// ABP namespaces
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Authorization;
using Volo.Abp;
using Volo.Abp.Domain.Entities;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.AspNetCore.Mvc;
<!-- ASP.NET Boilerplate packages -->
<PackageReference Include="Abp.AspNetCore" Version="6.4.0" />
<PackageReference Include="Abp.EntityFrameworkCore" Version="6.4.0" />
<PackageReference Include="Abp.AspNetCore.Mvc" Version="6.4.0" />
<!-- ABP packages -->
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="8.0.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="8.0.0" />
<PackageReference Include="Volo.Abp.AspNetCore" Version="8.0.0" />
// ASP.NET Boilerplate Module
[DependsOn(typeof(AbpAspNetCoreModule))]
public class MyProjectWebModule : AbpModule
{
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(typeof(MyProjectWebModule));
}
}
// ABP Module
[DependsOn(
typeof(MyProjectApplicationModule),
typeof(MyProjectEntityFrameworkCoreModule),
typeof(AbpAspNetCoreMvcModule)
)]
public class MyProjectWebModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(MyProjectApplicationModule).Assembly);
});
}
}
// ASP.NET Boilerplate appsettings.json
{
"ConnectionStrings": {
"Default": "Server=localhost;Database=MyProjectDb;Trusted_Connection=true"
}
}
// ABP appsettings.json
{
"ConnectionStrings": {
"Default": "Server=localhost;Database=MyProjectDb;Trusted_Connection=true"
},
"App": {
"SelfUrl": "https://localhost:44300",
"CorsOrigins": "https://localhost:44300"
},
"AuthServer": {
"Authority": "https://localhost:44300",
"RequireHttpsMetadata": "false"
}
}
// ASP.NET Boilerplate Test
public class ProductAppService_Tests : AppTestBase
{
private readonly IProductAppService _productAppService;
public ProductAppService_Tests()
{
_productAppService = Resolve<IProductAppService>();
}
[Fact]
public void Should_Get_All_Products()
{
var products = _productAppService.GetAll(new GetAllProductsInput());
products.Items.Count.ShouldBeGreaterThan(0);
}
}
// ABP Test
public class ProductAppService_Tests : MyProjectApplicationTestBase
{
private readonly IProductAppService _productAppService;
public ProductAppService_Tests()
{
_productAppService = GetRequiredService<IProductAppService>();
}
[Fact]
public async Task Should_Get_All_Products()
{
var products = await _productAppService.GetListAsync(new GetProductsInput());
products.TotalCount.ShouldBeGreaterThan(0);
}
}
# Run all tests
dotnet test
# Check database migrations
dotnet ef migrations list
# Verify application startup
dotnet run --project src/MyCompany.MyProject.Web
#!/bin/bash
# migrate-to-abp.sh
PROJECT_NAME=$1
TEMPLATE_TYPE=${2:-"app"}
UI_FRAMEWORK=${3:-"mvc"}
DB_PROVIDER=${4:-"ef"}
echo "Migrating $PROJECT_NAME to ABP.IO..."
# Create new ABP project
abp new $PROJECT_NAME -t $TEMPLATE_TYPE -u $UI_FRAMEWORK -d $DB_PROVIDER
# Copy domain entities
echo "Copying domain entities..."
cp -r ../$PROJECT_NAME_backup/src/$PROJECT_NAME.Domain/Entities src/$PROJECT_NAME.Domain/
# Copy application services (with manual conversion needed)
echo "Preparing application services..."
mkdir -p src/$PROJECT_NAME.Application/Services
# Update package references
echo "Updating package references..."
find . -name "*.csproj" -exec sed -i 's/Abp\./Volo.Abp./g' {} \;
# Run initial setup
echo "Running initial setup..."
cd $PROJECT_NAME
dotnet restore
dotnet ef database update
echo "Migration setup complete! Manual conversion required for:"
echo "1. Application services"
echo "2. Controllers"
echo "3. Views/UI components"
echo "4. Configuration files"
echo "5. Custom business logic"
Problem: Ambiguous references between old and new ABP namespaces Solution: Use fully qualified names or alias directives
using OldAbp = Abp;
using NewAbp = Volo.Abp;
Problem: ABP uses Guid keys by default
Solution: Update entities to use Guid keys or configure custom keys
public class Product : FullAuditedAggregateRoot<int> // Use int instead of Guid
{
// Entity definition
}
Problem: ABP requires async patterns for repository operations Solution: Update all repository calls to async
// Before
var products = _repository.GetAllList();
// After
var products = await _repository.GetListAsync();
Problem: Authorization attributes have different names Solution: Update attribute references
// Before
[AbpAuthorize("Products.Create")]
// After
[Authorize("Products.Create")]
This migration guide provides comprehensive steps to successfully transition from ASP.NET Boilerplate to ABP.IO while maintaining functionality and improving code quality.