Pre-built module services
Each CodeBlock DevKit module documented under Modules (core, supporting, and web client) registers injectable services you can use from your own code: application services, domain services, repositories, and other abstractions exposed as interfaces.
Cross-cutting injectables shared by every host (IRequestDispatcher, ICurrentUser, INotificationService, email/SMS, encryption, files) are summarized in General services.
To see what you can inject for a given area (namespaces, interface names, and typical capabilities), open that module’s Features page in this documentation.
Contract: ISubscriptionService
The Subscription module exposes this interface from CodeBlock.DevKit.Subscription.
- Namespace:
CodeBlock.DevKit.Subscription.Services.Subscriptions
// Copyright (c) CodeBlock.Dev. All rights reserved.
// For more information visit https://codeblock.dev
using CodeBlock.DevKit.Contracts.Dtos;
using CodeBlock.DevKit.Core.Helpers;
using CodeBlock.DevKit.Subscription.Dtos;
namespace CodeBlock.DevKit.Subscription.Services.Subscriptions;
/// <summary>
/// Core service interface for managing subscription operations and business logic.
/// Provides methods for subscription lifecycle management, user access control,
/// and administrative operations with proper result handling and validation.
/// </summary>
public interface ISubscriptionService
{
/// <summary>
/// Retrieves a subscription by its unique identifier.
/// Returns detailed subscription information including computed properties.
/// </summary>
/// <param name="id">Unique identifier of the subscription</param>
/// <returns>Result containing subscription DTO or error information</returns>
Task<Result<GetSubscriptionDto>> GetSubscription(string id);
/// <summary>
/// Gets the total count of all active subscriptions in the system.
/// Used for dashboard metrics and business reporting.
/// </summary>
/// <returns>Result containing the count of active subscriptions</returns>
Task<Result<long>> GetActiveSubscriptionsCount();
/// <summary>
/// Creates a new subscription with the specified parameters.
/// Validates business rules and creates subscription with proper lifecycle events.
/// </summary>
/// <param name="input">DTO containing subscription creation parameters</param>
/// <returns>Result indicating success or failure of subscription creation</returns>
Task<Result<CommandResult>> CreateSubscription(CreateSubscriptionDto input);
/// <summary>
/// Renews an existing subscription by extending its end time.
/// Applies billing cycle rules and updates grace period calculations.
/// </summary>
/// <param name="id">Unique identifier of the subscription to renew</param>
/// <returns>Result indicating success or failure of subscription renewal</returns>
Task<Result<CommandResult>> RenewSubscription(string id);
/// <summary>
/// Searches subscriptions using multiple filter criteria with pagination support.
/// Combines various filters and applies sorting for admin panel usage.
/// </summary>
/// <param name="input">Search criteria and pagination parameters</param>
/// <returns>Result containing paginated subscription results</returns>
Task<Result<SearchOutputDto<GetSubscriptionDto>>> SearchSubscriptions(SearchSubscriptionsInputDto input);
/// <summary>
/// Retrieves all subscriptions for a specific user.
/// Returns subscriptions sorted by creation time for user dashboard display.
/// </summary>
/// <param name="userId">Unique identifier of the user</param>
/// <returns>Result containing user's subscriptions</returns>
Task<Result<IEnumerable<GetSubscriptionDto>>> GetUserSubscriptions(string userId);
/// <summary>
/// Toggles the auto-renewal setting for a subscription.
/// Enables or disables automatic renewal based on current state.
/// </summary>
/// <param name="id">Unique identifier of the subscription</param>
/// <returns>Result indicating success or failure of the toggle operation</returns>
Task<Result<CommandResult>> ToggleAutoRenewal(string id);
/// <summary>
/// Marks a subscription as refunded and disables auto-renewal.
/// Updates subscription status and raises appropriate domain events.
/// </summary>
/// <param name="id">Unique identifier of the subscription</param>
/// <returns>Result indicating success or failure of the status update</returns>
Task<Result<CommandResult>> SetAsRefunded(string id);
/// <summary>
/// Cancels a subscription and disables auto-renewal.
/// Updates subscription status and raises cancellation domain events.
/// </summary>
/// <param name="id">Unique identifier of the subscription</param>
/// <returns>Result indicating success or failure of the cancellation</returns>
Task<Result<CommandResult>> SetAsCanceled(string id);
/// <summary>
/// Reactivates a previously canceled subscription.
/// Enables auto-renewal and raises activation domain events.
/// </summary>
/// <param name="id">Unique identifier of the subscription</param>
/// <returns>Result indicating success or failure of the reactivation</returns>
Task<Result<CommandResult>> SetAsActive(string id);
/// <summary>
/// Retrieves insights about subscription states across the system.
/// Provides aggregated data for dashboard analytics and reporting.
/// </summary>
/// <returns>Result containing subscription state insights</returns>
Task<Result<IEnumerable<GetSubscriptionStateInsightsDto>>> GetSubscriptionStateInsights();
/// <summary>
/// Checks if a user has any active subscription for a specific plan.
/// Considers subscription status, expiration time, and grace period.
/// </summary>
/// <param name="userId">Unique identifier of the user</param>
/// <param name="planId">Identifier of the subscription plan</param>
/// <returns>Result containing true if user has active subscription</returns>
Task<Result<bool>> UserHasAnyActiveSubscription(string userId, string planId);
/// <summary>
/// Checks if a user has any active subscription by plan system name.
/// Alternative method for checking subscriptions using plan system identifiers.
/// </summary>
/// <param name="userId">Unique identifier of the user</param>
/// <param name="planSystemName">System name of the plan to check</param>
/// <returns>Result containing true if user has active subscription</returns>
Task<Result<bool>> UserHasAnyActiveSubscriptionByPlanSystemName(string userId, string planSystemName);
/// <summary>
/// Checks if a user has any active subscription regardless of plan.
/// Used for general access control and feature gating.
/// </summary>
/// <param name="userId">Unique identifier of the user</param>
/// <returns>Result containing true if user has any active subscription</returns>
Task<Result<bool>> UserHasAnyActiveSubscription(string userId);
/// <summary>
/// Returns the active subscription ID for the user.
/// If the user has no active subscription, it returns null.
/// If the user has more than one active subscription, it returns the latest one.
/// </summary>
/// <param name="userId">Unique identifier of the user</param>
/// <returns>Result containing the active subscription ID or null</returns>
Task<Result<string>> GetUserActiveSubscriptionId(string userId);
/// <summary>
/// Gets the active subscription ID for a user and specific plan.
/// Returns the latest active subscription if multiple exist for the same plan.
/// </summary>
/// <param name="userId">Unique identifier of the user</param>
/// <param name="planId">Identifier of the subscription plan</param>
/// <returns>Result containing the active subscription ID or null</returns>
Task<Result<string>> GetUserActiveSubscriptionId(string userId, string planId);
/// <summary>
/// Gets the active subscription ID for a user by plan system name.
/// Alternative method for retrieving subscriptions using plan system identifiers.
/// </summary>
/// <param name="userId">Unique identifier of the user</param>
/// <param name="planSystemName">System name of the plan</param>
/// <returns>Result containing the active subscription ID or null</returns>
Task<Result<string>> GetUserActiveSubscriptionIdByPlanSystemName(string userId, string planSystemName);
}
Example: ISubscriptionService
You can inject ISubscriptionService into UI components, application services, use case handlers, and so on—for example to check whether the current user has an active subscription.
Inject and use in a Blazor page
The template’s admin demo page SubscribedUsersOnly.razor injects ISubscriptionService and calls UserHasAnyActiveSubscription for the signed-in user:
@page "/subscribedusers-only"
@using CodeBlock.DevKit.Subscription.Services.Subscriptions
@inject ISubscriptionService SubscriptionService
<PageTitle>@AdminPanelLocalizer[AdminPanelResource.SubscribedUsersOnly]</PageTitle>
<h1 class="page-title">
@AdminPanelLocalizer[AdminPanelResource.SubscribedUsersOnly]
</h1>
<p class="mb-4 text-muted">
@AdminPanelLocalizer[AdminPanelResource.SubscribedUsersOnlyInfo]
</p>
@if (UserHasAnyActiveSubscription)
{
<div class="alert alert-success">
@AdminPanelLocalizer[AdminPanelResource.ActiveSubscriptionMessage]
</div>
}
else
{
<div class="alert alert-danger">
@AdminPanelLocalizer[AdminPanelResource.NoActiveSubscriptionMessage]
<div class="mt-3">
<a class="btn btn-success" href="/pricing/demo">@AdminPanelLocalizer[AdminPanelResource.ViewAvailablePlans]</a>
</div>
</div>
}
@code {
private bool UserHasAnyActiveSubscription = false;
protected override async Task OnInitializedAsync()
{
await CheckIfUserHasAnyActiveSubscription();
}
private async Task CheckIfUserHasAnyActiveSubscription()
{
var result = await SubscriptionService.UserHasAnyActiveSubscription(CurrentUser.GetUserId());
if (result.IsSuccess)
UserHasAnyActiveSubscription = result.Value;
else
result.ShowErrorToast(ToastService);
}
}
Inject and use in a Use case
The same interface can be injected into a use case handler like below:
using System.Linq;
using CodeBlock.DevKit.Application.Commands;
using CodeBlock.DevKit.Application.Exceptions;
using CodeBlock.DevKit.Contracts.Services;
using CodeBlock.DevKit.Core.Helpers;
using CodeBlock.DevKit.Subscription.Services.Subscriptions;
using MediatR;
namespace CanBeYours.Application.UseCases.Examples;
internal sealed class SampleSubscriptionGatedUseCase
: IRequestHandler<SampleRequest, CommandResult>
{
private readonly ISubscriptionService _subscriptionService;
private readonly ICurrentUser _currentUser;
public SampleSubscriptionGatedUseCase(
ISubscriptionService subscriptionService,
ICurrentUser currentUser)
{
_subscriptionService = subscriptionService;
_currentUser = currentUser;
}
public async Task<CommandResult> Handle(
SampleRequest request,
CancellationToken cancellationToken)
{
var subscriptionResult = await _subscriptionService.UserHasAnyActiveSubscription(
_currentUser.GetUserId());
if (!subscriptionResult.IsSuccess)
throw new ApplicationException(
subscriptionResult.Errors.FirstOrDefault() ?? "Unable to verify subscription.");
if (!subscriptionResult.Value)
throw new ApplicationException("An active subscription is required for this operation.");
// ... your business logic when the user has an active subscription ...
return CommandResult.Create();
}
}
Related architecture topics
- General services —
IRequestDispatcher,ICurrentUser,INotificationService, and other cross-cutting injectables. - Logging — HTTP and sensitive-data logging markers.
- Domain building blocks —
Entity,AggregateRoot, and repository contracts used by module domains.