14 KiB
Migration Progress: FrontOffice.BFF → CMS Direct Integration
Date: 2026-02-01
Overview
Migration of FrontOffice from BFF layer to direct CMS microservice integration to eliminate unnecessary abstraction layer and improve architecture.
Migration Strategy
Discovery Phase
- Key Finding: BFF was acting as a DTO transformation layer
- Insight: BFF proto files serve as specification for frontend requirements
- Approach: Systematically compare BFF proto structures with CMS and add missing fields
Field Aliasing Strategy
Proto3 doesn't support field number reuse, so we use unique field numbers for alias fields:
- Original fields keep their numbers (e.g.,
name = 2,image_url = 8) - Alias fields get new numbers (e.g.,
title = 12,image_path = 13) - Both fields must be populated in service implementations
Completed Work
✅ Phase 1: Infrastructure Setup
- Changed URL from
localhost:32845(BFF) tolocalhost:32846(CMS) - Consolidated multiple BFF proto packages into single
Foursat.CMSMicroservice.Protobuf - Implemented Customer-prefixed API methods for frontend access
✅ Phase 2: Proto Package Updates
Version 0.0.171 (Successful)
- Added
modelsfield aliases in response types:GetAllCategoriesForCustomerResponse:categories→models(field 2)GetCustomerPackagesResponse:packages→models(field 1)GetAllUserCartsResponse:items→models(field 1)
- Added missing fields:
GetUserForCustomerResponse.token(field 16)GetClubMembershipResponse.status(field 11)GetClubMembershipResponse.days_remaining(field 12)
- Removed duplicate validators in
CMSMicroservice.Protobuf/Validator/UserCarts/
Version 0.0.172 (Current)
Proto Changes:
- package.proto: Added
title(field 12) andimage_path(field 13) toCustomerPackageModel - usercarts.proto:
- Added
user_cart_id(field 11) alias toUpdateUserCartRequest - Added
product_short_infomation(field 14) typo alias toUserCartItem - Added
createdtimestamp (field 10) toUserCartItem
- Added
- networkmembership.proto: Added to
NetworkTreeNodeModel:full_name(field 20) - alias for user_namelevel(field 21) - alias for network_levelmobile(field 14)avatar(field 15)position(field 16)left_child(field 17)right_child(field 18)
Service Implementation Changes:
- Updated
PackageService.GetCustomerPackageDetailsto populate:Title = "پکیج طلایی"(duplicate of Name)ImagePath = "/images/packages/golden-detail.jpg"(duplicate of ImageUrl)
Build Status:
✅ Proto build: Success
✅ Pack version 0.0.172: Success
✅ Package location: /home/masoud/Apps/project/FourSat/nupkg/Foursat.CMSMicroservice.Protobuf.0.0.172.nupkg
✅ FrontOffice.Main.csproj updated to version 0.0.172
✅ Phase 3: Error Reduction
- Initial: 250+ compilation errors
- After 0.0.171: 217 errors
- After 0.0.172: 170 errors ⬇️ (32% reduction)
Remaining Work
⚠️ Critical Issues (170 Errors)
1. Missing Service Methods (8 methods)
Need to be added to CMS proto services:
ConfigurationContract:
GetClubConfigurationAsyncGetClubFeaturesAsync
CommissionContract:
GetMyCommissionPayoutsAsyncGetMyWeeklyBalancesAsync
NetworkMembershipContract:
GetMyNetworkTreeAsyncGetSubordinateTreeAsyncGetMyNetworkStatisticsAsync
UserOrderContract:
GetVATRateAsync
2. Missing Proto Fields
GetWeekDefinitionsRequest (5 fields):
int32 page_number = ?;
int32 page_size = ?;
string search_text = ?;
google.protobuf.Int32Value persian_year = ?;
google.protobuf.Int32Value gregorian_year = ?;
google.protobuf.BoolValue is_active = ?;
WeekDefinitionItem (2 fields):
string start_date_persian = ?;
string end_date_persian = ?;
3. Type Conversion Issues
PaginationState conflict:
Cannot implicitly convert type 'CMSMicroservice.Protobuf.Protos.PaginationState'
to 'CMSMicroservice.Protobuf.Protos.City.PaginationState'
Location: Pages/Profile/Components/EditAddressDialog.razor.cs(45,35)
4. Incomplete Alias Population
Fields with aliases need population in ALL service methods:
CustomerPackageModel.Title/ImagePath(partially done)NetworkTreeNodeModel.FullName/Level- Other alias fields across services
Technical Decisions
Proto Field Number Strategy
Problem: Proto3 doesn't allow field number reuse for aliases
// ❌ This doesn't work:
string name = 2;
string title = 2; // ERROR: Field number 2 already used
// ✅ Solution:
string name = 2;
string title = 12; // New unique number
Why Not Update Frontend?
Preserving Business Logic: User requirement is "چیزی کم نشه از بیزینس" (don't lose any business logic). Changing frontend field names risks:
- Breaking existing functionality
- Missing edge cases in BFF transformation logic
- Extensive testing burden
Field Aliasing Benefits:
- Zero frontend changes required
- Gradual migration path
- Easy rollback if needed
- Maintains backward compatibility
Next Steps
Priority 1: Add Missing Methods
- Define proto service methods in CMS
.protofiles - Implement method stubs in CMS service classes
- Return mock/default data initially
Priority 2: Add Missing Fields
- Add fields to
GetWeekDefinitionsRequest - Add fields to
WeekDefinitionItem - Rebuild proto package as version 0.0.173
Priority 3: Fix Type Issues
- Resolve
PaginationStatenamespace conflict - Add missing
PaymentGatewayUrlfield - Fix
PaymentMethodenum reference
Priority 4: Complete Alias Population
- Populate all alias fields in service responses
- Ensure data consistency between original and alias fields
Package Version History
| Version | Status | Changes | Errors |
|---|---|---|---|
| 0.0.170 | Baseline | Initial BFF → CMS migration | 250+ |
| 0.0.171 | ✅ Success | Models aliases, Token field | 217 |
| 0.0.172 | ✅ Success | Title/ImagePath aliases, Network fields | 170 |
| 0.0.173 | Planned | Missing methods and fields | TBD |
Commands Reference
Build Proto Package
cd /home/masoud/Apps/project/FourSat/CMS/src/CMSMicroservice.Protobuf
dotnet build
dotnet pack -c Release -p:PackageVersion=0.0.172 -o ../../../nupkg -p:RunPushTarget=false
Update FrontOffice
cd /home/masoud/Apps/project/FourSat/FrontOffice/src/FrontOffice.Main
# Edit .csproj to update version number
dotnet build
Check Errors
cd /home/masoud/Apps/project/FourSat/FrontOffice/src/FrontOffice.Main
dotnet build 2>&1 | grep "error CS" | wc -l
dotnet build 2>&1 | grep "error CS" | head -20
Lessons Learned
-
BFF Transformation Discovery: BFF wasn't just routing - it was transforming DTOs. This is critical business logic.
-
Proto Field Aliasing: Proto3 requires unique field numbers. Can't reuse numbers for aliases.
-
Systematic Approach: Comparing BFF proto files as specification prevented missing fields.
-
Incremental Progress: Breaking work into small packages (0.0.171 → 0.0.172) made debugging easier.
-
Package Naming: Real package name is
Foursat.CMSMicroservice.Protobuf, notCMSMicroservice.Protobuf.
Notes
- Post-build push to Nexus disabled with
-p:RunPushTarget=falsedue to--allow-insecure-connectionsflag incompatibility - All changes preserve existing business logic per user requirement
- Field aliases provide backward compatibility during migration
- Final cleanup phase will update frontend to use CMS field names directly (optional future work)
سابقه مهاجرت اولیه (سرویسهای اولیه)
FrontOffice.BFF to CMS Migration Progress
Migration Overview
مهاجرت سرویسهای FrontOffice.BFF به CMS Microservice با معماری Clean Architecture و gRPC.
✅ Completed Services
1. Categories Service
- Status: ✅ Complete
- Proto Definition:
categories.proto - Service Implementation:
CategoryService.cs - Methods Migrated:
- Admin Methods:
AddNewCategory- افزودن دستهبندی جدیدUpdateCategory- بروزرسانی دستهبندیDeleteCategory- حذف دستهبندیGetCategory- دریافت یک دستهبندیGetAllCategoriesByFilter- دریافت لیست دستهبندیها
- Customer Methods:
GetActiveCategoriesForCustomer- دریافت دستهبندیهای فعال برای مشتری
- Admin Methods:
2. City Service
- Status: ✅ Complete
- Proto Definition:
city.proto - Service Implementation:
CityService.cs - Methods Migrated:
- Admin Methods:
AddNewCity- افزودن شهر جدیدUpdateCity- بروزرسانی شهرDeleteCity- حذف شهرGetCity- دریافت یک شهرGetAllCitiesByFilter- دریافت لیست شهرها
- Customer Methods:
GetActiveCitiesForCustomer- دریافت شهرهای فعال برای مشتری
- Admin Methods:
3. UserCarts Service
- Status: ✅ Complete
- Proto Definition:
usercarts.proto - Service Implementation:
UserCartsService.cs - Methods Migrated:
- Admin Methods:
AddNewUserCart- افزودن سبد خرید جدیدUpdateUserCart- بروزرسانی سبد خریدDeleteUserCart- حذف سبد خریدGetUserCart- دریافت سبد خرید (Admin)GetAllUserCartsByFilter- دریافت لیست سبدهای خرید
- Customer Methods:
AddNewUserCartForCustomer- افزودن محصول به سبد (Customer)UpdateUserCartForCustomer- بروزرسانی تعداد محصول در سبدRemoveUserCartForCustomer- حذف محصول از سبدGetCustomerCart- دریافت سبد خرید مشتری
- Admin Methods:
🛠️ Technical Implementation Details
gRPC HTTP Annotations
تمام سرویسها با HTTP annotations تعریف شدهاند:
- Admin endpoints:
/ServiceNamepattern - Customer endpoints:
/Customer/Actionpattern
Clean Architecture Structure
CMSMicroservice.Domain/ # Core business entities
CMSMicroservice.Application/ # Business logic & CQRS
CMSMicroservice.Infrastructure/ # Data access & external services
CMSMicroservice.WebApi/ # gRPC services & controllers
CMSMicroservice.Protobuf/ # Protocol buffer definitions
Swagger Integration
- Multiple Swagger documents: cms, admin, customer, unified
- gRPC HTTP transcoding enabled
- Custom CSS styling applied
- Conflict resolution implemented
🔧 Issues Resolved
1. Swagger Conflict Resolution
Problem:
Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException:
Conflicting method/path combination "GET GetUserCart"
Root Cause:
- دو method با operation ID یکسان:
GetUserCartوGetUserCartForCustomer - Swagger از method name برای operation ID استفاده میکند
Solutions Attempted:
- ❌
CustomOperationIds- ineffective - ❌
ResolveConflictingActions- incomplete resolution - ✅ Method Renaming - successful
Final Solution:
// Before (conflicting):
rpc GetUserCartForCustomer(GetUserCartForCustomerRequest) returns (GetUserCartForCustomerResponse)
// After (resolved):
rpc GetCustomerCart(GetUserCartForCustomerRequest) returns (GetUserCartForCustomerResponse)
2. Application Layer Dependencies
Problem: Build errors در Application layer Solution: پاکسازی dependencies و rebuild پروژه
📊 Migration Status Summary
| Service | Proto ✅ | Implementation ✅ | Build ✅ | Swagger ✅ |
|---|---|---|---|---|
| Categories | ✅ | ✅ | ✅ | ✅ |
| City | ✅ | ✅ | ✅ | ✅ |
| UserCarts | ✅ | ✅ | ✅ | ✅ |
🎯 Next Steps
- Service Integration Testing - تست عملکرد سرویسهای migrate شده
- Business Logic Implementation - پیادهسازی منطق کسبوکار واقعی
- Database Integration - اتصال به لایه دیتا
- Continue Migration - ادامه migration سایر سرویسها
🏗️ Technical Architecture
gRPC Service Pattern
public class ServiceName : ServiceContract.ServiceContractBase
{
private readonly IDispatchRequestToCQRS _dispatcher;
// Customer Methods Section
#region Customer Methods
public override async Task<Response> CustomerMethod(Request request, ServerCallContext context)
{
// Implementation
}
#endregion
// Admin Methods Section
#region Admin Methods
public override async Task<Response> AdminMethod(Request request, ServerCallContext context)
{
// Implementation
}
#endregion
}
Proto File Structure
syntax = "proto3";
import "google/api/annotations.proto";
service ServiceContract {
// ============= Admin Methods =============
rpc AdminMethod(Request) returns (Response) {
option (google.api.http) = {
post: "/AdminEndpoint"
body: "*"
};
};
// ============= Customer Methods =============
rpc CustomerMethod(Request) returns (Response) {
option (google.api.http) = {
get: "/Customer/Endpoint"
};
};
}
📈 Performance & Quality
- ✅ All services compile successfully
- ✅ Swagger documentation accessible
- ✅ gRPC HTTP transcoding working
- ✅ Clean separation of Admin/Customer concerns
- ✅ Consistent naming conventions applied
Last Updated: January 30, 2026
Migration Phase: Foundation Services Complete
Next Milestone: Business Logic Implementation