CargoWise eAdapter + .NET: robust integrations for logistics systems

Sep 12, 2025
cargowiseeadapterlogistics.net
0

CargoWise eAdapter is the officially supported gateway for exchanging data with CargoWise. It moves XML messages between CargoWise and external systems using transports like file drop (shared folder/SFTP), email, HTTP/SOAP, and message queues. This post shows practical .NET patterns that ship to production.

Core concepts (quick primer)

  • Message: XML payload that follows CargoWise schemas (XSD). Common objects: Shipment, House, Consignment, Organization, Customs, Events.
  • Direction:
    • Inbound (to CargoWise): place a file/message in a watched location/endpoint; eAdapter validates and loads it.
    • Outbound (from CargoWise): eAdapter emits messages when data changes per your subscriptions.
  • Transports: File drop (local/UNC/SFTP), HTTP/SOAP, SMTP/POP3, MQ. Choose the simplest that meets SLAs and security.
  • Reliability: eAdapter assigns message IDs and generates processing reports/acks. Design for retries and idempotency.
  • Edge workers: Small services (Windows Service, Azure Function, container) that translate between your domain and CW XML.
  • Mappings: Keep transform logic isolated (XSLT or C# mappers). Validate against CargoWise XSDs.
  • Queues: Use Azure Storage Queues/Service Bus for retry, backpressure, and observability.
  • Observability: Correlation ID per message, structured logs, dead-letter queue, replay tools.

Project layout example

src/
  Adapter.Host/           # Windows service or worker
  Adapter.Transforms/     # XSDs, XSLT, mapping code
  Adapter.Contracts/      # POCOs, DTOs
  Adapter.Tests/

Inbound to CargoWise (your system → CW)

Simplest transport: SFTP drop to the eAdapter inbound folder. The worker picks new files and moves them to processing/ after upload completes.

// Adapter.Host/InboundUploader.cs
using System.Net;
using System.Text;
using Renci.SshNet; // SSH.NET

public sealed class InboundUploader
{
    private readonly ConnectionInfo connection;
    private readonly string remoteDropPath; // e.g. /inbound/shipment

    public InboundUploader(string host, int port, string user, string password, string remoteDropPath)
    {
        connection = new ConnectionInfo(host, port, user, new PasswordAuthenticationMethod(user, password));
        this.remoteDropPath = remoteDropPath.TrimEnd('/');
    }

    public void Upload(string fileName, string xmlContents)
    {
        using var client = new SftpClient(connection);
        client.Connect();
        using var ms = new MemoryStream(Encoding.UTF8.GetBytes(xmlContents));
        client.UploadFile(ms, $"{remoteDropPath}/{fileName}");
        client.Disconnect();
    }
}

Transform your DTOs to CargoWise XML using XDocument or XSLT:

// Adapter.Transforms/ShipmentMapper.cs
using System.Xml.Linq;

public static class ShipmentMapper
{
    public static string ToCargoWiseXml(Shipment dto)
    {
        XNamespace ns = "http://www.cargowise.com/Schemas/Universal/2011/11"; // example, confirm version
        var doc = new XDocument(
            new XElement(ns + "UniversalShipment",
                new XElement(ns + "Shipment",
                    new XElement(ns + "ShipmentNumber", dto.Number),
                    new XElement(ns + "Direction", dto.Direction),
                    new XElement(ns + "TransportMode", dto.Mode)
                )
            )
        );
        return doc.ToString(SaveOptions.DisableFormatting);
    }
}

Validate against XSDs (CargoWise supplies them) during tests to catch mapping regressions.

Outbound from CargoWise (CW → your system)

Subscribe to events in eAdapter and consume messages via SFTP/HTTP. In .NET, expose an authenticated HTTP endpoint or poll an inbox.

// Minimal ASP.NET endpoint receiving outbound messages
[ApiController]
[Route("/cargowise/webhook")]
public class CargoWiseWebhookController : ControllerBase
{
    [HttpPost]
    public async Task<IActionResult> Receive()
    {
        using var reader = new StreamReader(Request.Body, Encoding.UTF8);
        var xml = await reader.ReadToEndAsync();
        // TODO: validate signature/IP allowlist
        // Parse XML → upsert into your system
        return Ok();
    }
}

For file-based delivery, schedule a durable fetch:

// Periodic job that downloads files and moves to archive
public async Task<int> DrainOutboundAsync()
{
    var files = await sftp.ListAsync("/outbound/events");
    foreach (var f in files)
    {
        var xml = await sftp.ReadAllTextAsync(f.FullName);
        await handler.ProcessAsync(xml);
        await sftp.MoveAsync(f.FullName, $"/outbound/archive/{f.Name}");
    }
    return files.Count;
}

Error handling & idempotency

  • Idempotency key: Use CW message ID or hash of the business key; reject duplicates.
  • Retries: Exponential backoff; push to DLQ after N attempts.
  • Poison messages: Persist raw XML for triage with reason codes.
  • Ack loops: Ensure you don’t re‑ingest your own outbound copies; separate inbound/outbound roots.

Security checklist

  • SFTP with key auth; restrict to dedicated user; chroot to the drop path.
  • HTTPS webhooks; IP allowlist; HMAC signature.
  • Secrets in GitHub Actions / Azure Key Vault; never commit credentials.

Local & test environments

  • Ask CargoWise for a test company and eAdapter test endpoints.
  • Keep test XSDs and sample payloads under version control.
  • Build a replay harness to feed fixtures into your inbound path.

Monitoring

  • Correlation ID per message; include in all logs/metrics.
  • Emit custom metrics: messages processed, failures, retry counts, end‑to‑end latency.
  • Alert on DLQ growth and consecutive failures.

Deployment

  • For Windows: use WorkerService template with sc.exe or NSSM; set recovery to auto‑restart.
  • For cloud: Azure Functions or container on App Service / ECS with scheduled triggers.
  • Ship configuration as code (JSON/YAML) so new lanes can be added without redeploy.

Quick start checklist

  • Obtain CargoWise schemas and sample messages
  • Choose transport (SFTP vs HTTP) and credentials
  • Map DTOs → CW XML and validate against XSD
  • Implement idempotent inbound + outbound pipelines
  • Add retry/DLQ, structured logging, metrics, and alerts
  • Security hardening (keys, IP allowlist, HMAC)

With a thin, well‑tested .NET adapter and disciplined observability, eAdapter integrations can be both resilient and easy to extend as lanes and partners grow.