Please ensure Javascript is enabled for purposes of website accessibility
Powered by Zoomin Software. For more details please contactZoomin

AVEVA™ Integration Service

ASP​.NET Core Integration

  • Last UpdatedJul 28, 2026
  • 4 minute read

This section covers integrating the AVEVA Integration Service Data API SDK into ASP.NET Core applications using dependency injection, health checks, Serilog, and middleware.

Setup

Project Dependencies

dotnet add package AVEVA.IntegrationService.DataAPI.SDK

dotnet add package Microsoft.Extensions.Http

dotnet add package Serilog.AspNetCore

Minimum .NET Version

.NET 5.0 or later

Dependency Injection

Register SDK in Program.cs

// Program.cs (.NET 6+)

var builder = WebApplication.CreateBuilder(args);

// Register all DataAPI services via extension method

builder.Services.AddDataApiServices(builder.Configuration);

var app = builder.Build();

app.Run();

Extension Method

// Extensions/DataApiServiceCollectionExtensions.cs

public static class DataApiServiceCollectionExtensions

{

public static IServiceCollection AddDataApiServices(

this IServiceCollection services,

IConfiguration configuration)

{

var host = configuration["DataApi:Host"];

if (string.IsNullOrEmpty(host))

throw new InvalidOperationException("DataApi:Host configuration is required");

services.Configure<DataApiOptions>(configuration.GetSection("DataApi"));

services.AddScoped<IDataApiClientFactory, DataApiClientFactory>();

services.AddScoped<IEngineeringDataService, EngineeringDataService>();

services.AddScoped<IExcelDataService, ExcelDataService>();

services.AddHttpClient();

return services;

}

}

DataApiClientFactory for DI

public interface IDataApiClientFactory

{

EngineeringClient CreateEngineeringClient();

ExcelClient CreateExcelClient();

}

public class DataApiClientFactory : IDataApiClientFactory

{

private readonly DataApiOptions _options;

public DataApiClientFactory(IOptions<DataApiOptions> options)

{

_options = options.Value;

}

public EngineeringClient CreateEngineeringClient()

{

var authType = _options.AuthenticationType == "Connect"

? AuthenticationType.Connect

: AuthenticationType.NTLM;

return DataApiClientFactory.CreateDataApiClient<EngineeringClient>(

host: _options.Host,

authType: authType,

token: _options.AccessToken ?? "");

}

public ExcelClient CreateExcelClient()

{

var authType = _options.AuthenticationType == "Connect"

? AuthenticationType.Connect

: AuthenticationType.NTLM;

return DataApiClientFactory.CreateDataApiClient<ExcelClient>(

host: _options.Host,

authType: authType,

token: _options.AccessToken ?? "");

}

}

Configuration Class

public class DataApiOptions

{

public string Host { get; set; }

public string AuthenticationType { get; set; } = "NTLM";

public string AccessToken { get; set; }

public int TimeoutMinutes { get; set; } = 60;

public int RetryAttempts { get; set; } = 3;

}

Configuration

appsettings.json

{

"Logging": {

"LogLevel": {

"Default": "Information",

"AVEVA": "Debug"

}

},

"DataApi": {

"Host": "https://your-ais-server/api/v1/datasources",

"AuthenticationType": "NTLM",

"TimeoutMinutes": 60,

"RetryAttempts": 3

}

}

Environment-Specific

// appsettings.Development.json

{

"DataApi": {

"Host": "https://localhost:44301/api/v1/datasources"

}

}

// appsettings.Production.json

{

"DataApi": {

"Host": "https://ais-prod.empresa.com/api/v1/datasources",

"AuthenticationType": "Connect"

}

}

Secure Token Storage

// Azure Key Vault

builder.Configuration.AddAzureKeyVault(

new Uri($"https://{keyVaultName}.vault.azure.net/"),

new DefaultAzureCredential());

// User Secrets (Development only)

builder.Configuration.AddUserSecrets<Program>();

Service Implementation

Engineering Data Service

public interface IEngineeringDataService

