ASP.NET Core Web API:尝试激活时无法解析服务类型

Posted

技术标签:

【中文标题】ASP.NET Core Web API:尝试激活时无法解析服务类型【英文标题】:ASP.NET Core Web API: Unable to resolve service for type while attempting to activate 【发布时间】:2021-09-23 19:05:25 【问题描述】:

这是我第一次尝试 .NET API 并使用 .NET 核心。我曾经能够使用 ADO.NET 将数据库连接到项目,但显然不再支持,所以我使用 EF Core 使用这些包:microsoft.entityframeworkcore\5.0.8、microsoft.entityframeworkcore.sqlserver\5.0。 6,以及 microsoft.entityframeworkcore.tools\5.0.6。

然后我为数据库中的两个表生成了模型和数据库上下文,这似乎工作正常。但是,当我尝试访问 localhost/api/Statewides 时,我收到此错误:

System.InvalidOperationException: Unable to resolve service for type 'TestAPI.Models.RoadWay_HistoryContext' while attempting to activate 'TestAPI.Controllers.StatewidesController'.
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
   at lambda_method9(Closure , IServiceProvider , Object[] )
   at Microsoft.AspNetCore.Mvc.Controllers.ControllerActivatorProvider.<>c__DisplayClass4_0.<CreateActivator>b__0(ControllerContext controllerContext)
   at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

HEADERS
=======
Accept: text/plain
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: close
Host: localhost:44324
Referer: https://localhost:44324/swagger/index.html
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
sec-ch-ua-mobile: ?0
sec-fetch-site: same-origin
sec-fetch-mode: cors
sec-fetch-dest: empty

我真的不知道这意味着什么……我将提供数据库上下文和模型以及控制器和启动文件。如果您需要其他任何东西来回答这个问题,我很乐意提供。

全州控制器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using TestAPI.Models;

namespace TestAPI.Controllers

    [Route("api/[controller]")]
    [ApiController]
    public class StatewidesController : ControllerBase
    
        private readonly RoadWay_HistoryContext _context;

        public StatewidesController(RoadWay_HistoryContext context)
        
            _context = context;
        

        // GET: api/Statewides
        [HttpGet]
        public async Task<ActionResult<IEnumerable<Statewide>>> GetStatewides()
        
            return await _context.Statewides.ToListAsync();
        

        // GET: api/Statewides/5
        [HttpGet("id")]
        public async Task<ActionResult<Statewide>> GetStatewide(long id)
        
            var statewide = await _context.Statewides.FindAsync(id);

            if (statewide == null)
            
                return NotFound();
            

            return statewide;
        

        // PUT: api/Statewides/5
        // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
        [HttpPut("id")]
        public async Task<IActionResult> PutStatewide(long id, Statewide statewide)
        
            if (id != statewide.Id)
            
                return BadRequest();
            

            _context.Entry(statewide).State = EntityState.Modified;

            try
            
                await _context.SaveChangesAsync();
            
            catch (DbUpdateConcurrencyException)
            
                if (!StatewideExists(id))
                
                    return NotFound();
                
                else
                
                    throw;
                
            

            return NoContent();
        

        // POST: api/Statewides
        // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
        [HttpPost]
        public async Task<ActionResult<Statewide>> PostStatewide(Statewide statewide)
        
            _context.Statewides.Add(statewide);
            await _context.SaveChangesAsync();

            return CreatedAtAction("GetStatewide", new  id = statewide.Id , statewide);
        

        // DELETE: api/Statewides/5
        [HttpDelete("id")]
        public async Task<IActionResult> DeleteStatewide(long id)
        
            var statewide = await _context.Statewides.FindAsync(id);
            if (statewide == null)
            
                return NotFound();
            

            _context.Statewides.Remove(statewide);
            await _context.SaveChangesAsync();

            return NoContent();
        

        private bool StatewideExists(long id)
        
            return _context.Statewides.Any(e => e.Id == id);
        
    


Statewide.cs

using System;
using System.Collections.Generic;

#nullable disable

namespace TestAPI.Models

    public partial class Statewide
    
        public Statewide()
        
            DocumentsNavigation = new HashSet<Document>();
        

        public long Id  get; set; 
        public string County  get; set; 
        public string SignSys  get; set; 
        public string RouteNoOrigImport  get; set; 
        public int? RouteNo  get; set; 
        public int? SuppDes  get; set; 
        public string LocalName  get; set; 
        public DateTime? DateNumber  get; set; 
        public string Method  get; set; 
        public string OriginalL  get; set; 
        public string OriginalD  get; set; 
        public string Projects  get; set; 
        public string Documents  get; set; 
        public string Comments  get; set; 
        public int? District  get; set; 
        public bool DuplicateOk  get; set; 
        public string RightofWay  get; set; 
        public bool ReservedRoute  get; set; 
        public string ReservedBy  get; set; 
        public DateTime? ReservedDate  get; set; 
        public bool CpWorkCompleted  get; set; 
        public string WorkComments  get; set; 
        public string CpProjectNo  get; set; 
        public int? ReservedCat  get; set; 
        public string AddUser  get; set; 
        public DateTime? DateAdded  get; set; 

        public virtual ICollection<Document> DocumentsNavigation  get; set; 
    


数据库上下文

using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;

#nullable disable

