umbrella-dotnet-scaffold-client-data
Scaffold a client-side HTTP data service implementing an existing IManage<Name>Service interface, following the Umbrella GenericHttpDataService pattern. Registers the service in the client project and
SKILL.md.ai-shared/skills/umbrella-dotnet-scaffold-client-data/SKILL.md
GitHubScaffold Client Data Service
Purpose
Add a client-side HTTP data service to Web\<AppName>.Web.Client.Data\Services\ that implements an existing IManage<Name>Service interface using GenericHttpDataService. This is the transport layer that Blazor client components use to call the API — the same interface that Manage<Name>ControllerService implements on the server side.
Prerequisite: umbrella-dotnet-scaffold-api-data-service-controller must have run first. The service interface (IManage<Name>Service) and server controller service (Manage<Name>ControllerService) must already exist.
This skill also updates the server DI registration from AddScoped to ReplaceScoped, so the server continues to use the direct-repository implementation while the client uses this HTTP implementation.
Discovery (read these before writing anything)
- Read 2–3 existing client data services in
Web\<AppName>.Web.Client.Data\Services\to confirm naming conventions, usings, and the exactApiUrlformat used (e.g."api/ManageIndustry"). - Read
Web\<AppName>.Web.Client.Data\IServiceCollectionExtensions.csto see where to add theAddScopedregistration and how existing services are registered. - Read
Web\<AppName>.Web.Server\IServiceCollectionExtensions.cs— find the// Controller Servicessection to confirm the current registration forIManage<Name>Serviceand whether it is alreadyReplaceScoped.
Step 1 -- Create the client data service
File: Web\<AppName>.Web.Client.Data\Services\Manage<Name>Service.cs
using <AppName>.Web.Client.Data.Services.Abstractions;
using <AppName>.Web.Shared.Models.Api.Manage<Name>;
using Umbrella.Utilities.Data.Pagination;
using Umbrella.Utilities.DataAnnotations.Abstractions;
using Umbrella.Utilities.Http.Abstractions;
namespace <AppName>.Web.Client.Data.Services;
internal sealed class Manage<Name>Service : GenericHttpDataService<
Manage<Name>Model,
int,
SlimManage<Name>Model,
PaginatedResultModel<SlimManage<Name>Model>,
CreateManage<Name>Model,
CreateManage<Name>ResultModel,
UpdateManage<Name>Model,
UpdateManage<Name>ResultModel>, IManage<Name>Service
{
public Manage<Name>Service(
ILogger<Manage<Name>Service> logger,
IGenericHttpService httpService,
IGenericHttpServiceUtility httpServiceUtility,
IUmbrellaValidator validator)
: base(logger, httpService, httpServiceUtility, validator)
{
}
protected override string ApiUrl => "api/Manage<Name>";
}
Rules:
internal sealed class— the service is resolved via the interface; it never needs to be referenced directly outside this assembly.GenericHttpDataServicegeneric params in order (8 total):TModel,TIdentifier,TSlimModel,TPaginatedResultModel,TCreateModel,TCreateResultModel,TUpdateModel,TUpdateResultModel. NoteTModelcomes first (same order asIGenericDataService).ApiUrlmust match the controller's route:[Route("api/[controller]")]resolves to"api/Manage<Name>"— verify against the existing controller.- No additional overrides are needed unless an endpoint uses a non-standard URL segment. Check existing client services to confirm.
Step 2 -- Register in client DI
File: Web\<AppName>.Web.Client.Data\IServiceCollectionExtensions.cs
Add one line in alphabetical order among the other AddScoped service registrations. Preserve unrelated registration order and formatting; do not turn this focused scaffold into a wholesale reordering of an existing section.
_ = services.AddScoped<IManage<Name>Service, Manage<Name>Service>();
Step 3 -- Update server DI registration
File: Web\<AppName>.Web.Server\IServiceCollectionExtensions.cs
Find the existing AddScoped<IManage<Name>Service, Manage<Name>ControllerService>() line added by umbrella-dotnet-scaffold-api-data-service-controller and change it to ReplaceScoped:
// Before:
_ = services.AddScoped<IManage<Name>Service, Manage<Name>ControllerService>();
// After:
_ = services.ReplaceScoped<IManage<Name>Service, Manage<Name>ControllerService>();
This ensures that at server runtime the client's AddScoped registration (loaded when the server bootstraps the client services for SSR pre-rendering) is replaced by the direct-repository implementation.
If the server registration is already ReplaceScoped, skip this step.
Analyzer compatibility
Before finishing, read .ai-shared\bundles\umbrella\analyzer-compatibility.md and build the affected projects with their installed analyzers enabled. Treat diagnostics introduced by the generated or changed code as defects in this workflow.
Verification
- The client service is
internal sealed classinheritingGenericHttpDataServicewith 8 type params in the correct order (same asIGenericDataService). ApiUrlmatches the controller route — confirm against the existing controller file.AddScoped<IManage<Name>Service, Manage<Name>Service>()is present inWeb.Client.Data.IServiceCollectionExtensions.cs.- The server registration for
IManage<Name>Serviceis nowReplaceScoped(notAddScoped). - The implementation imports the namespaces that own
IUmbrellaValidator,IGenericHttpService, andIGenericHttpServiceUtility; do not rely on project-specific global usings unless discovery confirms them.