{

Task<IEnumerable<DatasourceDto>> GetDataSourcesAsync();

Task<IEnumerable<Table>> GetTablesAsync(string datasourceName);

Task<IEnumerable<TableData>> GetTableDataAsync(string datasourceName, string tableName);

}

public class EngineeringDataService : IEngineeringDataService

{

private readonly IDataApiClientFactory _clientFactory;

private readonly ILogger<EngineeringDataService> _logger;

public EngineeringDataService(

IDataApiClientFactory clientFactory,

ILogger<EngineeringDataService> logger)

{

_clientFactory = clientFactory;

_logger = logger;

}

public async Task<IEnumerable<DatasourceDto>> GetDataSourcesAsync()

{

try

{

_logger.LogInformation("Retrieving data sources");

var client = _clientFactory.CreateEngineeringClient();

return await client.GetDataSources("");

}

catch (Exception ex)

{

_logger.LogError(ex, "Error retrieving data sources");

throw;

}

}

public async Task<IEnumerable<Table>> GetTablesAsync(string datasourceName)

{

try

{

_logger.LogInformation("Retrieving tables for {DatasourceName}", datasourceName);

var client = _clientFactory.CreateEngineeringClient();

return await client.GetTables(datasourceName, "");

}

catch (Exception ex)

{

_logger.LogError(ex, "Error retrieving tables for {DatasourceName}", datasourceName);

throw;

}

}

public async Task<IEnumerable<TableData>> GetTableDataAsync(

string datasourceName, string tableName)

{

try

{

_logger.LogInformation("Retrieving data for {DatasourceName}.{TableName}",

datasourceName, tableName);

var client = _clientFactory.CreateEngineeringClient();

return await client.GetTableData(datasourceName, tableName, "");

}

catch (Exception ex)

{

_logger.LogError(ex, "Error retrieving data for {DatasourceName}.{TableName}",

datasourceName, tableName);

throw;

}

}

}

Controllers

REST API Controller

[ApiController]

[Route("api/[controller]")]

public class DataSourcesController : ControllerBase

{

private readonly IEngineeringDataService _dataService;

private readonly ILogger<DataSourcesController> _logger;

public DataSourcesController(

IEngineeringDataService dataService,

ILogger<DataSourcesController> logger)

{

_dataService = dataService;

_logger = logger;

}

[HttpGet("datasources")]

public async Task<ActionResult<IEnumerable<DatasourceDto>>> GetDataSources()

{

try

{

var dataSources = await _dataService.GetDataSourcesAsync();

return Ok(dataSources);

}

catch (TimeoutException ex)

{

_logger.LogWarning(ex, "Request timeout");

return StatusCode(StatusCodes.Status504GatewayTimeout,

new { message = "Request timed out" });

}

catch (Exception ex)

{

_logger.LogError(ex, "Error retrieving data sources");

return StatusCode(StatusCodes.Status500InternalServerError,

new { message = "An error occurred" });

}

}

[HttpGet("tables/{datasourceName}")]

public async Task<ActionResult<IEnumerable<Table>>> GetTables(string datasourceName)

{

try

{

var tables = await _dataService.GetTablesAsync(datasourceName);

return Ok(tables);

}

catch (Exception ex)

{

_logger.LogError(ex, "Error retrieving tables for {DatasourceName}", datasourceName);

return BadRequest(new { message = ex.Message });

}

}

[HttpGet("data/{datasourceName}/{tableName}")]

public async Task<ActionResult<IEnumerable<TableData>>> GetTableData(

string datasourceName, string tableName)

{

try

{

var data = await _dataService.GetTableDataAsync(datasourceName, tableName);

return Ok(data);

}

catch (Exception ex)

{

_logger.LogError(ex, "Error retrieving data");

return BadRequest(new { message = ex.Message });

}

}

}

Health Checks

Register Health Check

// Program.cs

builder.Services

.AddHealthChecks()

.AddCheck<DataApiHealthCheck>("dataapi");

var app = builder.Build();

app.MapHealthChecks("/health");

DataApiHealthCheck Implementation

public class DataApiHealthCheck : IHealthCheck

