Using API in C# application
In this tutorial, we will show you how you can use Customer's Canvas REST API with a help of official C# API Client. As an example, we will create a simple controller which requests a list of design folders.
It is supposed that you already have an instance of Customer's Canvas set up and running on our infrastructure or your servers.
Preparing
Creating a test project
- In Visual Studio, create a new project, either
ASP.NET Web Application (.NET Framework)
orASP.NET Core Web Application
. - When creating the project, use the
Web API
project template. - Select the 64 bit version of IIS Express:
- On the menu, click Tools > Options > Projects and Solutions > Web Projects.
- Select Use the 64 bit version of IIS Express for web sites and projects.
Installing Nuget packages
The official C# API Client for Customer's Canvas is published in Nuget. Each service has its own package. For the purpose of our tutorial, let's install the Aurigma.AssetStorage.ApiClient
by typing the following command in the Visual Studio Package Manager Console:
Install-Package Aurigma.AssetStorage.ApiClient
Setting Up the Application
The Back-end Services allow you to implement the following authentication approaches:
- Passing Api Keys in the request header.
- Passing tokens in the request header.
- Performing authorization on every request.
- Using a service to cache the authorization result and to monitor the token expiration time.
Now, let's set up the authentication, depending on your framework:
.Net Framework
In our ASP.NET Framework project, we will use Autofac Inversion Of Control container. You can also use other IoC containers instead.
In this project, you need to change Application_Start
in the Global.asax.cs file. At the end of this method, add:
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<HttpClient>()
.AsSelf()
.SingleInstance();
/*
Configure API client authentication here.
*/
var container = builder.Build();
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
Let's learn how you can configure API clients based on different authentication approaches.
1. Configuring a Client with API Keys
For example, define an API key for Aurigma.DesignAtomsApi.ApiClient
.
// Register custom configuration for API clients.
builder.RegisterType<Aurigma.DesignAtomsApi.ApiClientConfiguration>()
.As<Aurigma.DesignAtomsApi.IApiClientConfiguration>()
.InstancePerRequest()
.OnActivating(e => // Set up client configuration in the DI callback.
{
// Specify a DesingAtomsApi service URL.
e.Instance.ApiUrl = "http://localhost:56416/";
// Set up a DesingAtomsApi API key.
e.Instance.ApiKey = "ApiKey";
});
// Register API clients.
builder.RegisterType<DesignAtomsServiceApiClient>()
.As<IDesignAtomsServiceApiClient>();
2. Configuring a Client with Tokens in the Header
This authentication approach is well suited, for example, for communication between services, when AssetProcessor accesses AssetStorage. In the following example, we define a token for Aurigma.AssetProcessor.ApiClient
.
// Register custom configuration for API clients.
builder.RegisterType<Aurigma.AssetProcessor.ApiClientConfiguration>()
.As<Aurigma.AssetProcessor.IApiClientConfiguration>()
.InstancePerRequest()
.OnActivating(e => // Set up client configuration in the DI callback.
{
// Acquire an input token from the request context.
var token = HttpContext.Current?.Request?.Headers["Authorization"]?
.ToString().Replace("Bearer ", "");
// Specify an AssetProcessor service URL.
e.Instance.ApiUrl = "http://localhost:64288/";
// Set up a token.
e.Instance.AuthorizationToken = token;
});
// Register API clients.
builder.RegisterType<DesignProcessorApiClient>()
.As<IDesignProcessorApiClient>();
builder.RegisterType<PrivateDesignProcessorApiClient>()
.As<IPrivateDesignProcessorApiClient>();
3. Configuring a Client with Authorization for a Request.
In this example, authorization is carried out in the SampleAssetStorageApiClientConfiguration.GetToken
method, which is called with each request from a client that uses this configuration.
// Register custom configuration for API clients.
builder.RegisterType<SampleAssetStorageApiClientConfiguration>()
.As<Aurigma.AssetStorage.IApiClientConfiguration>()
.InstancePerRequest()
.OnActivating(e => // Set up client configuration in the DI callback.
{
// Specify an AssetStorage service URL.
e.Instance.ApiUrl = "http://localhost:56416/";
});
// Register API clients.
builder.RegisterType<DesignsApiClient>()
.As<IDesignsApiClient>();
builder.RegisterType<PrivateDesignsApiClient>()
.As<IPrivateDesignsApiClient>();
SampleAssetStorageApiClientConfiguration
implements the Aurigma.AssetStorage.IApiClientConfiguration
interface and uses the IdentityModel client library.
using IdentityModel.Client;
public class SampleAssetStorageApiClientConfiguration : Aurigma.AssetStorage.IApiClientConfiguration
{
private readonly HttpClient _client;
public SampleAssetStorageApiClientConfiguration(HttpClient client)
{
_client = client;
}
// ...
public async Task<string> GetAuthorizationTokenAsync()
{
var tokenResponse = await _client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
// BackOffice Identity Server URL.
Address = "http://localhost:21021/connect/token",
ClientId = "<YOUR CLIENT ID>",
ClientSecret = "<YOUR CLIENT SECRET>"
});
if (tokenResponse.IsError)
{
throw new HttpException((int)HttpStatusCode.InternalServerError, "Could not retrieve token.");
}
return tokenResponse.AccessToken;
}
}
4. Configuring a Client with a Token Service.
This approach is an improved version of the previous one. We implemented CustomAssetStorageApiClientConfiguration
(not included in the ApiClient packages) that allows for defining an arbitrary authorization function in the DI callback. The TokenService
service is also a custom service(not included in the ApiClient packages), Which returns a cached token or makes an authorization request in the GetTokenAsync
method.
// Register TokenService to handle acquiring a token.
builder.RegisterType<TokenService>()
.AsSelf()
.SingleInstance();
// Register custom configuration for API clients.
builder.RegisterType<CustomAssetStorageApiClientConfiguration>()
.As<Aurigma.AssetStorage.IApiClientConfiguration>()
.InstancePerRequest()
.OnActivating(e => // Set up client configuration in the DI callback.
{
var tokenService = e.Context.Resolve<TokenService>();
// Specify an AssetStorage service URL.
e.Instance.ApiUrl = "http://localhost:56416/";
// Set up TokenProvider function using the TokenService.
e.Instance.TokenProvider = () => tokenService.GetTokenAsync();
});
// Register API clients.
builder.RegisterType<DesignsApiClient>()
.As<IDesignsApiClient>();
builder.RegisterType<PrivateDesignsApiClient>()
.As<IPrivateDesignsApiClient>();
ASP.NET Core
For an ASP.NET Core project, change the ConfigureServices
method in Startup.cs. Before adding controllers, paste:
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "http://localhost:21021";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false
};
options.RequireHttpsMetadata = false;
});
/*
Configure API client authentication here.
*/
Let's learn how you can configure API clients based on different authentication approaches.
1. Configuring a Client with API Keys
For example, define an API key for Aurigma.DesignAtomsApi.ApiClient
.
// Register custom configuration for API clients.
// Set up client configuration in the DI callback.
services.AddScoped<Aurigma.DesignAtomsApi.IApiClientConfiguration>(s =>
{
return new Aurigma.DesignAtomsApi.ApiClientConfiguration()
{
// Specify a DesingAtomsApi service URL.
ApiUrl = "http://localhost:56416/";
// Set up a DesingAtomsApi API key.
ApiKey = "ApiKey"
};
});
// Use HttpClientFactory for managing HttpClient lifetime.
services.AddHttpClient<IDesignAtomsServiceApiClient, DesignAtomsServiceApiClient>();
2. Configuring a Client with Tokens in the Header
In this example, we define a token for Aurigma.AssetProcessor.ApiClient
.
services.AddHttpContextAccessor();
// Register custom configuration for API clients.
// Set up client configuration in the DI callback.
services.AddScoped<Aurigma.AssetProcessor.IApiClientConfiguration>(s =>
{
var httpContextAccessor = s.GetRequiredService<IHttpContextAccessor>();
// Acquire an input token from the request context.
var token = httpContextAccessor?.HttpContext?.Request
.Headers["Authorization"].ToString().Replace("Bearer ", "");
return new Aurigma.AssetProcessor.ApiClientConfiguration()
{
// Specify an AssetProcessor service URL.
ApiUrl = "http://localhost:64288/",
// Set up a token.
AuthorizationToken = token
};
});
// Use HttpClientFactory for managing HttpClient lifetime.
services.AddHttpClient<IDesignProcessorApiClient, DesignProcessorApiClient>();
services.AddHttpClient<IPrivateDesignProcessorApiClient, PrivateDesignProcessorApiClient>();
3. Configuring a Client with Authorization for a Request.
In this example, authorization is carried out in the SampleAssetStorageApiClientConfiguration.GetToken
method, which is called with each request from a client that uses this configuration. SampleAssetStorageApiClientConfiguration
implements the Aurigma.AssetStorage.IApiClientConfiguration
interface.
// Set up client configuration in the DI callback.
services.AddScoped<Aurigma.AssetStorage.IApiClientConfiguration>(s =>
{
var httpClientFactory = s.GetRequiredService<IHttpClientFactory>();
// Register custom configuration for API clients.
return new SampleAssetStorageApiClientConfiguration(httpClientFactory)
{
// Specify an AssetStorage service URL.
ApiUrl = "http://localhost:56416/"
};
});
// Use HttpClientFactory for managing HttpClient lifetime.
services.AddHttpClient<IDesignsApiClient, DesignsApiClient>();
services.AddHttpClient<IPrivateDesignsApiClient, PrivateDesignsApiClient>();
4. Configuring a Client with a Token Service.
This approach is an improved version of the previous one. We implemented CustomAssetStorageApiClientConfiguration
(not included in the ApiClient packages) that allows for defining an arbitrary authorization function in the DI callback. The TokenService
service is also a custom service(not included in the ApiClient packages), Which returns a cached token or makes an authorization request in the GetTokenAsync
method.
services.AddHttpClient();
services.AddSingleton<TokenService>();
// Register custom configuration for API clients.
// Set up client configuration in the DI callback.
services.AddScoped<Aurigma.AssetStorage.IApiClientConfiguration>(s =>
{
var tokenService = s.GetRequiredService<TokenService>();
return new CustomAssetStorageApiClientConfiguration()
{
// Specify an AssetStorage service URL.
ApiUrl = "http://localhost:56416/",
// Set up TokenProvider function using the TokenService.
TokenProvider = () => tokenService.GetTokenAsync()
};
});
// Use HttpClientFactory for managing HttpClient lifetime.
services.AddHttpClient<IDesignsApiClient, DesignsApiClient>();
services.AddHttpClient<IPrivateDesignsApiClient, PrivateDesignsApiClient>();
Creating Custom Endpoints
In your client implementation, you can override endpoints of the Back-end services. For following example illustrates how you can use Aurigma.AssetStorage.IDesignsApiClient
to retrieve a list of designs in a specific folder.
public class DefaultController : ControllerBase
{
private readonly IDesignsApiClient _designsClient;
public DefaultController(IDesignsApiClient client)
{
_designsClient = client;
// You can override client settings here if needed, for example:
// var token = HttpContext.Current?.Request?.Headers["Authorization"]?.ToString().Replace("Bearer ", "");
// _client.AuthorizationToken = token;
}
[HttpGet("action")]
public async Task<ActionResult> Action()
{
FolderContentOfDesignDto folderContent = await _designsClient.GetFolderAsync();
// Some actions here...
return Ok();
}
}
In Connecting the Design Editor topic, we will talk about how to connect the Design Editor to the Customer's Canvas Back-end Services.
In the API Reference, you can find details about the AssetStorage API, AssetProcessor API, and DesignAtoms API.