我有一个 blazor 项目,其中我使用依赖注入来使用 AuthenticationStateProvider。
我收到错误:
'GetAuthenticationStateAsync 在 SetAuthenticationState 之前被调用。
我有两项服务:
报告解析器间接依赖于ServiceClass,这是在startup.cs中的注册:
services.AddScoped<IServiceClass, ServiceClass>();
services.AddScoped<IReportServiceConfiguration>(sp =>
new ReportServiceConfiguration
{
ReportingEngineConfiguration = sp.GetService<IConfiguration>(),
HostAppId = "Html5DemoAppCore",
Storage = new FileStorage(),
ReportSourceResolver = sp.GetService<CustomReportSourceResolver>(),
}
); ;
服务类别代码:
public class ServiceClass : IServiceClass
{
public ServiceClass(AuthenticationStateProvider authenticationStateProvider)
{
_authenticationStateProvider = authenticationStateProvider;
}
private readonly AuthenticationStateProvider _authenticationStateProvider;
private string authuser = "";
public async Task<string> GetIdentity()
{
var result = "";
try
{
var authState = await _authenticationStateProvider.GetAuthenticationStateAsync();
var user = authState.User;
IEnumerable<Claim> claims = user.Claims;
if (authState != null)
{
result = claims.FirstOrDefault(c => c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress").Value;
authuser = result;
}
else
result = authuser;
}
catch (Exception ex)
{ System.Diagnostics.Debug.WriteLine(ex.ToSafeString()); }
return result;
}
}
全周期
服务类的 getIdentity() 自应用程序启动以来被调用多次,并且运行良好。 但是当这个剃刀组件运行时
<ReportViewer ViewerId="rv1"
ServiceUrl="/api/reports"
ReportSource="@(new ReportSourceOptions()
{
Report = "reportAccountingGeneralLedger",
Parameters= new Dictionary <string,object>
{}
})"
Parameters="@(new ParametersOptions { Editors = new EditorsOptions { MultiSelect = EditorType.ComboBox, SingleSelect = EditorType.ComboBox } })"
ScaleMode="@(ScaleMode.Specific)"
Scale="1.0" />
Report = "reportAccountingGeneralLedger" 部分是通过我们在startup.cs中注册的ReportServiceConfiguration服务来解析的。 (它使用 CustomReportSourceResolver 类从数据库获取报告 xml 定义并使用它返回报告源,代码如下)
class CustomReportSourceResolver : IReportSourceResolver
{
public CustomReportSourceResolver(IServiceClass sc, IReportConnectionStringManager csm)
{
userClass = sc;
conStrMan = csm;
//_scopeFactory = sc;
}
private readonly IServiceClass userClass;
private readonly IReportConnectionStringManager conStrMan;
public Telerik.Reporting.ReportSource Resolve(string reportName, OperationOrigin operationOrigin, IDictionary<string, object> currentParameterValues)
{
var report = string.Empty;
if (!string.IsNullOrEmpty(reportName))
{
using (var context = new DataContext(userClass))
{
report = (from table in context.Reports where table.Name == reportName select table.Definition).First();
}
}
ReportSource updatedReport;
if (string.IsNullOrEmpty(report))
{
throw new System.Exception("Unable to load a report with the specified ID: " + reportName);
}
else
{
XmlReportSource retreivedReport = new Telerik.Reporting.XmlReportSource { Xml = report };
updatedReport = conStrMan.UpdateReportSource(retreivedReport);
}
return updatedReport;
}
}
datacontext的代码:
public class DataContext : DbContext
{
public DataContext(IServiceClass sc)
{
serviceClass = sc;
}
private readonly IServiceClass serviceClass;
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(serviceClass.getUserConnectionString().Result);
}
object1..object2.. object3....
}
从上面的代码可以看出,为了通过数据库获取报告,它使用了 datacontext。 Datacontext 具有动态连接字符串,这就是为什么执行会转到服务类中的 getIdentity() 方法,然后我们在主题中获取消息。
您不应该直接在 ServiceClass 服务中注入
AuthenticationStateProvider
。相反,将其注入组件中并将其作为方法参数传递给 GetIdentity。
这就是 Microsoft
ASP.Net Core
文档所说的:
不要尝试在自定义中解决
范围,因为它会导致创建一个新的实例AuthenticationStateProvider
未正确初始化。AuthenticationStateProvider
要访问服务范围内的
组件,将AuthenticationStateProvider
与AuthenticationStateProvider
一起注入 指令或@inject
属性并将其作为 范围。这种方法确保了正确的、初始化的[Inject]
的实例用于每个用户应用程序 实例。AuthenticationStateProvider