{

private readonly DataApiOptions _options;

public DataApiHealthCheck(IOptions<DataApiOptions> options)

{

_options = options.Value;

}

public async Task<HealthCheckResult> CheckHealthAsync(

HealthCheckContext context,

CancellationToken cancellationToken = default)

{

try

{

var healthClient = HealthCheckClientFactory.CreateHealthCheckClient(new HttpClient());

var status = await healthClient.HealthCheckAPI(_options.Host);

return status == System.Net.HttpStatusCode.OK

? HealthCheckResult.Healthy("DataAPI is healthy")

: HealthCheckResult.Unhealthy($"DataAPI returned {status}");

}

catch (Exception ex)

{

return HealthCheckResult.Unhealthy($"DataAPI check failed: {ex.Message}", ex);

}

}

}

Logging

Configure Serilog

// Program.cs

Log.Logger = new LoggerConfiguration()

.MinimumLevel.Information()

.WriteTo.Console()

.WriteTo.File(

"logs/app-.txt",

rollingInterval: RollingInterval.Day,

outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}")

.Enrich.FromLogContext()

.CreateLogger();

try

{

var builder = WebApplication.CreateBuilder(args);

builder.Host.UseSerilog();

// ...

var app = builder.Build();

app.Run();

}

catch (Exception ex)

{

Log.Fatal(ex, "Application terminated unexpectedly");

}

finally

{

Log.CloseAndFlush();

}

Structured Logging Examples

_logger.LogInformation(

"Retrieved {Count} data sources from {Host}",

dataSources.Count(), _options.Host);

_logger.LogError(ex,

"Failed to retrieve data from {DatasourceName}", datasourceName);

Error Handling

Global Exception Handler Middleware

public class DataApiExceptionHandlerMiddleware

{

private readonly RequestDelegate _next;

private readonly ILogger<DataApiExceptionHandlerMiddleware> _logger;

public DataApiExceptionHandlerMiddleware(

RequestDelegate next,

ILogger<DataApiExceptionHandlerMiddleware> logger)

{

_next = next;

_logger = logger;

}

public async Task InvokeAsync(HttpContext context)

{

try

{

await _next(context);

}

catch (Exception ex)

{

_logger.LogError(ex, "Unhandled exception occurred");

await HandleExceptionAsync(context, ex);

}

}

private static Task HandleExceptionAsync(HttpContext context, Exception exception)

{

context.Response.ContentType = "application/json";

var response = new

{

message = exception.Message,

statusCode = context.Response.StatusCode

};

return context.Response.WriteAsJsonAsync(response);

}

}

// Register in Program.cs

app.UseMiddleware<DataApiExceptionHandlerMiddleware>();

Per-Endpoint Error Handling

[HttpGet("data")]

public async Task<ActionResult<DataResponse>> GetData()

{

try

{

var data = await _service.GetDataAsync();

return Ok(data);

}

catch (HubConnectionInitializationException)

{

return StatusCode(StatusCodes.Status503ServiceUnavailable,

new { message = "Data service is temporarily unavailable" });

}

catch (TimeoutException)

{

return StatusCode(StatusCodes.Status504GatewayTimeout,

new { message = "Request timed out" });

}

catch (Exception ex)

{

return StatusCode(StatusCodes.Status500InternalServerError,

new { message = "An unexpected error occurred" });

}

}

Complete Example: Web API

// Program.cs

using Serilog;

Log.Logger = new LoggerConfiguration()

.MinimumLevel.Information()

.WriteTo.Console()

.WriteTo.File("logs/app-.txt", rollingInterval: RollingInterval.Day)

.CreateLogger();

var builder = WebApplication.CreateBuilder(args);

builder.Host.UseSerilog();

builder.Services

.AddControllers();

builder.Services

.AddDataApiServices(builder.Configuration);

builder.Services

.AddHealthChecks()

.AddCheck<DataApiHealthCheck>("dataapi");

builder.Services.AddCors(options =>

options.AddPolicy("AllowAll", b =>

b.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader()));

var app = builder.Build();

app.UseHttpsRedirection();

app.UseCors("AllowAll");

app.MapControllers();

app.MapHealthChecks("/health");

app.Run();

In This Topic
Related Links