Table of Contents
Last updated: 6/17/2026

Development kits


ShareAspace is delivered with a set of development kits (DevKits) that support the implementation of extensions, integrations, and custom logic. These DevKits are distributed as NuGet packages and are intended to be referenced from custom projects during development.

Each DevKit targets a specific extension scenario, such as external events, tasks, validations, or mapping logic. The table below provides an overview of the available DevKits and their intended use.

Available development kits


Dev kit Description
Eurostep.ModelFramework.DevKit.Mapping.1.9.0.xyz.nupkg Development kit for the ShareAspace mapping framework (see Mapping framework)
Eurostep.ModelFramework.DevKit.Mapping.Testing.1.9.0.xyz.nupkg Development kit for building unit tests against mapping implemented using the ShareAspace mapping framework.
Eurostep.ModelFramework.DevKit.Toolbox.1.9.0.xyz.nupkg Development kit for the ShareAspace SoftType toolbox.
Eurostep.SAS.DevKit.External.Extension.1.9.0.xyz.nupkg Development kit with convenience libraries for using the ShareAspace REST APIs.
Eurostep.SAS.DevKit.External.Extension.ExternalEvent.1.9.0.xyz.nupkg Development kit for implementing external event handlers (see External extensions)
Eurostep.SAS.DevKit.External.Extension.ExternalTask.1.9.0.xyz.nupkg Development kit for implementing external tasks (see External extensions)
Eurostep.SAS.DevKit.External.Extension.ExternalValidation.1.9.0.xyz.nupkg Development kit for implementing external event validators (see External extensions)
Eurostep.SAS.DevKit.External.Extension.FileConverter.1.9.0.xyz.nupkg Development kit for implementing CAD conversion.
Eurostep.SAS.DevKit.External.Extension.FilePreview.1.9.0.xyz.nupkg Development kit for implementing custom file preview generators (see External extensions)
Eurostep.SAS.DevKit.External.Extension.FullTextIndexing.1.9.0.xyz.nupkg Development kit for implementing custom full text indexing (see External extensions)
Eurostep.SAS.DevKit.External.Extension.FullTextSearch.1.9.0.xyz.nupkg Development kit for implementing custom full text search (see External extensions)
Eurostep.SAS.DevKit.External.Extension.Mail.1.9.0.xyz.nupkg Development kit for implementing custom email handling (see External extensions)
Eurostep.SAS.DevKit.External.Logging.ShareAspace.1.9.0.xyz.nupkg Development kit for for reporting extension log information back to ShareAspace. (see External extensions)

OpenTelemetry (OTEL) and Application Insights in custom extension


ShareAspace provides built‑in support for OpenTelemetry (OTEL) for logging, tracing, and metrics. When developing custom external extensions, it is recommended to use the same telemetry stack to ensure consistent observability and integration with the ShareAspace platform.

For .NET‑based external extensions, OpenTelemetry can be enabled by adding the required NuGet dependencies and configuring the application during startup. The same configuration can optionally be extended to export telemetry data to Azure Application Insights.

Required NuGet packages

<PackageReference Include="Azure.Monitor.OpenTelemetry.AspNetCore" />

<PackageReference Include="Microsoft.Extensions.Http.Resilience" />
<PackageReference Include="Microsoft.Extensions.ServiceDiscovery" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" />
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" />

These packages enable:

  • OTEL logging, tracing, and metrics.
  • Automatic instrumentation for ASP.NET Core, HTTP clients, and runtime metrics.
  • Export of telemetry data via the OTLP protocol.
  • Optional export to Azure Monitor / Application Insights.

Configuring OpenTelemetry in an external extension

The following example demonstrates how to enable OpenTelemetry in an external extension that uses the ExternalEvent DevKit. The configuration is encapsulated in reusable extension methods that can be shared across multiple services.

Common service defaults and OpenTelemetry configuration

Add the following helper class to your solution. It configures logging, metrics, tracing, health checks, and OTLP or Azure Monitor exporters based on configuration.

