GVKun编程网logo

简单注入器无法注入Web API控制器中的依赖项(简单注入器无法注入web api控制器中的依赖项怎么办)

8

本文将为您提供关于简单注入器无法注入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控制器中的依赖项怎么办)

简单注入器无法注入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控制器,您将看到问题出在哪里。

这是逐步进行的幕后工作:

  1. 和中的System.Web.Http.DefaultHttpControllerActivator调用SimpleInjectorWebApiDependencyResolver要求创建API控制器。
  2. SimpleInjectorWebApiDependencyResolver将该调用转发到SimpleInjector.Container实例。
  3. Container但是,该实例没有对该API控制器进行任何显式注册(因为您向解析器提供了一个空容器)。
  4. 由于没有显式注册,因此容器尝试对此类型进行最后一刻的注册。
  5. 但是,该Controller类型取决于无法解析的接口,因为它们未在容器中注册(请记住,您的容器为空)。
  6. 尽管容器通常会引发异常,但是在这种情况下将返回null,因为通过该IServiceProvider.GetService方法请求了类型,并且该类型未明确注册。
  7. SimpleInjectorWebApiDependencyResolverGetService方法将返回null为好,因为它的定义,它应该返回null; 当不存在注册时(当前就是这种情况),它应该返回null。
  8. 由于DependencyResolver返回的null DefaultHttpControllerActivator将返回其默认行为,这意味着将自己创建该类型,但这需要控制器具有默认构造函数。

简而言之,问题是由Web API处理解析控制器类型的隐式方式引起的。

因此,这里的解决方案是:

  1. Container您的Web应用程序中只有一个。这样可以避免各种麻烦和配置复杂化。
  2. 在容器中显式注册所有Web API控制器。明确注册控制器将确保在无法解析控制器时,Simple Injector将引发异常。此外,这允许您调用container.Verify(),当配置无效(可验证的配置很重要)时,这将导致应用程序在启动过程中失败。而且,这还使您能够诊断配置,从而使您对配置的正确性更有信心。

我的建议是将MVC和Web API放在自己的项目中。这将使事情变得容易得多。

可以使用以下代码注册所有Web API控制器:

container.RegisterWebApiControllers(GlobalConfiguration.Configuration);

更新:

由于此错误非常普遍,因此在请求控制器类型时,SimpleInjectorWebApiDependencyResolver该类的较新版本将
永远不会
返回null。相反,它将引发一个描述性错误。因此,只要您使用Official,就永远不会再看到错误SimpleInjectorWebApiDependencyResolver

.net – 简单注入器“由于在MVC验证期间已经处理了DbContext,因此无法完成操作

.net – 简单注入器“由于在MVC验证期间已经处理了DbContext,因此无法完成操作

我有一个非常复杂的问题.我在ASP.NET MVC 5项目中使用FluentValidation.MVC.在其中,我使用存储库模式来检查用户的电子邮件地址是否不重复.问题不在于存储库模式;这是存储库在运行时使用注入构造函数的实体框架上下文:

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上下文.我认为这是可取的.

解决方法

我最好的选择是在AppDomain(单例)的持续时间内缓存Val类的实例,这意味着它的构造函数只调用一次,因此它只解析一个ISomeRepos,导致该repo被提升为单例同样(以及它的所有依赖).

快速修复很简单,在委托中移动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 仓储接口的依赖注入

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个方法选项?

asp.net web api控制器中不允许405个方法选项?

我有这个非常常见的问题,它说GET请求的方法不允许(OPTIONS).每当我进行API调用时,我都会收到以下错误.我在web.config中有这个设置:

<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,但这也无效.

解决方法

在< remove name =“OPTIONsverbHandler”/>之后的处理程序中,添加以下内容:

<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控制器中手动验证模型

asp.net – 在Web api控制器中手动验证模型

我有一个名为’User’的类和一个属性’Name’

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?

解决方法

您可以使用 ApiController类的 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控制器中手动验证模型等更多相关知识的信息可以在本站进行查询。

本文标签: