I have looked into attribute splatting for a blazor component,which I havent defined its class as inheriting ComponentBase, but I have set up some property field to assign the html attributes, and then whenever the HttpContextAccesor is injected(it loops through 3-4 times to be injected within the first services' constructor and only twice in the second service both, and then the method is called to consume an API from the first service, then when it finishes and the second Service is called the Context accessor is null
here is defined the custom component (child component )
<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; }
}
here is the parent component
@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 row>
<label for="@Employee.FirstName" > </label>
<div >
<InputText @bind-Value="Employee.FirstName"></InputText>
<ValidationMessage For="@(() => Employee.FirstName)" />
</div>
</div>
<div row>
<label for="@Employee.LastName" ></label>
<div >
<InputText @bind-Value="Employee.LastName"></InputText>
<ValidationMessage For="@(() => Employee.LastName)" />
</div>
</div>
<div row>
<label for="@Employee.DepartmentId" ></label>
<div >
<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 >
<label for="@Employee.Gender"> Gender </label>
<div >
<CustomInputSelect @bind-Value="Employee.Gender">
@foreach (var gender in Enum.GetValues(typeof(Gender)))
{
<option value="@gender">@gender</option>
}
</CustomInputSelect>
</div>
</div>
<div row>
<label for="@Employee.DateOfBirth" ></label>
<div >
<InputDate @bind-Value="Employee.DateOfBirth" @bind-Value:format="dd/MM/YYYY"></InputDate>
</div>
</div>
<div >
<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" >Delete</a>
</EditForm>
here are the Startup's service injection
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) => {
});
so I wonder what could be causing that the second request makes the IHTTPContextAccesor interface to be null?
CodePudding user response:
The odd solution was injecting the Interface in the same order i had injeccted it
first the HttpClient and then the IHpttpContextAccessor this way the DI seemed to work as expected, tho I am using the HttpAccessor as Transient because as scoped it throws an exception when it register the service at startup