InforIonClientLibrary 1.0.0

dotnet add package InforIonClientLibrary --version 1.0.0                
NuGet\Install-Package InforIonClientLibrary -Version 1.0.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="InforIonClientLibrary" Version="1.0.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add InforIonClientLibrary --version 1.0.0                
#r "nuget: InforIonClientLibrary, 1.0.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install InforIonClientLibrary as a Cake Addin
#addin nuget:?package=InforIonClientLibrary&version=1.0.0

// Install InforIonClientLibrary as a Cake Tool
#tool nuget:?package=InforIonClientLibrary&version=1.0.0                

Infor ION Integration Example Documentation

Overview

This documentation provides an example project demonstrating how to use the InforIonClientLibrary to integrate your application with Infor ION APIs. The goal is to show how to effectively set up and utilize components such as ConnectionOptions, TokenService, and InforIonClient to simplify secure API communication.

Components Overview:

  1. ConnectionOptions: Loads configuration settings from the .ionapi file.
  2. TokenService: Handles OAuth token management.
  3. InforIonClient: Sends HTTP requests to Infor ION APIs.

Each component works together to simplify backend communication, making it easy to manage API requests, authentication, and errors.


Demo Project: Setting Up Integration with Infor ION

This section demonstrates how to set up an ASP.NET Core project that utilizes the InforIonClientLibrary to communicate with Infor APIs. The example project will guide you through configuring services and using the provided classes to make API calls.

Step 1: Configure the Services

First, we need to configure the necessary services in the Program.cs or Startup.cs file.

using InforIonClientLibrary; 
using MongooseDemoApp.Components;
using MongooseDemoApp.Services;
using Microsoft.Extensions.DependencyInjection;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

// Configure InforIonClientLibrary services
builder.Services.AddHttpClient<IdoCollectionService>(); 
builder.Services.AddSingleton<ConnectionOptions>(sp => ConnectionOptions.FromIonApiFile("ionapi/JT_ClientConnection.ionapi"));
builder.Services.AddSingleton<ITokenService, TokenService>();
builder.Services.AddLogging(configure => configure.AddConsole());
builder.Services.AddSingleton<ApiHelper>();

var app = builder.Build();
.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAntiforgery();

app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

app.Run();

In this setup:

  • ConnectionOptions is used to load configuration details from the .ionapi file.
  • TokenService manages OAuth tokens for authentication.
  • IdoCollectionService is registered as an HTTP client to interact with specific Infor ION endpoints.

Step 2: Create the IdoCollectionService

The IdoCollectionService is responsible for interacting with the Infor ION APIs. Below is an example implementation that demonstrates fetching configurations and loading collections.

using InforIonClientLibrary.src;
using MongooseDemoApp.Models;
using InforIonClientLibrary;
using System.Text.Json;

namespace MongooseDemoApp.Services;
public class IdoCollectionService
{
    private readonly HttpClient _httpClient;
    private readonly ILogger<IdoCollectionService> _logger;
    private readonly ITokenService _tokenService;
    private readonly string _baseUri;
    private readonly string _mongooseConfig;

    public IdoCollectionService(HttpClient httpClient, ILogger<IdoCollectionService> logger, ITokenService tokenService, ConnectionOptions options)
    {
        _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        _tokenService = tokenService ?? throw new ArgumentNullException(nameof(tokenService));
        _baseUri = $"{options.Iu}/{options.Ti}/MONGOOSE/IDORequestService";
        _mongooseConfig = options.Ti ?? throw new ArgumentNullException(nameof(options.Ti));
    }

    public async Task<List<string>> GetConfigurationsAsync(string? configGroup = null)
    {
        configGroup ??= _mongooseConfig;

        var tokenResponse = await _tokenService.GetTokenAsync();
        _httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", tokenResponse.AccessToken);
        _httpClient.DefaultRequestHeaders.Add("X-Infor-MongooseConfig", _mongooseConfig);

        var url = $"{_baseUri}/ido/configurations";
        if (!string.IsNullOrEmpty(configGroup))
        {
            url += $"?configGroup={configGroup}";
        }

        _logger.LogInformation("Calling configurations endpoint with configGroup: {ConfigGroup}, URL: {Url}", configGroup, url);

        try
        {
            var response = await _httpClient.GetAsync(url, HttpCompletionOption.ResponseContentRead).ConfigureAwait(false);
            response.EnsureSuccessStatusCode();

            var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
            var configResponse = JsonSerializer.Deserialize<ConfigurationNames>(json);

            if (configResponse?.Configurations == null || configResponse.Configurations.Count == 0)
            {
                _logger.LogWarning("Configuration response was null or empty.");
                return new List<string>();
            }

            _logger.LogInformation("Successfully retrieved configurations.");
            return configResponse.Configurations;
        }
        catch (HttpRequestException ex)
        {
            _logger.LogError("Error calling configurations endpoint: {Message}", ex.Message);
            throw;
        }
    }

