You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core Controller带string构造参数报依赖解析错误如何解决

问题描述

在开展代码重构工作时,我将StatusController的构造函数入参从IConfiguration替换为string类型的连接字符串参数,该参数由其他控制器传入,相关实现代码如下:

StatusController.cs

public class StatusController : Microsoft.AspNetCore.Mvc.ControllerBase
{
    
    protected StatusDAL status_dal;
    public StatusController(string connectionString)
    {
        status_dal = new StatusDAL(connectionString);
    }
 }

StatusController会被其他控制器调用,对应HVIRCalcController的实现代码如下:
HVIRCalcController.cs

public class HVIRCalcController : BaseServicesController
{

    private readonly string _connectionString;
    public HVIRCalcController(IConfiguration config)
    {
        
        _connectionString = config.GetConnectionString("toolboxConnectionStrWPS");
        
    }

    [HttpPost]
    public IActionResult PostTask(int service_id, [FromBody]HVIRServiceRequestParams hvir_params)
    {
         StatusAck sack = new HVIR_Calc_Engine(_connectionString).BatchCalc(hvir_params);

     }
}

HVIRCalcEngine.cs

public class HVIR_Calc_Engine
{
    private string _connectionString;

    public HVIR_Calc_Engine(string connectionString)
    {
        //this.config = config;
        _connectionString = connectionString;
        status_dal = new StatusDAL(connectionString);
        pg_dal = new PostgresDAL(connectionString);

    }

    public StatusAck BatchCalc(HVIRServiceRequestParams hvirparams)
    {
       StatusAck statusack = new StatusController(_connectionString).PostStatusRecord();
    }
}

项目运行时抛出如下错误:

Unable to resolve service for type 'System.String' while attempting to activate 'WPS_WebAPI.Controllers.StatusController'

需求是找到可行技术方案,避免将IConfiguration从HVIRCalcController开始逐层传递至StatusController,同时解决上述依赖注入报错问题。

解决方案

报错核心原因是ASP.NET Core的依赖注入容器会自动尝试解析所有继承自ControllerBase的控制器构造函数参数,你给StatusController加了string类型的参数,容器不知道该注入什么值,自然会抛异常。控制器是由框架激活管理的,不应该在业务代码里手动实例化,你现在手动new控制器的写法本身就不符合ASP.NET Core的设计规范。

按下面步骤改就能解决问题,也不用逐层传配置:

  • 不要把业务逻辑写在控制器里,把StatusController里处理状态记录的逻辑抽成单独的服务类,比如IStatusService和对应实现StatusService,把原来StatusDAL的依赖放到这个服务里。
    public interface IStatusService
    {
        StatusAck PostStatusRecord();
    }
    
    public class StatusService : IStatusService
    {
        private readonly StatusDAL _statusDal;
        public StatusService(IConfiguration config)
        {
            var connStr = config.GetConnectionString("toolboxConnectionStrWPS");
            _statusDal = new StatusDAL(connStr);
        }
    
        public StatusAck PostStatusRecord()
        {
            // 迁移原来StatusController里的业务逻辑到这里
        }
    }
    
  • 把数据访问类的依赖统一注册到DI容器,不要到处手动new。StatusDAL、PostgresDAL都可以注册,连接字符串直接在注册的时候从配置取,不用逐层传。在Program.cs(老版本是Startup.cs)里加服务注册代码:
    // 注册业务服务
    builder.Services.AddScoped<IStatusService, StatusService>();
    // 注册DAL,注册阶段直接读取配置拿连接字符串,不需要上层传参
    builder.Services.AddScoped(sp => 
    {
        var config = sp.GetRequiredService<IConfiguration>();
        var connStr = config.GetConnectionString("toolboxConnectionStrWPS");
        return new StatusDAL(connStr);
    });
    builder.Services.AddScoped(sp => 
    {
        var config = sp.GetRequiredService<IConfiguration>();
        var connStr = config.GetConnectionString("toolboxConnectionStrWPS");
        return new PostgresDAL(connStr);
    });
    // 注册计算引擎
    builder.Services.AddScoped<HVIR_Calc_Engine>();
    
  • 改造HVIR_Calc_Engine,直接注入需要的DAL或者服务,不用接收连接字符串参数:
    public class HVIR_Calc_Engine
    {
        private readonly StatusDAL _statusDal;
        private readonly PostgresDAL _pgDal;
        private readonly IStatusService _statusService;
    
        public HVIR_Calc_Engine(StatusDAL statusDal, PostgresDAL pgDal, IStatusService statusService)
        {
            _statusDal = statusDal;
            _pgDal = pgDal;
            _statusService = statusService;
        }
    
        public StatusAck BatchCalc(HVIRServiceRequestParams hvirparams)
        {
            // 直接调用注入的服务方法,不需要手动new控制器
            StatusAck statusack = _statusService.PostStatusRecord();
            // 其余业务逻辑保持不变
            return statusack;
        }
    }
    
  • 改造HVIRCalcController,直接注入需要的计算引擎,不用手动读取配置传连接字符串、不用手动new引擎实例:
    public class HVIRCalcController : BaseServicesController
    {
        private readonly HVIR_Calc_Engine _calcEngine;
        public HVIRCalcController(HVIR_Calc_Engine calcEngine)
        {
            _calcEngine = calcEngine;
        }
    
        [HttpPost]
        public IActionResult PostTask(int service_id, [FromBody]HVIRServiceRequestParams hvir_params)
        {
             StatusAck sack = _calcEngine.BatchCalc(hvir_params);
             // 其余返回逻辑保持不变
             return Ok(sack);
        }
    }
    
  • 最后清理StatusController的构造函数,移除string类型的连接字符串参数,只保留处理HTTP请求的相关逻辑,需要的业务依赖直接注入对应服务即可。

如果只是想临时解决报错、不想做架构调整,也可以在注册控制器的时候手动指定StatusController的连接字符串参数,但这种写法不符合分层规范,后续维护成本高,不推荐长期使用。


内容的提问来源于stack exchange,提问作者Samra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 17:16:17