我正在尝试将代码从控制器分离到我创建的服务。我所做的是使用接口IUserService创建用户服务。
将RegisterUser代码从直接控制器移动到UserService,我遇到的下一个挑战是,直接与Controller一起使用的Url与Service不一起使用。
从控制器到服务的此代码已更改为:
如果在Controller中
private IUrlHelper _urlHelper;
public UserService (IUrlHelper urlHelper, HttpRequest request) {
_urlHelper = urlHelper;
}
从控制器更改为服务:
var callbackUrl = _urlHelper.EmailConfirmationLink (user.Email, token, U.Email, _request.Scheme);
这是构造函数,
在方法中,我这样称呼它:
services.AddScoped<IUserService, UserService>();
我在Startup.cs的DI中提到这样:
Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
An unhandled exception has occurred while executing the request.
System.InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Mvc.IUrlHelper' while attempting to activate 'erp.Services.UserService'.
在编译时没有例外。在运行时,它抛出异常:
Executed endpoint 'erp.Controllers.AccountController.Register (erp)'
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
An unhandled exception has occurred while executing the request.
System.InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Http.HttpRequest' while attempting to activate 'erp.Services.UserService'.
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type serviceType, Type implementationType, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Type serviceType, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.CreateServiceAccessor(Type serviceType)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
不清楚要做什么。
这是完整的堆栈跟踪,可以更仔细地查看错误。好吧,我不能说确切的行,因为我不是在调试,而只是从日志中复制:
{{1}}
答案 0 :(得分:1)
像这样在您的DI容器中注册IUrlHelper
:
services.AddScoped<IUrlHelper>(factory =>
{
var actionContext = factory.GetService<IActionContextAccessor>()
.ActionContext;
return new UrlHelper(actionContext);
});
要在服务中使用HttpContext,必须使用IHttpContextAccessor:
public class MyService
{
private IHttpContextAccessor _httpContextAccessor;
public MyService(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public void MyMethod()
{
// Use HttpContext like this
var username = _httpContextAccessor.HttpContext.User.Identity.Name;
}
}
此外,不要忘记在您的DI容器中注册IHttpContextAccessor:
services.AddHttpContextAccessor();
答案 1 :(得分:0)
对于Object reference not set to an instance of an object
,这是由于您没有注册IActionContextAccessor
而引起的。
尝试执行以下步骤:
UserService
public interface IUserService
{
void RegisterUser();
}
public class UserService : IUserService
{
private IUrlHelper _urlHelper;
private HttpRequest _request;
public UserService(IUrlHelper urlHelper, IHttpContextAccessor httpContextAccessor)
{
_urlHelper = urlHelper;
_request = httpContextAccessor.HttpContext.Request;
}
public void RegisterUser()
{
var callbackUrl = _urlHelper.EmailConfirmationLink("user.Email", "token", _request.Scheme);
//throw new NotImplementedException();
}
}
注册
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
services.AddScoped<IUrlHelper>(x => {
var actionContext = x.GetRequiredService<IActionContextAccessor>().ActionContext;
var factory = x.GetRequiredService<IUrlHelperFactory>();
return factory.GetUrlHelper(actionContext);
});
services.AddScoped<IUserService, UserService>();