本文将为您提供关于简单注入器无法注入WebAPI控制器中的依赖项的详细介绍,我们还将为您解释简单注入器无法注入webapi控制器中的依赖项怎么办的相关知识,同时,我们还将为您提供关于.net–简单注入
本文将为您提供关于简单注入器无法注入Web API控制器中的依赖项的详细介绍,我们还将为您解释简单注入器无法注入web api控制器中的依赖项怎么办的相关知识,同时,我们还将为您提供关于.net – 简单注入器“由于在MVC验证期间已经处理了DbContext,因此无法完成操作、ASP.NET Core 2.2 WebApi 系列【三】AutoFac 仓储接口的依赖注入、asp.net web api控制器中不允许405个方法选项?、asp.net – 在Web api控制器中手动验证模型的实用信息。
本文目录一览:- 简单注入器无法注入Web API控制器中的依赖项(简单注入器无法注入web api控制器中的依赖项怎么办)
- .net – 简单注入器“由于在MVC验证期间已经处理了DbContext,因此无法完成操作
- ASP.NET Core 2.2 WebApi 系列【三】AutoFac 仓储接口的依赖注入
- asp.net web api控制器中不允许405个方法选项?
- asp.net – 在Web api控制器中手动验证模型
简单注入器无法注入Web API控制器中的依赖项(简单注入器无法注入web api控制器中的依赖项怎么办)
我正在尝试使用Simple Injector做一些基本的构造函数DI,看来它无法解决Web API控制器的依赖关系。
- 我在“ Controllers”文件夹之外的“ API”文件夹中有一个API控制器。
- 我也尝试将其放置在“ Controllers”文件夹中,但这似乎并没有太大的区别。我收到的堆栈跟踪类似于此问题中介绍的跟踪。
- 我正在使用全新安装的“ Simple Injector MVC集成快速入门” NuGet软件包(v。2.1.0)。
- 我有
SimpleInjectorWebApiDependencyResolver
文档的基础,也与此处的文档相同。 - 我正在使用Entity Framework,并且查看了有关正确加载上下文的更改的讨论线程。
这似乎不是问题,但是我仍然收到以下错误:
类型’MyProject.API.ArticleController’没有默认的构造函数
System.ArgumentException在
System.Web.Http.Internal.TypeActivator.System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage请求,类型controllerType的System.Web.Http.Internal.TypeActivator.Create
[TBase](Type instanceType)的System.Linq.Expressions.Expression.New(Type type)
,Func`1&activator)在System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage请求,HttpControllerDescriptor
controllerDescriptor,类型controllerType)
如果有人可以向我提供一些建议,关于是否应从其当前状态/呼叫顺序进行任何修改,将不胜感激。
ArticleController(基本结构):
public class ArticleController : ApiController{ private readonly IArticleRepository articleRepository; private readonly IUserRepository userRepository; private readonly IReleaseRepository releaseRepository; public ArticleController(IArticleRepository articleRepository, IUserRepository userRepository, IReleaseRepository releaseRepository) { this.articleRepository = articleRepository; this.userRepository = userRepository; this.releaseRepository = releaseRepository; } // GET api/Article public IEnumerable<Article> GetArticles(){ // code } // GET api/Article/5 public Article GetArticle(int id){ // code } // PUT api/Article/5 public HttpResponseMessage PutArticle(int id, Article article){ // code } // POST api/Article public HttpResponseMessage PostArticle(ArticleModel article){ // code } // DELETE api/Article/5 public HttpResponseMessage DeleteArticle(int id){ // code }}
SimpleInjectorInitializer:
public static class SimpleInjectorInitializer{ public static void Initialize() { var container = new Container(); InitializeContainer(container); container.RegisterMvcControllers(Assembly.GetExecutingAssembly()); container.RegisterMvcAttributeFilterProvider(); container.Verify(); DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container)); } private static void InitializeContainer(Container container) { container.Register<IArticleRepository, ArticleRepository>(); container.Register<IUserRepository, UserRepository>(); container.Register<IReleaseRepository, ReleaseRepository>(); }}
Global.asax.cs:
public class WebApiApplication : System.Web.HttpApplication{ private void ConfigureApi() { // Create the container as usual. var container = new Container(); // Verify the container configuration // container.Verify(); // Register the dependency resolver. GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container); } protected void Application_Start() { AreaRegistration.RegisterAllAreas(); ConfigureApi(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); }}
答案1
小编典典TLTR: 问题是由Web API处理解析控制器类型的隐式方式引起的;显式注册您的Web API控制器,您将看到问题出在哪里。
这是逐步进行的幕后工作:
- 和中的
System.Web.Http.DefaultHttpControllerActivator
调用SimpleInjectorWebApiDependencyResolver
要求创建API控制器。 SimpleInjectorWebApiDependencyResolver
将该调用转发到SimpleInjector.Container
实例。Container
但是,该实例没有对该API控制器进行任何显式注册(因为您向解析器提供了一个空容器)。- 由于没有显式注册,因此容器尝试对此类型进行最后一刻的注册。
- 但是,该Controller类型取决于无法解析的接口,因为它们未在容器中注册(请记住,您的容器为空)。
- 尽管容器通常会引发异常,但是在这种情况下将返回null,因为通过该
IServiceProvider.GetService
方法请求了类型,并且该类型未明确注册。 - 该
SimpleInjectorWebApiDependencyResolver
的GetService
方法将返回null
为好,因为它的定义,它应该返回null; 当不存在注册时(当前就是这种情况),它应该返回null。 - 由于
DependencyResolver
返回的nullDefaultHttpControllerActivator
将返回其默认行为,这意味着将自己创建该类型,但这需要控制器具有默认构造函数。
简而言之,问题是由Web API处理解析控制器类型的隐式方式引起的。
因此,这里的解决方案是:
Container
您的Web应用程序中只有一个。这样可以避免各种麻烦和配置复杂化。- 在容器中显式注册所有Web API控制器。明确注册控制器将确保在无法解析控制器时,Simple Injector将引发异常。此外,这允许您调用
container.Verify()
,当配置无效(可验证的配置很重要)时,这将导致应用程序在启动过程中失败。而且,这还使您能够诊断配置,从而使您对配置的正确性更有信心。
我的建议是将MVC和Web API放在自己的项目中。这将使事情变得容易得多。
可以使用以下代码注册所有Web API控制器:
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
更新:
由于此错误非常普遍,因此在请求控制器类型时,SimpleInjectorWebApiDependencyResolver
该类的较新版本将
永远不会
返回null
。相反,它将引发一个描述性错误。因此,只要您使用Official,就永远不会再看到错误SimpleInjectorWebApiDependencyResolver
。
.net – 简单注入器“由于在MVC验证期间已经处理了DbContext,因此无法完成操作
public class SomeRepository { //IEFContext is something I modified the T4 template to generate public SomeRepository(IEFContext context) { _context = context; } }
该应用程序使用这种方法,它工作得很好. SimpleInjector连接我的EF上下文,其范围限定为使用Per ASP.NET Web请求(包装HttpContext.Items).
Dim httpLifecycle = New SimpleInjector.Integration.Web.WebRequestLifestyle(True) container.Register(of IEFContext,EFContext)(httpLifecycle)
这里的应用没有问题,只是验证.当服务器收到post操作时,我得到的错误是“由于已经处理了DbContext,因此无法完成操作”.看来我不能在FluentValidation属性中使用任何与EF相关的代码,该属性在每个Web请求的基础上使用EF上下文.验证属性没有什么特别之处,它可以:
public class Val : AbstractValidator<Entity> { public Val() { _repos = Container.GetInstance<ISomeRepos>(); RuleFor(i => i.Email).Must((o,v) => { _repos.HasdistinctEmail(o.ID,v); } } }
由于存储在HttpContext.Items中,因此上下文应该与之前的请求一起死亡.知道发生了什么事吗?我知道通过将True设置为WebRequestLifecycle,我会在请求结束时处理EF上下文.我认为这是可取的.
解决方法
快速修复很简单,在委托中移动GetInstance调用:
public Val() { RuleFor(i => i.Email).Must((o,v) => { repos = Container.GetInstance<ISomeRepos>(); repos.HasdistinctEmail(o.ID,v); } }
ASP.NET Core 2.2 WebApi 系列【三】AutoFac 仓储接口的依赖注入
一、准备工作
通过程序包管理器控制台安装 AutoFac:
Install-Package Autofac.Extensions.DependencyInjection
创建新类库(.NetCore 2.2 类库),存放接口跟实现类,命名为 NetCoreWebApi.Repository。
创建用户仓储接口
在类库项目上右键 -> 添加 -> 新建文件夹,命名为 Interface,存放接口类。在 Interface 文件夹下面新建类:IUserRepository,属性如下:
using System.Collections.Generic;
using NetCoreWebApi.Model.Models;
namespace NetCoreWebApi.Repository.Interface
{
/// <summary>
/// 用户接口
/// </summary>
public interface IUserRepository
{
/// <summary>
/// 添加用户
/// </summary>
/// <param name="entity">实体对象</param>
int Add(TbUser entity);
/// <summary>
/// 删除用户
/// </summary>
/// <param name="entity">实体对象</param>
int Remove(TbUser entity);
/// <summary>
/// 编辑用户
/// </summary>
/// <param name="entity">实体对象</param>
/// <returns></returns>
int Update(TbUser entity);
/// <summary>
/// 获取所有
/// </summary>
/// <returns></returns>
IList<TbUser> GetAll();
}
}
创建用户接口实现类
在类库项目上右键 -> 添加 -> 新建文件夹,命名为 Implement,存放接口实现类。在 Implement 文件夹下面新建类:UserRepository,属性如下:
using System.Collections.Generic;
using System.Linq;
using NetCoreWebApi.Model;
using NetCoreWebApi.Model.Models;
using NetCoreWebApi.Repository.Interface;
namespace NetCoreWebApi.Repository.Implement
{
/// <summary>
/// 业务处理
/// </summary>
public class UserRepository:IUserRepository
{
private readonly MyDbContext _dbContext;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="dbContext"></param>
public UserRepository(MyDbContext dbContext)
{
_dbContext = dbContext;
}
/// <summary>
/// 添加用户
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public int Add(TbUser entity)
{
_dbContext.TbUsers.Add(entity);
return _dbContext.SaveChanges();
}
/// <summary>
/// 删除用户
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public int Remove(TbUser entity)
{
_dbContext.TbUsers.Remove(entity);
return _dbContext.SaveChanges();
}
/// <summary>
/// 编辑用户
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public int Update(TbUser entity)
{
return _dbContext.SaveChanges();
}
/// <summary>
/// 查询用户
/// </summary>
/// <returns></returns>
public IList<TbUser> GetAll()
{
return _dbContext.TbUsers.ToList();
}
}
}
二、配置注入
打开 Startup.cs 类
把 ConfigureServices 方法的返回值由 void 变为 IServiceProvider
public static IContainer ApplicationContainer { get; set; }
/// <summary>
/// //负责注入服务
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public IServiceProvider ConfigureServices(IServiceCollection services)
{
var connectionStr = Configuration.GetConnectionString("SqlServer");
services.AddDbContext<MyDbContext>
(options => options.UseSqlServer(connectionStr,
e => e.MigrationsAssembly("NetCoreWebApi.Model")));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
//初始化容器
var builder = new ContainerBuilder();
//管道寄居
builder.Populate(services);
//注册仓储,IUserRepository接口到UserRepository的映射
builder.RegisterType<UserRepository>().As<IUserRepository>();
//构造
ApplicationContainer = builder.Build();
//将AutoFac反馈到管道中
return new AutofacServiceProvider(ApplicationContainer);
}
三、测试
在项目上右键 -> 添加 -> 新建文件夹,命名为 Controllers,存放相应的控制器。在 Controllers 文件夹下面新建一个控制器:UserController,如下:
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using NetCoreWebApi.Model.Models;
using NetCoreWebApi.Repository.Interface;
namespace NetCoreWebApi.Controllers
{
/// <summary>
/// 用户模块
/// </summary>
[Route("api/user")]
[ApiController]
public class UserController : ControllerBase
{
private readonly IUserRepository _userRepository;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="userRepository"></param>
public UserController(IUserRepository userRepository)
{
_userRepository = userRepository;
}
/// <summary>
/// 创建用户
/// </summary>
/// <returns></returns>
[Route("createUser")]
[HttpPost]
public TbUser CreateUser()
{
var user = new TbUser
{
UserId = Guid.NewGuid().ToString("N"),
CreateTime = DateTime.Now,
UserName = "tenghao",
Email = "tenghao510@qq.com"
};
_userRepository.Add(user);
return user;
}
/// <summary>
/// 查询用户
/// </summary>
/// <returns></returns>
[Route("getUser")]
[HttpGet]
public IList<TbUser> GetUser()
{
return _userRepository.GetAll();
}
}
}
Ctrl+F5 运行之后,先用 Postman 调创建用户接口
接下来测试下查询用户
好了,你们自己测下写的有没有问题。
asp.net web api控制器中不允许405个方法选项?
<system.webServer> <modules> <remove name="WebDAVModule"/> </modules> <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="*"/> <add name="Access-Control-Allow-Headers" value="Origin,Authorization,X-Requested-With,Content-Type,Accept"/> <add name="Access-Control-Allow-Methods" value="GET,POST,PUT,DELETE,OPTIONS"/> </customHeaders> </httpProtocol> <handlers> <remove name="WebDAV"/> <remove name="ExtensionlessUrlHandler-Integrated-4.0"/> <remove name="OPTIONsverbHandler"/> <remove name="TRACEVerbHandler"/> <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/> </handlers> </system.webServer>
我尝试使用Asp.Net.WebApi.Cors并使用EnableCors()对所有原始标头和方法全局强制执行CORS,但这也无效.
解决方法
<add name="OPTIONsverbHandler" path="*" verb="OPTIONS" modules="IsapiModule" requireAccess="None" scriptprocessor="C:\Windows\System32\inetsrv\asp.dll" resourceType="Unspecified" />
请参阅IIS hijacks CORS Preflight OPTIONS request的答案.
或者甚至可能只是这样:
<add name="OPTIONsverbHandler" path="*" verb="OPTIONS" modules="ProtocolSupportModule" requireAccess="None" />
如果这不起作用,那么将在global.asax或其他代码中添加以下内容:
protected void Application_BeginRequest(object sender,EventArgs e) { HttpContext.Current.response.addheader("Access-Control-Allow-Origin","*"); if(HttpContext.Current.Request.HttpMethod == "OPTIONS") { HttpContext.Current.response.addheader("Access-Control-Allow-Methods","GET,DELETE"); HttpContext.Current.response.addheader("Access-Control-Allow-Headers","Content-Type,Accept"); HttpContext.Current.response.addheader("Access-Control-Max-Age","1728000" ); HttpContext.Current.Response.End(); } }
asp.net – 在Web api控制器中手动验证模型
public class User { [required] public string Name { get; set; } }
而api控制器的方法是
public IHttpActionResult PostUser() { User u = new User(); u.Name = null; if (!ModelState.IsValid) return BadRequest(ModelState); return Ok(u); }
如何手动验证User对象,以便ModelState.IsValid向我返回false?
解决方法
Validate()
方法手动验证模型并设置
ModelState.
public IHttpActionResult PostUser() { User u = new User(); u.Name = null; this.Validate(u); if (!ModelState.IsValid) return BadRequest(ModelState); return Ok(u); }
今天关于简单注入器无法注入Web API控制器中的依赖项和简单注入器无法注入web api控制器中的依赖项怎么办的介绍到此结束,谢谢您的阅读,有关.net – 简单注入器“由于在MVC验证期间已经处理了DbContext,因此无法完成操作、ASP.NET Core 2.2 WebApi 系列【三】AutoFac 仓储接口的依赖注入、asp.net web api控制器中不允许405个方法选项?、asp.net – 在Web api控制器中手动验证模型等更多相关知识的信息可以在本站进行查询。
本文标签: