Я создал очень простое приложение Blazor, в котором есть BlazorTestApp и BlazorTestApp.Client. Я хочу внедрить HttpClient в BlazortestApp.Client>Pages>Counter.razor.
Ниже приведена упрощенная версия, и я использовал HttpClient в качестве примера, но в реальном сценарии я хочу иметь свой собственный объект для внедрения.
@page "/counter"
@rendermode InteractiveAuto
@inject HttpClient Http
<h1>HttpClient test</h1>
<button class = "btn btn-primary" @onclick = "GetData">Get Data</button>
@code {
private async Task GetData()
{
var url = "https://jsonplaceholder.typicode.com/users/1";
using HttpResponseMessage response = await Http.GetAsync(url);
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
}
}
Я зарегистрировал зависимость в BlazorTestApp.Client>Program.cs.
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
//Registering the HttpClient Dependency
builder.Services.AddScoped(sp => new HttpClient());
await builder.Build().RunAsync();
Когда я перехожу на эту страницу, я получаю следующее исключение.
System.InvalidOperationException: Cannot provide a value for property 'Http' on type 'BlozorTestApp.Client.Pages.Counter'. There is no registered service of type 'System.Net.Http.HttpClient'.
at Microsoft.AspNetCore.Components.ComponentFactory.<>c__DisplayClass9_0.<CreatePropertyInjector>g__Initialize|1(IServiceProvider serviceProvider, IComponent component)
at Microsoft.AspNetCore.Components.ComponentFactory.InstantiateComponent(IServiceProvider serviceProvider, Type componentType, IComponentRenderMode callerSpecifiedRenderMode, Nullable`1 parentComponentId)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateChildComponentOnFrame(RenderTreeFrame[] frames, Int32 frameIndex, Int32 parentComponentId)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(DiffContext& diffContext, Int32 frameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(DiffContext& diffContext, Int32 frameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(DiffContext& diffContext, Int32 newFrameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& diffContext, Int32 oldStartIndex, Int32 oldEndIndexExcl, Int32 newStartIndex, Int32 newEndIndexExcl)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer renderer, RenderBatchBuilder batchBuilder, Int32 componentId, ArrayRange`1 oldTree, ArrayRange`1 newTree)
at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, Exception& renderFragmentException)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
at Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToRenderQueue(Int32 componentId, RenderFragment renderFragment)
at Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged()
at Microsoft.AspNetCore.Components.ComponentBase.CallOnParametersSetAsync()
at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
at Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(ParameterView parameters)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderRootComponentAsync(Int32 componentId, ParameterView initialParameters)
at Microsoft.AspNetCore.Components.HtmlRendering.Infrastructure.StaticHtmlRenderer.BeginRenderingComponent(IComponent component, ParameterView initialParameters)
at Microsoft.AspNetCore.Components.Endpoints.EndpointHtmlRenderer.RenderEndpointComponent(HttpContext httpContext, Type rootComponentType, ParameterView parameters, Boolean waitForQuiescence)
at Microsoft.AspNetCore.Components.Endpoints.RazorComponentEndpointInvoker.RenderComponentCore(HttpContext context)
at Microsoft.AspNetCore.Components.Endpoints.RazorComponentEndpointInvoker.RenderComponentCore(HttpContext context)
at Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.<>c.<<InvokeAsync>b__10_0>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
Если я выполняю регистрацию зависимостей в BlazorTestApp>Program.cs, все работает.
Мой вопрос: поскольку это компонент на стороне клиента (InteractiveAuto или InteractiveWebAssembly), можем ли мы не иметь регистрацию этой зависимости только в BlazorTestApp.Client>program.cs





Я столкнулся с подобной проблемой. В моем случае метод выполнялся дважды: первый раз из серверного проекта, затем из клиентского проекта.
Изменить это
@rendermode InteractiveAuto
к этому:
@rendermode @(new InteractiveAutoRenderMode(prerender: false))
Да, это решает первоначальную проблему, но установка значения false для prerender приводит к тому, что приложение на некоторое время зависает, и это становится очень плохим UX.
rendermode InteractiveAutoобычно отображает компонент в трех разных состояниях: SSR Server Side и Client именно в таком порядке. Даже если у клиента есть загруженный компонент, готовый к использованию Wasm, он все равно сначала будет отображаться на сервере. Методы, которые я использовал, — это внедрение через общий интерфейс с различными реализациями, другой — внедрение самого поставщика услуг, и сервис/компонент корректно определяет доступность ресурса. Используйте конструктор режимов рендеринга Learn.microsoft.com/en-us/aspnet/core/blazor/comComponents/…