ODataToClass 1.5.0

dotnet tool install --global ODataToClass --version 1.5.0
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local ODataToClass --version 1.5.0
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=ODataToClass&version=1.5.0
                    
nuke :add-package ODataToClass --version 1.5.0
                    

ODataToClass

A .NET CLI tool that generates C# classes from OData metadata. Supports both SAP OData (v2/v4) and Microsoft Dynamics 365 metadata.

Installation

# Install globally
dotnet tool install --global ODataToClass

# Or install locally in a project
dotnet tool install ODataToClass

Quick Start

# Generate from a local metadata file
odatatoclass -i metadata.xml -o MyEntities.cs

# Generate from an OData service URL
odatatoclass -u https://myserver.com/sap/opu/odata/sap/API_COSTCENTER/$metadata -o CostCenter.cs

# Generate from a URL with authentication
odatatoclass -u https://myserver.com/odata/$metadata --user myuser -p mypassword -o Entities.cs

Input Options

You must provide either --input (file) or --url (remote endpoint) as the metadata source.

From Local File (--input / -i)

Use this when you have already downloaded the metadata XML file:

odatatoclass -i metadata.xml -o Output.cs

From URL (--url / -u)

Fetch metadata directly from an OData service endpoint. The tool automatically appends $metadata if not present.

# Basic URL (no authentication)
odatatoclass -u https://services.odata.org/V4/Northwind/Northwind.svc/$metadata -o Northwind.cs

# With Basic Authentication
odatatoclass -u https://myserver.com/sap/opu/odata/sap/API_PROFITCENTER/$metadata --user USERNAME -p PASSWORD -o ProfitCenter.cs

Output Options

Output File (--output / -o)

Specify the output C# file path. If omitted, defaults to the input filename with .cs extension.

odatatoclass -i metadata.xml -o src/Models/Entities.cs

Namespace (--namespace / -n)

Set the C# namespace for generated classes. Default is SAP.

# SAP OData - uses SAP.{EntityName} structure
odatatoclass -i metadata.xml -n SAP -o Entities.cs
# Generates: namespace SAP.ProfitCenter { ... }

# Dynamics 365 - uses Dynamics.{ServiceName} structure
odatatoclass -i dynamics.xml -n Dynamics.Finance -o Finance.cs
# Generates: namespace Dynamics.Finance { ... }

Filtering Options

Entity Filter (--entity / -e)

Filter which entities to generate. Useful for large metadata files (Dynamics 365 can have 4000+ entities).

Supports wildcards (*) for pattern matching:

# Generate only SalesOrder entities
odatatoclass -i dynamics.xml -e "SalesOrder*" -o SalesOrders.cs

# Generate only entities starting with "Customer"
odatatoclass -i metadata.xml -e "Customer*" -o Customers.cs

# Generate a single specific entity
odatatoclass -i metadata.xml -e "ProfitCenter" -o ProfitCenter.cs

Advanced Options

Skip OData Wrappers (--no-wrappers)

By default, the tool generates OData response wrapper classes for deserializing API responses. Use --no-wrappers when:

  • You already have wrapper classes in your project
  • You're generating multiple files and want to share one set of wrappers
# Generate without wrapper classes
odatatoclass -i metadata.xml -o Entities.cs --no-wrappers

# Generate shared wrappers separately
odatatoclass wrappers -o ODataWrappers.cs -n SAP

Generate Only Wrappers (wrappers subcommand)

Generate only the OData wrapper classes without any entity classes:

odatatoclass wrappers -o ODataWrappers.cs -n MyNamespace

Complete Options Reference

Option Alias Description Default
--input -i Local OData metadata XML file -
--url -u URL to OData $metadata endpoint -
--user - Username for Basic authentication -
--password -p Password for Basic authentication -
--output -o Output C# file path {input}.cs
--namespace -n C# namespace prefix SAP
--entity -e Entity name filter (supports * wildcard) -
--no-wrappers - Skip generating OData wrapper classes false

Supported Metadata Formats

SAP OData v2

SAP's legacy OData format. Response structure uses nested d.results:

{ "d": { "results": [...] } }

Generated wrapper: OData.RootArray<T>, OData.Results<T>

SAP OData v4