using Azure.Monitor.OpenTelemetry.AspNetCore;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using OpenTelemetry.Exporter;
using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
using System.Security.Cryptography.X509Certificates;

namespace Microsoft.Extensions.Hosting;

// Adds common .NET Aspire services: service discovery, resilience, health checks, and OpenTelemetry.
// This project should be referenced by each service project in your solution.
// To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults
public static class Extensions
{
    public static IHostApplicationBuilder AddServiceDefaults(this IHostApplicationBuilder builder)
    {
        builder.ConfigureOpenTelemetry();

        builder.AddDefaultHealthChecks();

        builder.Services.AddServiceDiscovery();

        builder.Services.ConfigureHttpClientDefaults(http =>
        {
            // Turn on resilience by default
            http.AddStandardResilienceHandler();

            // Turn on service discovery by default
            http.AddServiceDiscovery();
        });

        return builder;
    }

    public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicationBuilder builder)
    {
        builder.Logging.ClearProviders();
        builder.Logging.AddOpenTelemetry(logging =>
        {
            logging.IncludeFormattedMessage = true;
            logging.IncludeScopes = true;
        });

        builder.Services.AddOpenTelemetry()
            .WithMetrics(metrics =>
            {
                metrics.AddAspNetCoreInstrumentation()
                    .AddHttpClientInstrumentation()
                    .AddRuntimeInstrumentation();
            })
            .WithTracing(tracing =>
            {
                tracing.AddAspNetCoreInstrumentation()
                    // Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package)
                    //.AddGrpcClientInstrumentation()
                    .AddHttpClientInstrumentation();
            });

        builder.AddOpenTelemetryExporters();

        return builder;
    }

    private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder)
    {
        var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]);
        var useOtlpClientCert = !string.IsNullOrWhiteSpace(builder.Configuration["X_OTEL_EXPORTER_OTLP_CLIENT_PFX"]);
        var otlpClientCert = builder.Configuration["X_OTEL_EXPORTER_OTLP_CLIENT_PFX"];
        var otlpClientPassword = builder.Configuration["X_OTEL_EXPORTER_OTLP_CLIENT_PASSWORD"];

        X509Certificate2? clientCertificate = null;

        if (useOtlpExporter)
        {
            var openTelemetryBuilder = builder.Services.AddOpenTelemetry();

            if (useOtlpClientCert)
            {
                clientCertificate = X509CertificateLoader.LoadPkcs12FromFile(otlpClientCert, otlpClientPassword);
            }


            openTelemetryBuilder.WithLogging(b => b.AddOtlpExporter(opt => opt.HttpClientFactory =
                HttpClientFactoryWithClientCertOptional(useOtlpClientCert, clientCertificate, opt)));

            openTelemetryBuilder.WithMetrics(b => b.AddOtlpExporter(opt => opt.HttpClientFactory =
                HttpClientFactoryWithClientCertOptional(useOtlpClientCert, clientCertificate, opt)));

            openTelemetryBuilder.WithTracing(b => b.AddOtlpExporter(opt => opt.HttpClientFactory =
                HttpClientFactoryWithClientCertOptional(useOtlpClientCert, clientCertificate, opt)));

            if (useOtlpClientCert)
            {
                builder.Services.AddHttpClient("OtlpTraceExporter", (provider, client) => { })
                    .ConfigurePrimaryHttpMessageHandler(() => CreateClientCertEnabledHandler(clientCertificate));

                builder.Services.AddHttpClient("OtlpMetricExporter", (provider, client) => { })
                    .ConfigurePrimaryHttpMessageHandler(() => CreateClientCertEnabledHandler(clientCertificate));
            }
        }

        if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]))
        {
            builder.Services.AddOpenTelemetry()
               .UseAzureMonitor();
        }

        return builder;
    }

    private static Func<HttpClient> HttpClientFactoryWithClientCertOptional(bool useOtlpClientCert,
        X509Certificate2? clientCertificate, OtlpExporterOptions opt)
    {
        return () =>
        {
            var handler = useOtlpClientCert
                ? CreateClientCertEnabledHandler(clientCertificate)
                : new HttpClientHandler();

            return new HttpClient(handler) { Timeout = TimeSpan.FromMilliseconds(opt.TimeoutMilliseconds) };
        };
    }

    private static HttpMessageHandler CreateClientCertEnabledHandler(X509Certificate cert)
    {
        var handler = new HttpClientHandler();
        handler.ClientCertificates.Add(cert);
        handler.ClientCertificateOptions = ClientCertificateOption.Automatic;

        return handler;
    }

    public static IHostApplicationBuilder AddDefaultHealthChecks(this IHostApplicationBuilder builder)
    {
        builder.Services.AddHealthChecks()
            // Add a default liveness check to ensure app is responsive
            .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);

        return builder;
    }
}

