SOAP SvcUtil Sample
The ECGrid-SOAP-dotnet10-Console-SvcUtil project demonstrates calling the ECGridOS SOAP API using a typed client proxy generated by dotnet-svcutil. The generated proxy provides strongly typed method signatures and response objects, eliminating manual XML construction.
:::caution Established API The ECGridOS SOAP API is in maintenance mode. For new integrations, use the REST API instead. This sample is provided for teams maintaining or migrating existing SOAP-based integrations. :::
Project Location
samples/soap/ECGrid-SOAP-dotnet10-Console-SvcUtil/
What It Demonstrates
- Generating a typed WCF-compatible proxy from the ECGridOS WSDL using
dotnet-svcutil - Calling SOAP methods as strongly typed
asyncmethods - Session lifecycle:
LoginAsync→ operations →LogoutAsync - Operations covered:
LoginAsync,ParcelInBoxAsync,ParcelDownloadAsync,ParcelDownloadConfirmAsync,LogoutAsync
Key Files
| File | Purpose |
|---|---|
Program.cs | Entry point — full session workflow using the generated proxy |
Reference/ | Generated proxy code produced by dotnet-svcutil (do not edit manually) |
appsettings.json | Login credentials |
Regenerating the Proxy
The generated proxy in Reference/ was created from the ECGridOS WSDL. If the WSDL changes, regenerate it with:
# Install the tool globally (one-time)
dotnet tool install -g dotnet-svcutil
# Regenerate from the live WSDL — run from the project directory
dotnet-svcutil https://os.ecgrid.io/v4.1/prod/ECGridOS.asmx?WSDL --outputDir Reference
This produces a Reference.cs file and updates the project's NuGet references for System.ServiceModel.
Commit the generated Reference/ files to source control so that other developers can build without running dotnet-svcutil. Regenerate only when the WSDL changes.
Key Patterns
Client Instantiation
// The generated proxy class is typically named ECGridOSSoapClient
// Endpoint address matches the live ECGridOS service
var binding = new BasicHttpsBinding();
var endpoint = new EndpointAddress("https://os.ecgrid.io/v4.1/prod/ECGridOS.asmx");
await using var client = new ECGridOSSoapClient(binding, endpoint);
Session Lifecycle
// Program.cs — .NET 10 top-level statements
// Load credentials from IConfiguration — never hardcoded
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddUserSecrets<Program>()
.Build();
var binding = new BasicHttpsBinding();
var endpoint = new EndpointAddress("https://os.ecgrid.io/v4.1/prod/ECGridOS.asmx");
await using var client = new ECGridOSSoapClient(binding, endpoint);
// --- Login ---
// LoginAsync returns a typed SessionInfo object; the SessionID is used for all subsequent calls
var loginResult = await client.LoginAsync(
config["ECGridOS:Login"]!,
config["ECGridOS:Password"]!);
var sessionId = loginResult.SessionID;
// --- Check inbox ---
var inboxResult = await client.ParcelInBoxAsync(
sessionId,
int.Parse(config["ECGridOS:MailboxId"]!));
// ParcelInBoxAsync returns an array of ParcelIDInfo objects
foreach (var parcel in inboxResult ?? [])
{
// --- Download parcel ---
// ParcelDownloadAsync returns the EDI file content as a base64-encoded byte array
var downloadResult = await client.ParcelDownloadAsync(sessionId, parcel.ParcelID);
if (downloadResult?.Content is { Length: > 0 } content)
{
await File.WriteAllBytesAsync($"parcel-{parcel.ParcelID}.edi", content);
// --- Confirm download ---
// Must be called to mark the parcel as delivered in ECGrid
await client.ParcelDownloadConfirmAsync(sessionId, parcel.ParcelID);
Console.WriteLine($"Parcel {parcel.ParcelID} downloaded and confirmed.");
}
}
// --- Logout ---
// Always logout to release the session on the server
await client.LogoutAsync(sessionId);
Console.WriteLine("Done.");
Error Handling
// Wrap SOAP calls in try/catch for FaultException to handle SOAP faults gracefully
try
{
var result = await client.ParcelDownloadAsync(sessionId, parcelId);
}
catch (FaultException<ECGridOSFault> fault)
{
// ECGridOS-specific error details are in the fault detail
Console.Error.WriteLine($"ECGridOS error {fault.Detail.ErrorCode}: {fault.Detail.ErrorString}");
}
catch (CommunicationException ex)
{
// Network or channel errors
Console.Error.WriteLine($"Communication error: {ex.Message}");
}
Configuration
{
"ECGridOS": {
"Login": "",
"Password": "",
"MailboxId": 0
}
}
Store credentials with user-secrets:
cd samples/soap/ECGrid-SOAP-dotnet10-Console-SvcUtil
dotnet user-secrets set "ECGridOS:Login" "your-login"
dotnet user-secrets set "ECGridOS:Password" "your-password"
How to Run
cd samples/soap/ECGrid-SOAP-dotnet10-Console-SvcUtil
dotnet user-secrets set "ECGridOS:Login" "your-login"
dotnet user-secrets set "ECGridOS:Password" "your-password"
dotnet run
Comparison with the HttpClient Sample
| Aspect | SvcUtil Proxy | HttpClient Manual |
|---|---|---|
| Setup effort | Generate proxy once | Write envelope helpers manually |
| Type safety | Full — compiler checks method signatures | None — all XML strings |
| Dependencies | System.ServiceModel.Http NuGet | No extra packages |
| Maintenance | Regenerate when WSDL changes | Update XML strings manually |
| Best for | Longer-lived integrations | Minimal-dependency or scripted use |
See SOAP HttpClient Sample for the manual approach.