namespace TestAPI.Models

    public partial class RoadWay_HistoryContext : DbContext
    
        public RoadWay_HistoryContext()
        
        

        public RoadWay_HistoryContext(DbContextOptions<RoadWay_HistoryContext> options)
            : base(options)
        
        

        public virtual DbSet<Document> Documents  get; set; 
        public virtual DbSet<Statewide> Statewides  get; set; 

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        
            if (!optionsBuilder.IsConfigured)
            
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263.
                optionsBuilder.UseSqlServer("Server=dotb6gisdbst01;Database=RoadWay_History;Trusted_Connection=True;");
            
        

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        
            modelBuilder.HasAnnotation("Relational:Collation", "SQL_Latin1_General_CP1_CI_AS");

            modelBuilder.Entity<Document>(entity =>
            
                entity.Property(e => e.Id).HasColumnName("ID");

                entity.Property(e => e.AddUser)
                    .HasMaxLength(25)
                    .HasColumnName("Add_User");

                entity.Property(e => e.DateAdded)
                    .HasColumnType("date")
                    .HasColumnName("Date_Added");

                entity.Property(e => e.DocLocation)
                    .HasMaxLength(255)
                    .HasColumnName("Doc_Location");

                entity.Property(e => e.DocType)
                    .HasMaxLength(255)
                    .HasColumnName("Doc_Type");

                entity.Property(e => e.FileContents)
                    .HasMaxLength(255)
                    .HasColumnName("File_Contents");

                entity.Property(e => e.OrderDate)
                    .HasColumnType("date")
                    .HasColumnName("Order_Date");

                entity.Property(e => e.StatewideId).HasColumnName("Statewide_ID");

                entity.HasOne(d => d.Statewide)
                    .WithMany(p => p.DocumentsNavigation)
                    .HasForeignKey(d => d.StatewideId)
                    .HasConstraintName("FK_Documents_Statewide");
            );

            modelBuilder.Entity<Statewide>(entity =>
            
                entity.ToTable("Statewide");

                entity.Property(e => e.Id).HasColumnName("ID");

                entity.Property(e => e.AddUser)
                    .HasMaxLength(25)
                    .HasColumnName("Add_User");

                entity.Property(e => e.County)
                    .HasMaxLength(255)
                    .HasColumnName("COUNTY");

                entity.Property(e => e.CpProjectNo)
                    .HasMaxLength(255)
                    .HasColumnName("CP_ProjectNo");

                entity.Property(e => e.CpWorkCompleted).HasColumnName("CP_WorkCompleted");

                entity.Property(e => e.DateAdded)
                    .HasColumnType("date")
                    .HasColumnName("Date_Added");

                entity.Property(e => e.DateNumber).HasColumnType("date");

                entity.Property(e => e.DuplicateOk).HasColumnName("Duplicate OK");

                entity.Property(e => e.LocalName).HasMaxLength(255);

                entity.Property(e => e.Method).HasMaxLength(255);

                entity.Property(e => e.OriginalD).HasMaxLength(255);

                entity.Property(e => e.OriginalL).HasMaxLength(255);

                entity.Property(e => e.ReservedDate).HasColumnType("date");

                entity.Property(e => e.RightofWay).HasMaxLength(255);

                entity.Property(e => e.RouteNoOrigImport).HasMaxLength(255);

                entity.Property(e => e.SignSys).HasMaxLength(255);

                entity.Property(e => e.WorkComments)
                    .HasMaxLength(255)
                    .HasColumnName("Work_Comments");
            );

            OnModelCreatingPartial(modelBuilder);
        

        partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
    


Startup.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace TestAPI

    public class Startup
    
        public Startup(IConfiguration configuration)
        
            Configuration = configuration;
        

        public IConfiguration Configuration  get; 

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        

            services.AddControllers();
            services.AddSwaggerGen(c =>
            
                c.SwaggerDoc("v1", new OpenApiInfo  Title = "TestAPI", Version = "v1" );
            );
        

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        
            if (env.IsDevelopment())
            
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "TestAPI v1"));
            

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            
                endpoints.MapControllers();
            );
        
    


【问题讨论】:

【参考方案1】:

您收到此错误是因为您尚未将RoadWay_HistoryContext 注册到服务容器。通过依赖注入使用的所有服务都必须注册。这就是类在您尝试使用它们时能够解析服务的方式。这就是您通过将此行添加到 ConfigureServices 方法来修复它的方法。

services.AddDbContext<RoadWay_HistoryContext>(opts => opts.UseSqlServer(Configuration.GetConnectionString("ConnectionName")));

更新


  "Logging": 
    "LogLevel": 
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    
  ,
  "ConnectionStrings": 
    "ConnectionName": "Server=ServerOfDatabase;Database=DatabaseName;Trusted_Connection=True;MultipleActiveResultSets=true"
  

【讨论】:

非常感谢您。 2 个问题:在哪里可以找到“我的连接名称”?我认为 RoadWay_HistoryContext 是这个名字......第二,你能不能给我指出一个好的文档?我找不到正确的文档来解决这个问题以挽救我的生命。 @GrillOwner69420 理想情况下,您应该将它放在 appsettings.development.json 中。我会更新答案以反映这一点。 在 appsettings.development.json 中放置什么?连接名称?我想我可以做到,但我必须先找到我的连接名称。我的连接名称是什么,如何找到它?就像我说的,我认为 RoadWay_HistoryContext 是连接名称。我不知道连接名称是什么。我不记得曾经被要求或声明过“连接名称” 连接名称可以是任何名称。它只是一个变量,其值为您的数据库连接字符串 我发现这是一个愚蠢的错误。非常感谢您的帮助!

以上是关于ASP.NET Core Web API:尝试激活时无法解析服务类型的主要内容,如果未能解决你的问题,请参考以下文章

使用 AspNetUserTokens 表在 ASP.NET Core Web Api 中存储刷新令牌

尝试将 ASP.NET CORE 2 Web API 应用程序连接到 WCF 服务

ASP.NET Core Web API DELETE 调用返回 405

如何从 ASP.NET MVC 到 ASP.NET Core Web API 的 PUT?

在c#asp.net core web api中创建jwt令牌[重复]

ASP.NET Core 6 Web API 的集成测试引发 System.InvalidOperationException