问题是:
处理请求时发生未处理的异常。
InvalidOperationException:尝试激活“CineMagic.Controllers.HomeController”时无法解析类型“CineMagicAPI.Controllers.PopularMoviesController”的服务。
Microsoft.Extensions.DependencyInjection.ActivatorUtilities.ThrowHelperUnableToResolveService(类型类型,类型requiredBy)
CineMagicAPI> Movies.cs:
public class Movies
{
public bool adult { get; set; }
public string backdrop_path { get; set; }
public List<int> genre_ids { get; set; }
public int id { get; set; }
public string original_language { get; set; }
public string original_title { get; set; }
public string overview { get; set; }
public decimal popularity { get; set; }
public string poster_path { get; set; }
public DateTime release_date { get; set; }
public string title { get; set; }
public bool video { get; set; }
public decimal vote_average { get; set; }
public int vote_count { get; set; }
}
CineMagicAPI>PopularMoviesController.cs
using Microsoft.AspNetCore.Mvc;
using CineMagicAPI.Models;
using System.Collections.Generic;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
namespace CineMagicAPI.Controllers
{
[ApiController]
[Route("[controller]")]
public class PopularMoviesController : ControllerBase
{
private readonly IHttpClientFactory _clientFactory;
private readonly PopularMoviesController _popularMoviesService;
private const string TMDB_API_KEY = "30b4c1980f6c33f5036366f3c4def27b"; //tmdb'ye kayıt olunup key alındı.
public PopularMoviesController(IHttpClientFactory clientFactory, PopularMoviesController popularMoviesService)
{
_clientFactory = clientFactory;
_popularMoviesService = popularMoviesService;
}
[HttpGet]
public async Task<List<Movies>> GetPopularMoviesAsync()
{
List<Movies> popularMovies = new List<Movies>();
string endpoint = $"https://api.themoviedb.org/3/movie/popular?api_key={TMDB_API_KEY}";
var client = _clientFactory.CreateClient();
HttpResponseMessage response = await client.GetAsync(endpoint);
if (response.IsSuccessStatusCode)
{
string json = await response.Content.ReadAsStringAsync();
var data = JsonSerializer.Deserialize<TMDbResponse>(json);
popularMovies = data?.results;
}
return popularMovies;
}
}
public class TMDbResponse
{
public List<Movies> results { get; set; }
}
}
CineMagic> HomeController.cs
using CineMagic.Models;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using CineMagicAPI.Controllers;
namespace CineMagic.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private readonly PopularMoviesController _popularMoviesService;
public HomeController(ILogger<HomeController> logger, PopularMoviesController popularMoviesService)
{
_logger = logger;
_popularMoviesService = popularMoviesService;
}
public async Task<IActionResult> Index()
{
List<Movies> popularMovies = await _popularMoviesService.GetPopularMoviesAsync();
return View(popularMovies);
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}
CineMagic>Program.cs
using CineMagicAPI.Controllers;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
我想使用从 TMDB API 收到的密钥在我的主页上显示热门电影。我有索引 html 页面,但在此之前我收到错误。如何修复我上面分享的错误?
您正在尝试将一个控制器注入另一个控制器,但在默认配置中,控制器未在 DI 容器中注册。 MVC 自己创建控制器(不通过 DI 容器请求它们),并且仅从 DI 容器请求其依赖项。这需要注册这些依赖项,但同样,控制器未注册(默认情况下)。
快速解决方法是添加以下注册:
builder.Services.AddControllersWithViews()
.AddControllersAsServices();
尽管这将允许将
PopularMoviesController
注入到您的 HomeController
中,但它可能仍然无法按预期工作。这是否有效取决于您是否使用 MVC 为 PopularMoviesController
初始化的请求特定状态。此状态仅在 MVC 作为根对象创建/解析时才会初始化,但在将其注入另一个对象时不会初始化。考虑到您发布的代码,目前这可能会起作用,但如果您对 PopularMoviesController
进行更改,将来可能很容易崩溃。所以更好的解决办法是防止控制器相互依赖。相反,从 PopularMoviesController
中提取共享逻辑并将其放入新类中。将该类注册到 DI 容器中,并将其作为依赖项注入到
PopularMoviesController
和 HomeController
。例如:
[ApiController]
[Route("[controller]")]
public class PopularMoviesController : ControllerBase
{
private readonly PopularMoviesController _service;
public PopularMoviesController(IPopularMoviesService service)
{
_service = service;
}
[HttpGet]
public async Task<List<Movies>> GetPopularMoviesAsync()
{
var movies = await _service.GetPopularMoviesAsync();
return movies;
}
}
public class HomeController : Controller
{
private readonly IPopularMoviesService _service;
public HomeController(IPopularMoviesService service)
{
_service = service;
}
public async Task<IActionResult> Index()
{
var movies = await _service.GetPopularMoviesAsync();
return View(movies);
}
...
}
来自
PopularMoviesController
的逻辑现在隐藏在
IPopularMoviesService
后面,PopularMoviesController
和 HomeController
都依赖于此。这个IPopularMoviesService
需要实现,如下所示:public interface IPopularMoviesService
{
Task<List<Movies>> GetPopularMoviesAsync();
}
public class PopularMoviesService : IPopularMoviesService
{
private const string TMDB_API_KEY = "{your api key}";
private readonly IHttpClientFactory _clientFactory;
public PopularMoviesController(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
}
public async Task<List<Movies>> GetPopularMoviesAsync()
{
List<Movies> popularMovies = new List<Movies>();
var endpoint = $"https://api.themoviedb.org/3/movie/popular?api_key={TMDB_API_KEY}";
// IMPORTANT: Do make sure HttpClient is disposed of.
using (var client = _clientFactory.CreateClient())
{
HttpResponseMessage response = await client.GetAsync(endpoint);
if (response.IsSuccessStatusCode)
{
string json = await response.Content.ReadAsStringAsync();
var data = JsonSerializer.Deserialize<TMDbResponse>(json);
popularMovies = data?.results;
}
return popularMovies;
}
}
}
这引入了一个新的
PopularMoviesService
类和
IPopularMoviesService
接口,它们必须在 DI 容器中注册,如下所示:builder.Services
.AddTransient<IPopularMoviesService, PopularMoviesService>();