5.2Interface Definition and Usage

Created on Aug 17, 2026~6 min read

Before using HTTP Declarative Requests, you need to define an interface and make sure it implements the IHttpDeclarative interface:

cs
public interface IHttpService : IHttpDeclarative{}

Then, in the Startup.cs or Program.cs file, configure and register the HttpRemote service to enable the HTTP Declarative Requests feature:

cs
services.AddHttpRemote(builder =>{    // Register the IHttpService declarative interface using the generic approach    builder.AddHttpDeclarative<IHttpService>();    // Or use the type-based approach    // builder.AddHttpDeclarative(typeof(IHttpService));    // To register multiple interfaces, use the following method (not the array syntax shown in this example)    // builder.AddHttpDeclaratives(new[] { typeof(IHttpService), typeof(IHttpService) });    // Recommended: scan and batch-register from assemblies    // builder.AddHttpDeclarativesFromAssemblies([Assembly.GetEntryAssembly()]);    // If using the Furion framework, pass App.Assemblies directly    // builder.AddHttpDeclarativesFromAssemblies(App.Assemblies);});

When using the IHttpService declarative request in a service, you can inject it through the constructor:

cs
public class YourService{    private readonly IHttpService _httpService;    public YourService(IHttpService httpService)    {        _httpService = httpService;    }}

If you are using .NET 8 or later, you can use primary constructors injection to further simplify the code:

cs
public class YourService(IHttpService httpService){    // Use the httpService variable}

In some scenarios, you can also inject only in a specific method by adding the [FromServices] attribute in front of the parameter:

cs
public class YourService{    public Task<string> GetResource([FromServices] IHttpService httpService)    {        // Your business logic    }}

In addition, if you want to dynamically resolve the declarative service, you can first inject IHttpRemoteService and then call its For<T>() method to obtain an instance:

cs
public class YourService(IHttpRemoteService httpRemoteService){    public async Task InvokeAsync()    {        var httpService = httpRemoteService.For<IHttpService>();    }}

Open Generic Interfaces

HTTP declarative interfaces also support open generic definitions, for example:

cs
public interface IHttpService<T> : IHttpDeclarative{}

Note that when using the assembly scanning approach (such as builder.AddHttpDeclarativesFromAssemblies(assemblies)), open generic interfaces are skipped by default, because it requires a concrete type at runtime (that is, a closed generic type). In this case, you should explicitly register the closed generic version:

cs
services.AddHttpRemote(builder =>{    // Register a closed generic type, such as IHttpService<string>    builder.AddHttpDeclarative<IHttpService<string>>();    // Or use the type-based approach    // builder.AddHttpDeclarative(typeof(IHttpService<string>));});

When using it in business logic, you can obtain the specified closed type (such as IHttpService<string>) directly through dependency injection, or call IHttpRemoteService.For<IHttpService<string>>() to dynamically resolve the service instance.

No Need to Implement the IHttpDeclarative Interface

In some cases, you may want to generate a declarative proxy directly for an ordinary interface without requiring that interface to implement IHttpDeclarative. For example, define an ordinary IMyApi interface:

cs
public interface IMyApi{    [Get("https://api.furion.net/users/{id}")]    Task<User> GetUserAsync(int id);}

In this case, specify requireIHttpDeclarative: false when registering:

cs
services.AddHttpRemote(builder =>{    builder.AddHttpDeclarative(typeof(IMyApi), requireIHttpDeclarative: false);});

After registration, this interface is used in exactly the same way as an ordinary declarative interface: it can be injected through the constructor, injected with the [FromServices] attribute, or dynamically resolved with IHttpRemoteService.For<T>().