【问题标题】:How can I call Web API non-default constructor in new ASP.NET Core如何在新的 ASP.NET Core 中调用 Web API 非默认构造函数
【发布时间】:2017-03-18 20:14:07
【问题描述】:

我创建了一个使用 Web API 的项目。我想让控制器有一个构造函数,它接受构造函数注入的一个参数。在启动时,我添加了这个:

Startup.cs:

public class Startup
{
    // Other codes ommitted

    public void ConfigureServices(IServiceCollection services)
    {
        // Other codes ommitted

        // Add application services.
        services.AddTransient<IStudentDataAccess, StudentDataAccess>();
    }
}

在控制器中,我有这个构造函数:

值控制器:

[Route("api/[controller]")]
public class ValuesController : Controller
{
    private IStudentDataAccess _studentDataAccess;

    public ValuesController(IStudentDataAccess studentDataAccess)
    {
        _studentDataAccess = studentDataAccess;
    }

    // GET: api/values
    [HttpGet]
    public IEnumerable<string> Get()
    {
        IStudentLogic studentLogic = new StudentLogic(_studentDataAccess);
        return new string[] { "value1", "value2" };
    }
}

但是构造函数没有被调用。我看到对于以前的 ASP.NET 版本,您可以这样做。如何在新的 ASP.NET 中执行此操作?或者 ASP.NET 解析 IStudentDataAccess 时如何传递参数?

更新:

好的,我认为问题在于我的 StudentDataAccess 类有一个接受 IDbContext 的非默认构造函数。如果我删除构造函数,它可以工作。但我需要能够在 StudentDataAccess 的构造函数中传递一个 IDbContext。我尝试在 ConfigureServices 中添加它:

services.AddTransient<IDbContext, TestDbContext>();

但是构造函数没有被断点击中。以下是 StudentDataAccess 的声明:

public class StudentDataAccess : IStudentDataAccess
{
    private IDbContext _context;

    public StudentDataAccess(IDbContext context)
    {
        _context = context;
    }
}

IDbContext 只是一个没有成员的接口。

【问题讨论】:

  • 它应该可以工作。您的控制器是从Microsoft.AspNet.Mvc.Controller 派生的吗?你有多个构造函数吗?你有minimal, complete and verifiable example吗?
  • @Leonardo Herrera:不幸的是,事实并非如此。我不能在这里复制所有内容,但我所做的是默认的 Web API 模板,使用一个参数创建了一个新的构造函数,在其上放置了一个断点,然后运行它。它没有达到断点。
  • 可以创建一个 MCVE。显示您的控制器声明。
  • @mason:按照建议添加。
  • 如果你在 get 方法的第一行放了一个断点,它会被命中吗?

标签: c# asp.net-core asp.net-core-mvc


【解决方案1】:

您显示的内容有问题。

要将您自己的瞬态服务添加到您的控制器:

  • 定义你的界面
  • 定义实现接口的类
  • Startup.cs中将services.AddTransient&lt;IYourInterface, YourClass&gt;();添加到ConfigureServices
  • 将构造函数添加到您的控制器,以接收您的服务作为参数。确保您只有一个构造函数。

我的最小工作示例:

Startup.cs:

using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace WebApplication5
{
    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
        }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddTransient<IStudentDataAccess, StudentDataAccess>();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            app.UseIISPlatformHandler();
            app.UseMvc();
        }
        public static void Main(string[] args) => WebApplication.Run<Startup>(args);
    }
}

ValuesController.cs:

using Microsoft.AspNet.Mvc;
using System.Collections.Generic;

namespace WebApplication5.Controllers
{
    [Route("api/[controller]")]
    public class ValuesController : Controller
    {
        private IStudentDataAccess _studentDataAccess;

        public ValuesController(IStudentDataAccess studentDataAccess)
        {
            _studentDataAccess = studentDataAccess;
        }

        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "value", _studentDataAccess.Hello() };
        }
    }
}

StudentDataAccess.cs:

namespace WebApplication5
{
    public interface IStudentDataAccess
    {
        string Hello();
    }

    public class StudentDataAccess : IStudentDataAccess
    {
        public string Hello()
        {
            return "Hello from Service";
        }
    }
}

结果:

["value","Hello from Service"]

【讨论】:

  • 我试过你的例子,它确实有效。在我的项目中,接口和具体类都在不同的程序集中(但 StudentDataAccess 肯定实现了 IStudentDataAccess)。当这是设置时,构造函数不会被命中。但是当我将它们移动到同一个程序集(就在 Startup.cs 之后)时,它就可以工作了。知道这是为什么吗?我有相同的代码,只是不同的程序集。
  • 好的,我认为问题在于我的 StudentDataAccess 类有一个接受 IDbContext 的非默认构造函数。如果我删除构造函数,它可以工作。但我需要能够在 StudentDataAccess 的构造函数中传递一个 IDbContext。你能告诉我怎么做吗?
  • 我创建了一个新项目,即使 StudentDataAccess 没有默认构造函数,它也可以工作。我需要追踪我原来的问题发生了什么,但正如你所说,它确实有效。
  • 我认为您需要为您的服务使用配置选项。这可能是另一个问题。
  • 我们可以有两个构造函数吗?
【解决方案2】:

试试把FromServicesAttribute,例如:

public ValuesController([FromServices]IStudentDataAccess studentDataAccess)
{
    _studentDataAccess = studentDataAccess;
}

这对我有用:)

【讨论】:

  • 构造函数中不需要FromServices 属性。它用于动作中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-20
  • 2010-10-30
  • 2017-07-06
  • 2016-12-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多