    public async Task<LoadCollectionResponse> LoadIdoCollectionAsync(
        string idoName,
        string properties,
        string configuration,
        string filter = null,
        string orderBy = null,
        int? recordCap = null)
    {
        var tokenResponse = await _tokenService.GetTokenAsync();
        _httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", tokenResponse.AccessToken);
        _httpClient.DefaultRequestHeaders.Remove("X-Infor-MongooseConfig");
        _httpClient.DefaultRequestHeaders.Add("X-Infor-MongooseConfig", configuration);

        var url = $"{_baseUri}/ido/load/{idoName}?properties={properties}";
        if (!string.IsNullOrEmpty(filter)) url += $"&filter={filter}";
        if (!string.IsNullOrEmpty(orderBy)) url += $"&orderBy={orderBy}";
        if (recordCap.HasValue) url += $"&recordCap={recordCap}";

        var response = await _httpClient.GetAsync(url);
        response.EnsureSuccessStatusCode();

        var json = await response.Content.ReadAsStringAsync();
        return JsonSerializer.Deserialize<LoadCollectionResponse>(json) ?? new LoadCollectionResponse();
    }
}

In this example:

  • The IdoCollectionService makes API calls to Infor ION to get available configurations and interact with IDO collections.
  • GetConfigurationsAsync and LoadIdoCollectionAsync methods demonstrate how to use the TokenService to retrieve an access token before making requests.

Step 3: Using the Service in Your Application

Here's an example of how you might use the IdoCollectionService in a Razor component to display available configurations and load collection data.

@page "/"
@page "/collections"
@rendermode InteractiveServer
@using MongooseDemoApp.Services
@inject IdoCollectionService MongooseService

<div class="container my-5">
    <div class="card shadow-sm">
        <div class="card-header bg-primary text-white">
            <h3 class="card-title mb-0">Collection Loader</h3>
        </div>
        <div class="card-body">
            @if (loadError)
            {
                <div class="alert alert-danger" role="alert">
                    <strong>Error:</strong> Failed to load configurations. Please try again later.
                </div>
            }

            <div class="mb-3">
                <label for="config" class="form-label">Select Configuration:</label>
                <select id="config" class="form-select" @bind="selectedConfiguration">
                    <option value="">Select a configuration</option>
                    @foreach (var config in availableConfigurations)
                    {
                        <option value="@config">@config</option>
                    }
                </select>
            </div>

            <div class="mb-3">
                <label for="collection" class="form-label">Enter IDO Name:</label>
                <input id="collection" class="form-control" @bind="selectedCollection" placeholder="e.g., SLItems" />
            </div>

            <div class="mb-3">
                <label for="properties" class="form-label">Enter Properties (space-separated):</label>
                <input id="properties" class="form-control" @bind="propertiesInput" placeholder="e.g., Caption CollectionName CreatedBy" />
            </div>

            <div class="mb-3">
                <button class="btn btn-primary" @onclick="LoadCollectionData">Load Collection</button>
            </div>
        </div>
    </div>

    @if (data != null && data.Any())
    {
        <div class="table-responsive mt-4">
            <table class="table table-striped table-hover">
                <thead class="table-dark">
                    <tr>
                        @foreach (var column in columns)
                        {
                            <th>@column</th>
                        }
                    </tr>
                </thead>
                <tbody>
                    @foreach (var item in data)
                    {
                        <tr>
                            @foreach (var column in columns)
                            {
                                <td>@item[column]</td>
                            }
                        </tr>
                    }
                </tbody>
            </table>
        </div>
    }
    else if (hasLoaded && !loadError)
    {
        <div class="alert alert-info mt-4" role="alert">
            No data to display
        </div>
    }
</div>

@code {
    private string selectedCollection;
    private string propertiesInput;
    private string selectedConfiguration;
    private List<string> availableConfigurations = new();
    private List<string> columns = new();
    private List<Dictionary<string, object>> data = new();
    private bool hasLoaded = false;
    private bool loadError = false; 

    protected override async Task OnInitializedAsync()
    {
        try
        {
            availableConfigurations = await MongooseService.GetConfigurationsAsync();

            if (availableConfigurations.Count == 1)
            {
                selectedConfiguration = availableConfigurations[0];
            }

            loadError = false;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error loading configurations: {ex.Message}");
            loadError = true;
        }
    }

    private async Task LoadCollectionData()
    {
        hasLoaded = false;

        if (!string.IsNullOrEmpty(selectedCollection) && !string.IsNullOrEmpty(selectedConfiguration))
        {
            try
            {
                var properties = string.Join(",", propertiesInput?.Split(' ', StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty<string>());

                var response = await MongooseService.LoadIdoCollectionAsync(selectedCollection, properties, selectedConfiguration);

                if (response?.Items != null && response.Items.Any())
                {
                    data = response.Items;
                    columns = data.First().Keys.ToList();
                }
                else
                {
                    data = new List<Dictionary<string, object>>();
                    columns = new List<string>();
                }
                loadError = false;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error loading data: {ex.Message}");
                loadError = true;
            }
        }
        else
        {
            Console.WriteLine("Please select a configuration and enter an IDO name.");
        }

        hasLoaded = true;
    }
}

This Razor component:

  • Injects the IdoCollectionService to interact with the Infor ION APIs.
  • Allows the user to select configurations, specify IDO names, and load collection data.
  • Displays the fetched data in a table format.

Conclusion

This example project shows how to use the InforIonClientLibrary to integrate your ASP.NET Core application with Infor ION APIs:

  • Set up services for managing API connections and tokens.
  • Utilize IdoCollectionService to interact with configurations and collections.
  • Create Razor components to demonstrate fetching and displaying data from Infor APIs.

This approach allows you to focus more on the application logic and less on the complexities of managing API connections and tokens.


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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.0 77 11/14/2024

Initial release.