Files
KJD_WebService/KJD_WebService_Net10迁移文档.md
2026-08-25 09:18:36 +08:00

21 KiB
Raw Permalink Blame History

KJD WebService 迁移文档(.NET Framework 4.6.2 → .NET 10)

生成日期:2026-08-14 适用范围:旧项目 D:\Works\KJD Cef138\KJDService → 新项目 D:\Works\StoreHub\StoreHub.KJDWebService


1. 迁移背景与目标

项目 说明
旧项目 D:\Works\KJD Cef138\KJDService,ASP.NET WebService(*.asmx),.NET Framework 4.6.2,MySQL(MySql.Data)
新项目 D:\Works\StoreHub\StoreHub.KJDWebService,.NET 10 + ASP.NET Core,宿主为 D:\Works\StoreHub\StoreHub(Web 项目,已引用 KJDWebService)
迁移目标 功能等价迁移到 .NET 10;不优化代码;模型照抄;Manage 方法内逻辑不修改;执行语句改为参数方式;对外路由保持一致

新项目仓库结构(解决方案 D:\Works\StoreHub\StoreHub.slnx):

D:\Works\StoreHub\
├─ StoreHub\                  # Web 宿主(Program.cs,引用 KJDWebService)
├─ StoreHub.Framework\        # 公共框架(IOC、FreeSql、ApiResult、SqlRepository)
├─ StoreHub.KJDWebService\    # 本次迁移目标项目(业务代码)
├─ StoreHub.Services\         # 其他服务
└─ Core\

2. 新项目目录结构规范(必须严格遵循)

StoreHub.KJDWebService/
├─ Commons/          # 公共工具(旧 Utils 照搬)
├─ Controllers/      # API(旧 *.asmx 的每个 WebMethod → Action)
├─ Dtos/             # DTO 目录
├─ Models/           # 模型目录(旧 Model 照抄)
├─ Services/         # 服务目录(旧 BLL/*Manage → *Service)
├─ Repositorys/      # SqlRepository(框架提供)
└─ Startup.cs        # IStartup 入口

3. 核心编码规范

3.1 Service 规范(强制)

  • 所有 Service 都要注入 SqlRepository sqlRepository;
  • 用 _sqlRepository.Ado.ExecuteDataTable(...) 执行 SQL 语句;
  • Service 需实现 ITransientDependency / IScopedDependency 标记接口,由框架自动注册,方便 Controller 构造注入调用。

参考 Services/DemoService.cs(已存在的示例):

using MAX.Core.DependencyInjection;
using StoreHub.Framework.Repositorys;

namespace StoreHub.KJDWebService.Services
{
    public class DemoService : ITransientDependency
    {
        private readonly SqlRepository _sqlRepository;

        public DemoService(SqlRepository sqlRepository)
        {
            _sqlRepository = sqlRepository;
        }

        public bool Test()
        {
            _sqlRepository.Ado.ExecuteDataTable("select * from user");
            return true;
        }

        public bool Test2()
        {
            return true;
        }
    }
}

SqlRepository(StoreHub.Framework/Repositorys/SqlRepository.cs):

public class SqlRepository : IScopedDependency
{
    public IAdo Ado { get; }
    public SqlRepository([FromKeyedServices("KJDDB")] IFreeSql fsql)
    {
        Ado = fsql.Ado;
    }
}

3.2 服务注册机制

框架(StoreHub.Framework/DependencyInjection/ServiceCollectionExtensions.cs)自动扫描并注册所有实现以下标记接口的类型:

标记接口 生命周期
ISingletonDependency Singleton
IScopedDependency Scoped
ITransientDependency Transient

因此:Manage 对应的 Service 只需实现上述任一标记接口即可被自动注册,无需手写 DI 代码。Controller 构造函数直接注入 Service 即可。

3.3 Controller 规范

参考现有 Controllers/Login.cs:

[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]/[action]")]
public class Login : ControllerBase
{
    private readonly DemoService _userService;

    public Login(DemoService userService)
    {
        _userService = userService;
    }

    [HttpGet]
    public ApiResult<bool> Loinout()
    {
        _userService.Login();
        return ApiResult.Success(true);
    }
}

⚠️ 迁移注意:旧接口路由是 /{前缀}/{方法名}(如 /user/user_login),为保持路由一致,每个业务 Controller 应使用旧前缀路由(见第 5.3 节),而不是统一 api/v1/[controller]/[action]。是否保留 api/v{version} 前缀需与调用方确认。


4. 旧项目 → 新项目映射规则

