Home > front end >  Registering service in Blazor Server application
Registering service in Blazor Server application

Time:01-19

I have following project structure:

  • Project.Server
  • Project.Client
  • Project.Application
  • Porject.Shared

I want to create ExportManager that I would use for exporting data into Excel using closedXML library. So I have created following files into Project.Application:

IExportManager.cs:

  public interface IExportManager
  {
    bool TryExportToExcelFile(DataTable dataTable, string excelTemplatePath, IJSRuntime js, string selectedProjectName, out FileExportErrorInfo errorInfo);
  }

ExportManager.cs:

  public class ExportManager : IExportManager
  {
    /// <summary>
    ///   Method for exporting DataTable to Excel
    /// </summary>
    public bool TryExportToExcelFile(DataTable dataTable, string excelTemplatePath, IJSRuntime js, string selectedProjectName, out FileExportErrorInfo errorInfo)
    {
      errorInfo = null;
      if (string.IsNullOrEmpty(excelTemplatePath))
      {
        return false;
      }

      string worksheetName = "Data";
      WriteToWorkbook(dataTable, excelTemplatePath, worksheetName, js, selectedProjectName, ref errorInfo);
      return errorInfo.State == FileExportErrorState.Successful;
    }

    private static void WriteToWorkbook(DataTable dataTable, string excelTemplatePath, string worksheetName, IJSRuntime js, string selectedProjectName, ref FileExportErrorInfo errorInfo)
    {
      SaveOptions? saveOptions = new SaveOptions()
      {
        EvaluateFormulasBeforeSaving = true,
      };

      using XLWorkbook workbook = File.Exists(excelTemplatePath)
        ? new XLWorkbook(excelTemplatePath)
        : new XLWorkbook();

      ...

      using (MemoryStream stream = new MemoryStream())
      {
        workbook.SaveAs(stream);
        byte[] content = stream.ToArray();

        js.InvokeAsync<object>("saveAsFile", fileName, Convert.ToBase64String(content));
      }
    }
  }

I am then registering this service in Project.Server -> Startup.cs with:

public void ConfigureServices(IServiceCollection services)
{
  services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

  services.AddSingleton<IExportManager, ExportManager>();
}

Then in Project.Client, on a razor page I injecting it with:

[Inject] protected IExportManager ExportManager { get; set; }

Then I am running my application and proceeding to webpage with above injection and getting the following error:

Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] Unhandled exception rendering component: Cannot provide a value for property 'ExportManager' on type 'Project.Client.Pages.Project.Project'. There is no registered service of type 'Project.Application.IExportManager'. System.InvalidOperationException: Cannot provide a value for property 'ExportManager' on type 'Project.Client.Pages.Project.Project'. There is no registered service of type 'Project.Application.IExportManager'. at Microsoft.AspNetCore.Components.ComponentFactory.<>c__DisplayClass7_0.g__Initialize|1(IServiceProvider serviceProvider, IComponent component) at Microsoft.AspNetCore.Components.ComponentFactory.PerformPropertyInjection(IServiceProvider serviceProvider, IComponent instance) at Microsoft.AspNetCore.Components.ComponentFactory.InstantiateComponent(IServiceProvider serviceProvider, Type componentType) at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateComponent(Type componentType) at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateChildComponentOnFrame(RenderTreeFrame& frame, 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)

What I am doing wrong?

P.S. I can try to upload example project to GitHub, if above information is not enough.

This is my Project.Application.csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="ClosedXML" Version="0.95.4" />
    <PackageReference Include="Microsoft.JSInterop" Version="6.0.1" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\BlazingProject\Project.Shared\Project.Shared.csproj" />
  </ItemGroup>

</Project>

CodePudding user response:

The simple answer is you are adding the service in the Server project and then trying to consume it in the client project. The normal answer would be to set the service up in the Client project.

That however wouldn't work. I can see file system operations which won't work on the Client. You need to re-design and use an API call to generate and provide the Workbook from the server.

  •  Tags:  
  • Related