Skip to content

Commit

Permalink
Add sample project that consumes the ODS API client SDK - v6 (#989)
Browse files Browse the repository at this point in the history
  • Loading branch information
axelmarquezh authored Apr 12, 2024
1 parent 65c3830 commit 16a2c6e
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.9.1" />
</ItemGroup>

</Project>
21 changes: 21 additions & 0 deletions Examples/Using the ODS API SDK/EdFi.OdsApi.SdkClient/Options.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: Apache-2.0
// Licensed to the Ed-Fi Alliance under one or more agreements.
// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0.
// See the LICENSE and NOTICES files in the project root for more information.

using CommandLine;

namespace EdFi.OdsApi.SdkClient
{
internal class Options
{
[Option('u', "url", Required = true, HelpText = "The base URL of the ODS API.")]
public required string OdsApiUrl { get; set; }

[Option('k', "key", Required = true, HelpText = "The client key.")]
public required string ClientKey { get; set; }

[Option('s', "secret", Required = true, HelpText = "The client secret.")]
public required string ClientSecret { get; set; }
}
}
69 changes: 69 additions & 0 deletions Examples/Using the ODS API SDK/EdFi.OdsApi.SdkClient/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// SPDX-License-Identifier: Apache-2.0
// Licensed to the Ed-Fi Alliance under one or more agreements.
// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0.
// See the LICENSE and NOTICES files in the project root for more information.

using CommandLine;
using EdFi.OdsApi.Sdk.Apis.All;
using EdFi.OdsApi.Sdk.Client;
using EdFi.OdsApi.Sdk.Models.All;
using EdFi.OdsApi.SdkClient;

// Parse the command line arguments
var options = Parser.Default.ParseArguments<Options>(args)
.WithNotParsed(e => e.Output()) // Show errors and help
.Value;

if (options == default) return;

// Trust all SSL certs -- needed unless signed SSL certificates are configured.
System.Net.ServicePointManager.ServerCertificateValidationCallback =
((sender, certificate, chain, sslPolicyErrors) => true);

//Explicitly configures outgoing network calls to use the latest version of TLS where possible.
//Due to our reliance on some older libraries, the.NET framework won't necessarily default
//to the latest unless we explicitly request it. Some hosting environments will not allow older versions
//of TLS, and thus calls can fail without this extra configuration.
System.Net.ServicePointManager.SecurityProtocol |= System.Net.SecurityProtocolType.Tls11 | System.Net.SecurityProtocolType.Tls12;

// TokenRetriever makes the oauth calls. It has RestSharp dependency
var tokenRetriever = new TokenRetriever(options.OdsApiUrl, options.ClientKey, options.ClientSecret);

// Plug Oauth access token. Tokens will need to be refreshed when they expire
var configuration = new Configuration() { AccessToken = tokenRetriever.ObtainNewBearerToken(), BasePath = $"{options.OdsApiUrl}/data/v3" };

// GET students
var apiInstance = new StudentsApi(configuration);
apiInstance.Configuration.DefaultHeaders.Add("Content-Type", "application/json");

// Fetch a single record with the totalCount flag set to true to retrieve the total number of records available
var studentWithHttpInfo = apiInstance.GetStudentsWithHttpInfo(limit: 1, offset: 0, totalCount: true);

var httpReponseCode = studentWithHttpInfo.StatusCode; // returns System.Net.HttpStatusCode.OK
Console.WriteLine("Response code is " + httpReponseCode);

// Parse the total count value out of the "Total-Count" response header
var totalCount = int.Parse(studentWithHttpInfo.Headers["Total-Count"].First());

int offset = 0;
int limit = 100;
var students = new List<EdFiStudent>();

while (offset < totalCount)
{
Console.WriteLine($"Fetching student records {offset} through {Math.Min(offset + limit, totalCount)} of {totalCount}");
students.AddRange(apiInstance.GetStudents(limit: limit, offset: 0));
offset += limit;
}

Console.WriteLine();
Console.WriteLine("Student Results");

foreach (var student in students)
{
Console.WriteLine($"Student: {student.StudentUniqueId}, {student.FirstName}, {student.LastSurname}");
}

Console.WriteLine();
Console.WriteLine("Hit ENTER key to continue...");
Console.ReadLine();
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// SPDX-License-Identifier: Apache-2.0
// Licensed to the Ed-Fi Alliance under one or more agreements.
// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0.
// See the LICENSE and NOTICES files in the project root for more information.

using System.Net;
using System.Runtime.Serialization;
using System.Security.Authentication;
using EdFi.OdsApi.Sdk.Client;

namespace EdFi.OdsApi.SdkClient
{
internal class TokenRetriever(string basePath, string clientKey, string clientSecret)
{
public string ObtainNewBearerToken()
{
var oauthClient = new ApiClient(basePath);
return GetBearerToken(oauthClient);
}

private string GetBearerToken(ApiClient oauthClient)
{
var configuration = new Configuration() { BasePath = basePath };
var bearerTokenRequestOptions = new RequestOptions() { Operation = String.Empty };
bearerTokenRequestOptions.FormParameters.Add("Client_id", clientKey);
bearerTokenRequestOptions.FormParameters.Add("Client_secret", clientSecret);
bearerTokenRequestOptions.FormParameters.Add("Grant_type", "client_credentials");

var bearerTokenResponse = oauthClient.Post<BearerTokenResponse>("oauth/token", bearerTokenRequestOptions, configuration);
if (bearerTokenResponse.StatusCode != HttpStatusCode.OK)
{
throw new AuthenticationException("Unable to retrieve an access token. Error message: " +
bearerTokenResponse.Data.Error);
}

if (bearerTokenResponse.Data.Error != null || bearerTokenResponse.Data.TokenType != "bearer")
{
throw new AuthenticationException(
"Unable to retrieve an access token. Please verify that your application secret is correct.");
}

return bearerTokenResponse.Data.AccessToken;
}
}

[DataContract]
internal class BearerTokenResponse
{
[DataMember(Name = "access_token", EmitDefaultValue = false)]
public required string AccessToken { get; set; }

[DataMember(Name = "expires_in", EmitDefaultValue = false)]
public required string ExpiresIn { get; set; }

[DataMember(Name = "token_type", EmitDefaultValue = false)]
public required string TokenType { get; set; }

[DataMember(Name = "error", EmitDefaultValue = false)]
public required string Error { get; set; }
}
}
1 change: 1 addition & 0 deletions Examples/Using the ODS API SDK/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Contains a C# sample project that consumes the generated client SDK.

0 comments on commit 16a2c6e

Please sign in to comment.