旧项目 新项目 说明
*.asmx / *.asmx.cs(20 个) Controllers/*Controller.cs asmx 的每个 [WebMethod] → Controller 的一个 Action
BLL/*/*Manage.cs(23 个) Services/*Service.cs Manage 类 → Service 类,注入 SqlRepository
Global.asax.cs 中的 URL 重写规则 Controller 的 Route 特性 路由保持与旧地址一致
Model/*.cs(47 个) Models/ 照抄,不做任何改动
Utils/*.cs(含 Extension、Helper) Commons/ 照搬(公共工具)
Web.config 连接串/业务配置 appsettings.json ConnKJD → KJDConnection(keyed KJDDB)等
MysqlUtils(MySql.Data) _sqlRepository.Ado(FreeSql IAdo) SQL 执行方式改为参数化(见第 7 节)
NaiBa.Util.*(Extension/Helper 命名空间) 迁移后统一到新命名空间 注意 using 同步调整

5. 详细迁移清单

5.1 asmx 服务 → Controller 映射(共 20 个服务 / 356 个 WebMethod)

# asmx 服务(旧) WebMethod 数 依赖的 Manage 建议 Controller(新)
1 UserService.asmx 18 UserManage、UpdateManage(代码中为 UpadteManage,见风险 9.2) UserController
2 ShopService.asmx 18 ShopManage ShopController
3 OrderService.asmx 8 OrderManage OrderController
4 ProductService.asmx 24 ProductManage ProductController
5 ProductThirdService.asmx 18 ProductThirdManage ProductThirdController
6 PriceService.asmx 8 PriceManage PriceController
7 UpdateService.asmx 4 UpdateManage UpdateController
8 ToolService.asmx 2 ToolManage ToolController
9 BXXUserService.asmx 18 BXXUserManage BXXUserController
10 BXXShopService.asmx 24 BXXShopManage、WXShopManage BXXShopController
11 BXXProductService.asmx 44 BXXProductManage、WXShopManage BXXProductController
12 BXXProductThirdService.asmx 14 BXXProductThirdManage BXXProductThirdController
13 BXXPriceService.asmx 12 BXXPriceManage BXXPriceController
14 DYUserService.asmx 11 DYUserManage DYUserController
15 DYShopService.asmx 13 DYShopManage DYShopController
16 WXUserService.asmx 22 WXUserManage、WXOemManage WXUserController
17 WXShopService.asmx 38 WXShopManage、WXExpressOptimizeManage WXShopController
18 WXProductService.asmx 34 WXProductManage、BXXProductManage WXProductController
19 WXOrderService.asmx 25 WXOrderManage WXOrderController
20 WXShopRevenueStatistics.asmx 1 WXShopRevenueStatisticsManage WXShopRevenueStatisticsController

Global.asax.cs 中还引用了 DYProductService、DYProductThirdService、DYPriceService、WXProductThirdService、WXPriceService 的重写目标,但旧项目中不存在这些 asmx 文件(见 9.1)。

5.2 Manage → Service 映射(23 个)

BLL 目录 Manage(旧) Service(新)
BLL/KJD UserManage.cs UserService.cs
BLL/KJD ShopManage.cs ShopService.cs
BLL/KJD OrderManage.cs OrderService.cs
BLL/KJD ProductManage.cs ProductService.cs
BLL/KJD ProductThirdManage.cs ProductThirdService.cs
BLL/KJD PriceManage.cs PriceService.cs
BLL/KJD UpdateManage.cs UpdateService.cs
BLL/KJD ToolManage.cs ToolService.cs
BLL/BXX BXXUserManage.cs BXXUserService.cs
BLL/BXX BXXShopManage.cs BXXShopService.cs
BLL/BXX BXXProductManage.cs BXXProductService.cs
BLL/BXX BXXProductThirdManage.cs BXXProductThirdService.cs
BLL/BXX BXXPriceManage.cs BXXPriceService.cs
BLL/DYXD DYUserManage.cs DYUserService.cs
BLL/DYXD DYShopManage.cs DYShopService.cs
BLL/WXXD WXUserManage.cs WXUserService.cs
BLL/WXXD WXShopManage.cs WXShopService.cs
BLL/WXXD WXProductManage.cs WXProductService.cs
BLL/WXXD WXOrderManage.cs WXOrderService.cs
BLL/WXXD WXShopRevenueStatisticsManage.cs WXShopRevenueStatisticsService.cs
BLL/WXXD WXOemManage.cs WXOemService.cs
BLL/WXXD WXExpressOptimizeManage.cs WXExpressOptimizeService.cs
(备注) ProductThridManage、UpadteManage 旧代码中仅注释/疑似笔误,见 9.2

5.3 Global.asax 路由映射表(路由必须保持一致)

Global.asax.cs 的 Application_BeginRequest 中,把不带 .asmx 的友好 URL 重写到对应的 asmx。迁移后需在 Controller 上配置等价路由:

旧 URL 前缀 重写到(旧) 建议新路由(保持一致)
/user/{method} UserService.asmx/{method} [Route("user/[action]")] UserController
/shop/{method} ShopService.asmx/{method} [Route("shop/[action]")] ShopController
/order/{method} OrderService.asmx/{method} [Route("order/[action]")] OrderController
/product/{method} ProductService.asmx/{method} [Route("product/[action]")] ProductController
/product_third/{method} ProductThirdService.asmx/{method} [Route("product_third/[action]")] ProductThirdController
/price/{method} PriceService.asmx/{method} [Route("price/[action]")] PriceController
/update/{method} UpdateService.asmx/{method} [Route("update/[action]")] UpdateController
/bxx_user/{method} BXXUserService.asmx/{method} [Route("bxx_user/[action]")] BXXUserController
/bxx_shop/{method} BXXShopService.asmx/{method} [Route("bxx_shop/[action]")] BXXShopController
/bxx_product/{method} BXXProductService.asmx/{method} [Route("bxx_product/[action]")] BXXProductController
/bxx_product_third/{method} BXXProductThirdService.asmx/{method} [Route("bxx_product_third/[action]")] BXXProductThirdController
/bxx_price/{method} BXXPriceService.asmx/{method} [Route("bxx_price/[action]")] BXXPriceController
/dyxd_user/{method} DYUserService.asmx/{method} [Route("dyxd_user/[action]")] DYUserController
/dyxd_shop/{method} DYShopService.asmx/{method} [Route("dyxd_shop/[action]")] DYShopController
/dyxd_product/{method} DYProductService.asmx(旧项目不存在) 待确认
/dyxd_product_third/{method} DYProductThirdService.asmx(旧项目不存在) 待确认
/dyxd_price/{method} DYPriceService.asmx(旧项目不存在) 待确认
/wxxd_user/{method} WXUserService.asmx/{method} [Route("wxxd_user/[action]")] WXUserController
/wxxd_shop/{method} WXShopService.asmx/{method} [Route("wxxd_shop/[action]")] WXShopController
/wxxd_product/{method} WXProductService.asmx/{method} [Route("wxxd_product/[action]")] WXProductController
/wxxd_product_third/{method} WXProductThirdService.asmx(旧项目不存在) 待确认
/wxxd_price/{method} WXPriceService.asmx(旧项目不存在) 待确认
/wxxd_order/{method} WXOrderService.asmx/{method} [Route("wxxd_order/[action]")] WXOrderController
/wxxd_shop_revenue_statistics/{method} WXShopRevenueStatistics.asmx/{method} [Route("wxxd_shop_revenue_statistics/[action]")] WXShopRevenueStatisticsController
/ToolService.asmx/{method}(无前缀) 直接访问 [Route("ToolService/[action]")] ToolController

说明:旧 URL 没有 api/v1 前缀。若新项目仍使用 api/v{version}/[controller]/[action] 全局模板,则旧调用方 URL 会变化,属于不保持路由一致。默认方案:给各 Controller 单独设置与旧前缀一致的路由。

5.4 Model 清单(47 个,照抄)

Model/ 根目录(14 个):CommentParam、DBPriceResultParam、DBProdDbIdMapProductIdResultParam、DBProductResultParam、JSTDownProdSkuInfo、OrderParam、ProductPurchasePriceResultParam、ProductSelectResultParam、Result、SkuImgResult、TemuDBOrderInfo、UserLoginResultParam、WXAddressInfo、WxProdSecretSpuIdShopIdMapParam、WXShopDefaultAddressInfo

Model/ErpModel/(1 个):ErpMerchantInfo

Model/PddModel/(7 个):BuyerLoginInfo、PDDMaterialInfo、PDDProductDecorationInfo、PDDProductDetailInfo、PDDProductInfo、PDDProductPropertyInfo、PDDSizeSpecInfo

Model/ShopModel/(4 个):JitCardCodeParam、JSTListProductSkuInfo、ShopParam、sku_img_replace

Model/WxModel/(20 个):oem、oms_wei_external_procurement_after_sale_info、oms_wei_external_procurement_log、oms_wei_order、oms_wei_order_item、oms_wei_refund、order_item_ext、order_pdd_buyer_after_sale、order_pdd_buyer_order、user_payment_record_info、user_points_record_info、WXBuyUrlNotesInfo、WXClientProductInfoLite、WXGetEditProductInfoLite、WxOptimizeExpressInfo、WXOrderAmountInfo、WXOrderDecryptAddressInfo、wx_qualification_image_info

规则:所有 model 照抄,字段、属性、类名、命名空间规则均不修改(仅按需调整命名空间以适配新项目编译)。

5.5 Utils → Commons 清单(照搬)

旧 Utils 文件 新位置 说明
EncrypUtil.cs Commons/ 加密工具
HtmlUtils.cs Commons/ HTML/URL 工具
HttpUtils.cs Commons/ HTTP 工具
JsonUtils.cs Commons/ JSON 工具
RandomUtils.cs Commons/ 随机数工具
RegexUtils.cs Commons/ 正则解析(Manage 大量依赖)
TimeUtils.cs Commons/ 时间工具
Extension/(Convert、Enum、Exception、Linq、Validate) Commons/Extension/ 扩展方法(Manage 依赖 NaiBa.Util.Extension)
Helper/(HtmlHelper、JsonHelper、ReflectionHelper、RegexHelper) Commons/Helper/ 辅助类
ApiRequestLogger.cs (保留在旧项目或移入新项目) 请求录制,用于迁移后回放校验

6. 迁移实施步骤

  1. 确认新项目骨架:D:\Works\StoreHub\StoreHub.KJDWebService 已存在,Commons、Controllers、Dtos、Models、Services 目录已建,DemoService、SqlRepository、Startup.cs、Login.cs 示例已就位。
  2. Models 迁移:把旧 Model/ 下 47 个文件照抄到新项目 Models/(保留子目录结构或平铺均可,类定义一字不改)。
  3. Commons 迁移:把旧 Utils/(含 Extension、Helper)照搬进 Commons/,调整命名空间与 using 以适配 .NET 10 编译。
  4. Services 迁移:按 5.2 表,把每个 *Manage.cs 转换为 *Service.cs:
    • 类实现 ITransientDependency;
    • 构造函数注入 SqlRepository _sqlRepository;
    • 方法逻辑原样保留(不做优化、不改算法);
    • 把 new MysqlUtils(conn) + mySql.XXX(sql) 的调用改为 _sqlRepository.Ado.XXX(sql, 参数)(见第 7 节)。
  5. Controllers 迁移:按 5.1 表,把每个 *.asmx.cs 的 [WebMethod] 转为 Controller Action,并保留:
    • 请求体读取逻辑(等价于旧 GetRequestJsonString():body JSON 为空时回退 QueryString);
    • 响应格式(旧接口 Context.Response.Write(result) 输出原始 JSON 字符串 {code,msg,...},新接口建议 return Content(result, "text/html;charset=utf-8") 保持调用方兼容)。
  6. 路由配置:按 5.3 表给 Controller 配置与旧前缀一致的路由。
  7. 配置迁移:把旧 Web.config 的连接串与业务配置迁到宿主 appsettings.json(见第 8 节)。
  8. 编译与验证:编译通过后,用旧项目 App_Data/ApiLogs/ 下录制的请求做回放校验(ApiRequestLogger 录制了请求与响应),逐接口比对返回结果。

7. SQL 执行方式改造规范(改为参数方式)

旧代码示例(字符串拼接 + 手工转义):

string conn = System.Configuration.ConfigurationManager.ConnectionStrings["ConnKJD"].ConnectionString;
MysqlUtils mySql = new MysqlUtils(conn);
string sql = "select * from user where name = '" + name.Replace("'", "\\'") + "'";
var dt = mySql.ExecuteDataTable(sql);
mySql.Close();

新代码示例(参数化,逻辑不变):

string sql = "select * from user where name = @name";
var dt = _sqlRepository.Ado.ExecuteDataTable(sql, new { name = name });

MysqlUtils 方法 → FreeSql IAdo 对照:

旧(MysqlUtils) 新(_sqlRepository.Ado)
ExecuteDataTable(sql) ExecuteDataTable(sql, 参数)
ExecuteDataTableRow(sql) ExecuteDataTable(sql, 参数) 取第一行
ExecuteRowCount(sql) ExecuteDataTable(sql, 参数).Rows.Count 或 ExecuteScalar
ExecuteFirst / ExecuteFirstInt / ExecuteFirstDecimal ExecuteScalar / ExecuteDataTable
ExecuteAffectedRows / ExecuteNonQuery ExecuteNonQuery
ExecuteInsertId ExecuteInsertId / ExecuteScalar(select last_insert_id())
ExecuteExists ExecuteDataTable 判断行数
事务(IsUseTrans / Commit / RollBack) IAdo 事务 API(BeginTransaction / Commit / Rollback)
Close() 连接池自动管理,无需手动 Close

规则:只把拼接 SQL 改为参数方式,不改变 SQL 语义与业务逻辑。


8. 配置迁移(Web.config → appsettings.json)

旧 Web.config 关键配置:

旧配置(Web.config) 新配置(appsettings.json) 说明
connectionStrings: ConnKJD ConnectionStrings: KJDConnection 框架已用 KJDConnection 注册 keyed IFreeSql("KJDDB")(见 StoreHub.Framework/Startup.cs)
connectionStrings: ConnKJDBAK ConnectionStrings: KJDBAKConnection(建议) 备份库连接串,业务是否使用需确认
connectionStrings: UpdateVersion / UpdateFileDir / UpdateNewUrl / UpdateExe / UpdateExeChk / LowVersion / LimitVersion 等 appsettings.json 自定义配置节 供 UpdateService 使用
connectionStrings: GetReturnPackage / GetWXRecommendHotProd / ... 同上 业务开关类配置
connectionStrings: IsKeepBase64UploadImgFile / UpdateWxFindOrderFileDir / UpdateWxFindOrderUrl / WxFindOrderLimitVersion / WxFindOrderLowVersion 同上 业务配置

当前 appsettings.json 中的 KJDConnection 是占位值(Server=localhost;...),迁移时必须替换为旧 ConnKJD 的真实连接串。


9. 风险与待确认项

  1. Global.asax 中存在指向不存在 asmx 的路由:/dyxd_product/、/dyxd_product_third/、/dyxd_price/、/wxxd_product_third/、/wxxd_price/ 重写目标文件(DYProductService、DYProductThirdService、DYPriceService、WXProductThirdService、WXPriceService)在旧项目中不存在。迁移时按原样保留路由定义,但需与业务确认这些前缀是否仍被调用方使用。
  2. UserService.asmx.cs 的 GetUpdateInfo 引用 new UpadteManage():旧项目中不存在 UpadteManage 类(疑似 UpdateManage 笔误),迁移时需修正为 UpdateManage 或与业务确认。
  3. 响应格式兼容:旧接口返回的 {code,msg,...} 是原始 JSON 字符串,字段名/大小写/结构必须原样保留;不要直接替换成新框架 ApiResult<T> 的序列化格式,除非调用方同步升级。
  4. 请求读取方式:旧 GetRequestJsonString() 先读 body,body 为空时拼 QueryString;Controller 需保留等价实现。
  5. 多库支持:旧代码可能动态切换 ConnKJD / ConnKJDBAK;新框架目前只注册了 KJDDB 与 UserDB 两个 keyed IFreeSql,若业务用到其他库需在 StoreHub.Framework/Startup.cs 中补充注册。
  6. 上传/文件接口:UpdateService.DownloadFile(返回 byte[])、Upload/ 目录文件读写等,迁移时注意 IFormFile / 静态文件映射的等价实现。
  7. MachineKey / 会话:旧配置中有 machineKey,若接口依赖加密校验(如 EncrypUtil.Encryption 的 time/code 校验),仅为应用内算法,不依赖 ASP.NET 会话,可直接沿用 EncrypUtil。
  8. Base64 图片:IsKeepBase64UploadImgFile 等业务开关需迁移,保证行为一致。

10. 验收标准

  • 新项目可编译通过(.NET 10);
  • 20 个 asmx 服务全部有对应 Controller,356 个 WebMethod 全部有对应 Action;
  • 23 个 Manage 全部有对应 Service,且均注入 SqlRepository、使用 _sqlRepository.Ado.ExecuteDataTable;
  • 所有 Model 照抄未改动;
  • Manage 方法内业务逻辑未做任何优化/修改;
  • SQL 语句全部参数化,无字符串拼接注入风险;
  • 所有 Service 均已注册(实现 ITransientDependency / IScopedDependency),Controller 可正常注入;
  • 路由与旧 URL 保持一致(含 Global.asax 全部重写规则);
  • 使用 App_Data/ApiLogs/ 录制的请求做回放,新旧响应一致;
  • 连接串/业务配置迁移完成(KJDConnection 为真实连接串)。

本文档依据旧项目源码现状与目标项目骨架生成,供迁移实施与验收使用。