Modern OData standard. Response structure uses value array:

{ "@odata.context": "...", "value": [...] }

Generated wrapper: ODataV4.RootArray<T> with List<T>

Microsoft Dynamics 365

Large enterprise metadata with extensive enum types. Auto-detected by namespace containing "Dynamics" or "Microsoft.Dynamics".

Generated Code Structure

Entity Classes

namespace SAP.ProfitCenter
{
    public class ProfitCenter
    {
        public string? ControllingArea { get; set; }

        [JsonProperty("ProfitCenter")]
        public string? _ProfitCenter { get; set; }

        public DateTimeOffset ValidityEndDate { get; set; }

        // Navigation property with OData v2 wrapper
        [JsonProperty("to_Text")]
        public OData.Results<ProfitCenterText>? Texts { get; set; }

        // Nested related entity
        public class ProfitCenterText
        {
            public string? Language { get; set; }
            public string? ProfitCenterName { get; set; }
        }
    }
}

Enum Types (Dynamics 365)

namespace Dynamics.Finance
{
    public enum FiscalQuarter
    {
        Q1 = 0,
        Q2 = 1,
        Q3 = 2,
        Q4 = 3
    }

    [Flags]
    public enum TransactionFlags : long
    {
        None = 0,
        Posted = 1,
        Reversed = 2
    }
}

OData Wrapper Classes

namespace SAP.OData
{
    // OData v2 response wrapper
    public class RootArray<T>
    {
        public Results<T> d { get; set; }
    }

    public class Results<T>
    {
        public List<T> results { get; set; }
    }
}

namespace SAP.ODataV4
{
    // OData v4 response wrapper
    public class RootArray<T>
    {
        [JsonProperty("@odata.context")]
        public string? Context { get; set; }

        [JsonProperty("value")]
        public List<T> Value { get; set; }
    }
}

Usage Examples

Deserializing OData v2 Response

using SAP.OData;
using SAP.ProfitCenter;
using Newtonsoft.Json;

var json = await httpClient.GetStringAsync("https://server/sap/opu/odata/sap/API_PROFITCENTER/A_ProfitCenter");
var response = JsonConvert.DeserializeObject<RootArray<ProfitCenter>>(json);

foreach (var pc in response.d.results)
{
    Console.WriteLine($"Profit Center: {pc._ProfitCenter}");
}

Deserializing OData v4 Response

using SAP.ODataV4;
using SAP.CostCenter;
using Newtonsoft.Json;

var json = await httpClient.GetStringAsync("https://server/odata/v4/CostCenters");
var response = JsonConvert.DeserializeObject<RootArray<CostCenter>>(json);

foreach (var cc in response.Value)
{
    Console.WriteLine($"Cost Center: {cc.CostCenterId}");
}

Generating Multiple Files (Dynamics 365)

When working with large Dynamics 365 metadata, generate separate files per module:

# Generate shared wrappers first
odatatoclass wrappers -o Shared/ODataWrappers.cs -n Dynamics

# Generate Sales module entities
odatatoclass -i dynamics.xml -e "SalesOrder*" -n Dynamics.Sales -o Sales/SalesOrders.cs --no-wrappers

# Generate Finance module entities
odatatoclass -i dynamics.xml -e "Ledger*" -n Dynamics.Finance -o Finance/Ledger.cs --no-wrappers

# Generate Customer entities
odatatoclass -i dynamics.xml -e "Cust*" -n Dynamics.Customers -o Customers/Customers.cs --no-wrappers

Type Mappings

EDM Type C# Type
Edm.String string?
Edm.Int32 int
Edm.Int64 long
Edm.Int16 short
Edm.Decimal decimal
Edm.Double double
Edm.Single float
Edm.Boolean bool
Edm.Guid Guid
Edm.DateTime DateTimeOffset
Edm.DateTimeOffset DateTimeOffset
Edm.Date DateTimeOffset
Edm.Time TimeSpan
Edm.Binary byte[]?
Edm.Byte byte

License

MIT

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
1.5.0 572 12/11/2025
1.4.0 438 12/11/2025
1.3.0 450 12/11/2025
1.2.0 454 12/11/2025
1.1.0 454 12/10/2025
1.0.0 465 12/9/2025