在 blazor 中使用自定义组件时在注入的差异服务中调用 HttpContextAccesor 后为 null

Posted

技术标签:

【中文标题】在 blazor 中使用自定义组件时在注入的差异服务中调用 HttpContextAccesor 后为 null【英文标题】:HttpContextAccesor is null after being called in a difference service where it was inject when using a custom component in blazor 【发布时间】:2021-12-16 10:47:25 【问题描述】:

我已经研究了 blazor 组件的属性飞溅,我没有将它的类定义为继承 ComponentBase,但我已经设置了一些属性字段来分配 html 属性,然后每当注入 HttpContextAccesor 时(它循环 3在第一个服务的构造函数中注入 -4 次,在第二个服务中只注入两次,然后调用该方法以使用第一个服务的 API,然后当它完成并调用第二个服务时,上下文访问器是空

这里定义了自定义组件(子组件)

<input   required="@InputParameters["required"]" max="@InputParameters["max"]" maxlength="@InputParameters["maxlength"]"  
       placeholder="@InputParameters["placeholder"]" size="@InputParameters["min"]"
       value="@InputParameters["value"]" min="@InputParameters["min"]" name="@NameInput"  />

@code 

    [Parameter]
    public Dictionary<string, object> InputParameters  get; set;  = new Dictionary<string, object>
    
        "required","required" ,
        "placeholder","text place holder" ,
        "size", 100 ,
        "maxlength",100 ,
        "max",100 ,
        "min",0 ,
        "value",null 
    ;

    [Parameter]
    public string NameInput  get; set; 


这里是父组件

@page "/EditEmployee/Id:int"
@inherits EditEmployeeBase
@using SharedRazorClassLibrary.Components;
@using EmployeeManagement.Models; 
<h3>EditEmployee</h3>

<label>Time Elapsed: @ElapsedTime </label>
<EditForm Model="Employee" OnValidSubmit="SaveEmployeeDetails" OnInvalidSubmit="CheckErrors">
    <DataAnnotationsValidator />
    <MultiParameterComponent InputParameters="@(new Dictionary<string, object> 
                                                "size",120 ,
                                                "placeholder","Hello",
                                                "maxlength",500 ,
                                                "max",500 ,
                                                "min",1 ,
                                                "value",null 
                                            )" NameInput="CustomMultiInput"></MultiParameterComponent>
    <div class="form-group" row>
        <label for="@Employee.FirstName" class="col-sm-2 col-form-label"> </label>
        <div class="col-sm-10">
            <InputText @bind-Value="Employee.FirstName"></InputText>
            <ValidationMessage For="@(() => Employee.FirstName)" />
        </div>
    </div>
    <div class="form-group" row>
        <label for="@Employee.LastName" class="col-sm-2 col-form-label"></label>
        <div class="col-sm-10">
            <InputText @bind-Value="Employee.LastName"></InputText>
            <ValidationMessage For="@(() => Employee.LastName)" />
        </div>
    </div>

    <div class="form-group" row>
        <label for="@Employee.DepartmentId" class="col-sm-2 col-form-label"></label>
        <div class="col-sm-10">
            <CustomInputSelect @bind-Value="Employee.DepartmentId">
                @foreach (var dept in Departments)
                
                    <option value="@dept.DepartmentId">@dept.DepartmentName</option>
                
            </CustomInputSelect>
            <ValidationMessage For="@(() =>Employee.DepartmentId)" />
        </div>
    </div>
    <div class="form-group">
        <label for="@Employee.Gender"> Gender </label>
        <div class="col-sm-10">
            <CustomInputSelect @bind-Value="Employee.Gender">
                @foreach (var gender in Enum.GetValues(typeof(Gender)))
                
                    <option value="@gender">@gender</option>
                

            </CustomInputSelect>

        </div>
    </div>
    <div class="form-group" row>
        <label for="@Employee.DateOfBirth" class="col-sm-2 col-form-label"></label>
        <div class="col-sm-10">
            <InputDate @bind-Value="Employee.DateOfBirth" @bind-Value:format="dd/MM/YYYY"></InputDate>
        </div>
    </div>
    <div class="form-group">
        <label for="@Employee.Email">Email</label>
        <InputText @bind-Value="@Employee.Email"></InputText>
        <ValidationMessage For="@(()=>Employee.Email)" />
    </div>
    <button type="submit">Submit</button>
    <a href="/DeleteEmployee/@Employee.EmployeeId" @onclick="DeleteEmployee" class="btn btn-danger">Delete</a>

</EditForm>


这里是 Startup 的服务注入

    services.AddRazorPages();
    services.AddServerSideBlazor();
    services.AddAutoMapper((config) => 
        config.AddProfile(typeof(EmployeeProfile));
    );
    services.AddHttpContextAccessor();
    services.AddSingleton<PathHelper>();
    //services.AddScoped<Microsoft.AspNetCore.Http.IHttpContextAccessor, Microsoft.AspNetCore.Http.HttpContextAccessor>();
    services.AddScoped<IEmployeeServices,EmployeeServices>();
    services.AddScoped<IDepartmentServices, DepartmentServices>();
    services.AddHttpClient<IEmployeeServices,EmployeeServices>().ConfigureHttpClient((sp, httpClient) => 
       

    );

所以我想知道是什么原因导致第二个请求使 IHTTPContextAccesor 接口为空?

【问题讨论】:

[礼貌]我看到一个带有MultiParameterComponent 的表单,它看起来不起作用,并且没有绑定到任何东西。然后是关于 HttpContextAccessor 的一个有点乱码的问题。我目前没有看到任何连接。你用 HttpContextAccessor 做什么。它与表格有何联系?我写了很多 Blazor 代码,但我很少使用 HttpContextAccessor 我认为你有一个 XY 问题。您能分享一下您为什么要使用 HttpContextAccessor 吗? @MayurEkbote 我需要知道我是否正在使用 VS 或 VS Code 运行项目,因此上下文访问器让我知道它正在使用哪些端口,如果我删除自定义输入组件它工作正常 @MrCakaShaunCurtis 我不知道,但只有当我将此组件添加到 EditForm 时才会发生这种情况, 所以问题出在MultiParameterComponent。你想用它来实现什么,一个带有一点格式的 Blazor 输入控件不能做?我不是想学究气,只是了解您要达到的目标。 :-) 【参考方案1】:

奇怪的解决方案是按照我在 Startup.cs 中注入的相同顺序注入接口

首先是 HttpClient,然后是 IHpttpContextAccessor,这样 DI 似乎按预期工作,但我将 HttpAccessor 用作 Transient,因为在范围内它在启动时注册服务时会引发异常

【讨论】:

以上是关于在 blazor 中使用自定义组件时在注入的差异服务中调用 HttpContextAccesor 后为 null的主要内容,如果未能解决你的问题,请参考以下文章

Blazor University (45)依赖注入 —— 将依赖项注入 Blazor 组件

如何在 blazor 组件中显示来自后端的自定义引导警报

Blazor 中的依赖注入与 Razor 组件

具有自定义子组件的自定义 Blazor 组件

Blazor 的依赖注入问题

Blazor 中隐藏/非绑定字段的自定义验证