This setup ensures:

  • Logs are emitted through OpenTelemetry instead of default .NET logging providers.
  • Metrics and traces are automatically collected.
  • Exporters are enabled based on configuration values.

Enabling telemetry in the extension startup

Once the service defaults are defined, enable them in the extension’s startup code by calling AddServiceDefaults() on the application builder.

Example startup configuration for an external extension:

using Eurostep.SAS.External.Extension;
using Microsoft.AspNetCore.Server.Kestrel.Core;

var builder = WebApplication.CreateBuilder();

builder.AddServiceDefaults();

var services = builder.Services;

services.AddRouting();

services.AddHttpClient();
services.AddNovaExternalExtensions();

var app = builder.Build();
var env = builder.Environment;

app.UseForwardedHeaders();

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseHsts();
}

app.UseNovaExternalExtensions("");

await app.RunAsync();

Configuration using OTLP (ShareAspace OTEL collector)

Telemetry exporters are configured using standard OpenTelemetry environment variables. The following example shows a typical appsettings.json configuration when exporting telemetry data to the ShareAspace OTEL collector (or other OTEL collector).

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "NovaConfig": {
    "SymmetricKey": "_APISYMKEY_"
  },

  "OTEL_SERVICE_NAME": "My.Custom.Extension",
  "OTEL_EXPORTER_OTLP_ENDPOINT": "_OTELCOLLECTORGRPCURI_",
  "OTEL_EXPORTER_OTLP_PROTOCOL": "grpc",

  "OTEL_DOTNET_EXPERIMENTAL_ASPNETCORE_DISABLE_URL_QUERY_REDACTION": "true",
  "OTEL_DOTNET_EXPERIMENTAL_HTTPCLIENT_DISABLE_URL_QUERY_REDACTION": "true",
  "OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES": "true",
  "OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES": "true",
  "OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY": "in_memory"
}

When these settings are present, the extension exports logs, metrics, and traces to the configured OTLP endpoint.

Using Azure Application Insights instead of OTLP

If you want to send telemetry data to Azure Application Insights instead of the ShareAspace OTEL file logger and collector, replace the OTLP‑specific settings with an Application Insights connection string.

Remove the following settings:

  "OTEL_EXPORTER_OTLP_ENDPOINT": "_OTELCOLLECTORGRPCURI_",
  "OTEL_EXPORTER_OTLP_PROTOCOL": "grpc",

  "OTEL_DOTNET_EXPERIMENTAL_ASPNETCORE_DISABLE_URL_QUERY_REDACTION": "true",
  "OTEL_DOTNET_EXPERIMENTAL_HTTPCLIENT_DISABLE_URL_QUERY_REDACTION": "true",
  "OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES": "true",
  "OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES": "true",
  "OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY": "in_memory"

And add the following setting instead:

"APPLICATIONINSIGHTS_CONNECTION_STRING": "InstrumentationKey=REDACTED;IngestionEndpoint=REDACTED;LiveEndpoint=REDACTED;ApplicationId=REDACTED"

When this connection string is present, the Azure Monitor OpenTelemetry exporter is automatically enabled, and all telemetry data is sent to Application Insights.