A foundational library for building Ordercloud middleware APIs, jobs, plugins and extensions with .NET. A toolbox of helpers for authentication, performant bulk requests, error handling, jobs, project setup, ect.
See dotnet-middleware for a starter server-side project that uses this library. Targeted guides are found there.
If you're building solutions for OrderCloud using .NET and find a particular task difficult or tedious, we welcome you to suggest a feature for inclusion in this library.
Contributing Guide For Integrations -> CONTRIBUTING.md
Use Ordercloud's authentication scheme in your own APIs. More Info
[HttpGet("hello"), OrderCloudUserAuth(ApiRole.Shopper)]
public string SayHello() {
return $"Hello {UserContext.Username}"; // UserContext is a property on CatalystController
}
Securely receive push notifications of events from the Ordercloud platform. More Info
[HttpPost("webhook"), OrderCloudWebhookAuth]
public object HandleAddressSave([FromBody] WebhookPayloads.Addresses.Save<MyConfigData> payload) {
...
}
If OrderCloud's limit of 100 records per page is a pain point. More Info
var orders = new OrderCloudClient(...).Orders.ListAllAsync();
Receive list requests to your API with user defined filters, search, paging, and sorting. More Info
[HttpGet("orders"), OrderCloudUserAuth(ApiRole.Shopper)]
public async Task<ListPage<Order>> ListOrders(IListArgs args)
{
var user = await _oc.Me.GetAsync(UserContext.AccessToken); // get user details
args.Filters.Add(new ListFilter("FromCompanyID", user.MeUser.Buyer.ID)) // filter using the user's buyer organization ID
args.Filters.Add(new ListFilter("LineItemCount", ">5"))
// list orders from an admin endpoint
var orders = await _oc.Orders.ListAsync(OrderDirection.Incoming, null, null, null, null, args); // apply list args with an extension version of ListAsync()
return orders;
}
Use Redis or LazyCache. Or, define your own implementation of ISimpleCache. More Info
private ISimpleCache _cache;
[HttpGet("thing")]
public Thing GetThing(string thingID) {
var key = $"thing-{thingID}";
var timeToLive = TimeSpan.FromMinutes(10);
var thing = await _cache.GetOrAddAsync(key, timeToLive, () database.GetThing(thingID));
return thing;
}
[HttpPut("thing")]
public Thing EditThing(string thingID) {
var key = $"thing-{thingID}";
await _cache.RemoveAsync(thingID);
return await database.EditThing(thingID);
}
A perfomance helper for multiple async function calls. More Info
var cars = new List<Car>();
var maxConcurency = 20;
var minPause = 100 // ms
var carOwners = await Throttler.RunAsync(cars, minPause, maxConcurency, car => apiClient.GetCarOwner(car.ID);
Handle API errors, including unexpected ones, with a standard JSON response structure. Define your own errors. More Info
public class AgeLimit21Exception : CatalystBaseException
{
public AgeLimit21Exception() : base("AgeLimit21", 403, "You must be 21 years of age or older to buy this product.") { }
}
....
Require.That(user.xp.Age >= 21, new AgeLimit21Exception());
Take advantage of DataAnnotation attributes to specify validation requirements for your own custom models. More Info
[Required(ErrorMessage = "This field is required, please try again.")]
public string RequiredField { get; set; }
When writing integration tests that hit an endpoint marked with [OrderCloudUserAuth]
, you'll need to pass a properly formatted JWT token in the Authorization header, otherwise the call will fail. Fake tokens are a bit tedious to create, so OrderCloud.Catalyst
provides a helper:
var token = FakeOrderCloudToken.Create(
clientID: "my-client-id",
roles: new List<string> { "Shopper" },
expiresUTC: DateTime.UtcNow + TimeSpan.FromHours(1),
notValidBeforeUTC: DateTime.UtcNow - TimeSpan.FromHours(1)
);
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", token);