在我的ASP.Net Core 6解决方案中,我有两组控制器。其中一组包含有其常规视图的网页。另一组包含API控制器。
为了避免重复db逻辑,web控制器正在使用API控制器。目前,我正在手动创建所需控制器的实例,方法是将DbContext作为构造函数参数传递给它。这是通过依赖注入给web控制器的DbContext。
但是,每当我向API控制器添加另一个构造函数参数时,我就需要修改使用这个API控制器的所有web控制器。
如何使用内置到ASP.Net 5的依赖注入系统为我创建所需API控制器的实例?然后它将自动填写所需的构造函数参数。
一种解决方案可以是将db逻辑从API控制器移到一个单独的层,并从API和web控制器调用它。这不会解决我的问题,因为新的层仍然需要相同的参数,我不喜欢不必要的布线。
另一种解决方案是让网络控制器通过网络调用访问API,但这只会增加应用程序的复杂性。
今天我要做的是:
public IActionResult Index()
{
using (var foobarController = new Areas.Api.Controllers.FoobarController(
// All of these has to be in the constructor of this controller so they can be passed on to the ctor of api controller
_dbContext, _appEnvironment,
_userManager, _roleManager,
_emailSender, _smsSender))
{
var model = new IndexViewModel();
model.Foo = foobarController.List(new FoobarRequest() { Foo = true, Bar = false });
model.Bar = foobarController.List(new FoobarRequest() { Foo = false, Bar = true });
return View(model);
}
}
我希望有这样的东西:(这个例子不起作用)
using (var foobarController = CallContextServiceLocator.Locator.ServiceProvider.GetService<Areas.Api.Controllers.FoobarController>())
{
var model = new IndexViewModel();
model.Foo = foobarController.List(new FoobarRequest() { Foo = true, Bar = false });
model.Bar = foobarController.List(new FoobarRequest() { Foo = false, Bar = true });
return View(model);
}
发布于 2016-01-28 08:15:42
要能够使用来自另一个控制器的控制器,您需要:
services.AddTransient <Areas.Api.Controllers.FoobarController, Areas.Api.Controllers.FoobarController>();
中注册控制器如果您需要访问控制器(如User
或Url
)中的本地属性,则有两种方法可以这样做。
第一种方法是使用DI获取IHttpContextAccessor
的一个实例来访问User
,使用IUrlHelper
来访问Url
对象:
public class FoobarController : Controller
{
private readonly ApplicationDbContext _dbContext;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IUrlHelper _urlHelper;
public FoobarController(ApplicationDbContext dbContext, IHttpContextAccessor httpContextAccessor, IUrlHelper _urlHelper, [...])
{
_dbContext = dbContext;
_httpContextAccessor = httpContextAccessor;
_urlHelper = urlHelper;
}
public FoobarResponse List(FoobarRequest request)
{
var userId = _httpContextAccessor.HttpContext.User.GetUserId();
var response = new FoobarResponse();
response.List = _dbContext.Foobars.Where(f => f.UserId == userId).ToList();
response.Thumb =
return response;
}
}
第二种方法是在调用控制器中设置它:
public class HomeController : Controller
{
private Areas.Api.Controllers.FoobarController _foobarController;
public HomeController(Areas.Api.Controllers.FoobarController foobarController)
{
_foobarController = foobarController;
}
private void InitControllers()
{
// We can't set this at Ctor because we don't have our local copy yet
// Access to Url
_foobarController.Url = Url;
// Access to User
_foobarController.ActionContext = ActionContext;
// For more references see https://github.com/aspnet/Mvc/blob/6.0.0-rc1/src/Microsoft.AspNet.Mvc.ViewFeatures/Controller.cs
// Note: This will change in RC2
}
public IActionResult Index()
{
InitControllers();
var model = new IndexViewModel();
model.Foo = _foobarController.List(new FoobarRequest() { Foo = true, Bar = false });
model.Bar = _foobarController.List(new FoobarRequest() { Foo = false, Bar = true });
return View(model);
}
}
ASP.Net核心MVC6 RC1控制器的源代码可以找到这里。然而,它正在对RC2进行大量重写,因此必须复制的属性才能访问用户和Url。
发布于 2018-03-19 21:31:33
如何使用内置到ASP.Net 5的依赖注入系统为我创建所需API控制器的实例?
在您的Startup.cs
中,可以告诉MVC注册所有的作为服务的控制器。
services.AddMvc().AddControllersAsServices();
然后,您可以通过DI机制将所需的控制器简单地注入到其他控制器中,并调用其操作方法。
发布于 2016-01-25 14:10:35
不要这样做。将该逻辑移动到另一个组件,该组件将在两个控制器之间共享。作为HTTP调用的结果,控制器由框架分派到,它不是您的公共API表面。通常,您的控制器应该用作将HTTP请求转换为业务对象的位置。对这些对象的操作应该委托给另一个层(特别是如果需要从应用程序中的多个位置使用它)。
https://stackoverflow.com/questions/34963586
复制相似问题