.NET (C# / VBA.NET): arupcompute-connect-dotnet
There is no project charging for use of ArupCompute, however project usage data is critical to justifying continued funding of ArupCompute - please provide a job number!
To contribute and / or submit bug reports go to the arupcompute-connect-dotnet github.
You will require access to the Arup GitHub account to see the above link. If you are having trouble reach out on the ArupCompute teams.
You can join the teams using the code b53lq6l
Installation
You can reference the arupcompute-connect-dotnet library using NuGet, dotnet, or Visual Studio.
Dotnet
As arupcompute-connect-dotnet is hosted on a private feed you will need to install the Azure Artifacts Credential Provider.
Also ensure that you visit this webpage to ensure that you have access to the repository where the reference libraries are stored (enter Arup login details if prompted).
Project setup
Add a nuget.config file to your project, in the same folder as your .csproj or .sln file
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="arupcomputedevops@Release" value="https://pkgs.dev.azure.com/arupcomputedevops/_packaging/arupcomputedevops/nuget/v3/index.json" />
</packageSources>
</configuration>
Add references
Use the dotnet add package --interactive command (using the interactive flag, which allows the credential manager to prompt you for credentials):
dotnet add [<PROJECT>] package --interactive arupcompute-connect-dotnet
The three packages you will need to add to your solution are:
- arupcompute-connect-dotnet
- Arup.Compute.Models
- Arup.Compute.DotNetSdk
Restore packages
If prompted to restore packages you may need to use the --interactive flag:
dotnet restore --interactive
Simple example
using Arup.Compute.Connect;
using Arup.Compute.Models;
using Arup.Compute.DotNetSdk;
using System.Threading.Tasks;
Connection connection = new Connection("00000-00"); // The job number will _not_ be charged
int calcId = 11416564; // Sample Library - Basic calculation
Dictionary<string, object> inputs = new Dictionary<string, object>()
{
{ "a", 1 },
{ "b", 2}
};
Task<CalcRecord> resultTask = Call.ExecuteCalculationAsync(connection, calcId, false, inputs);
CalcRecord calcRecord = resultTask.Result;
If you are interacting with a library that utilises the expanded features of ArupCompute (e.g. report writing, errors, warnings, remarks etc.) such as DesignCheck2 you will need the additional step below to interpret the .Result
:
Task<CalcRecord> resultTask = Call.ExecuteCalculationAsync(connection, calcId, false, inputs, resultType: Arup.Compute.Connect.Call.ResultType.Simple); // Simple provides reports, errors etc. default is mini which just returns results
CalcRecord result = resultTask.Result;
ArupComputeResult acr = result.ParseOutput<Arup.Compute.DotNetSdk.ArupComputeResult>();
// For example if you want access to the plain-text report
string report = acr.ArupComputeReport;
If you are utilising the batch execution feature of ArupCompute and want access to reports etc. you will need to do the following:
///Call.ExecuteBatchCalculationAsync(...)
var lacr = result.ParseOutput<List<Arup.Compute.DotNetSdk.ArupComputeResult>>();
Connection object
The Connection
class is one of the most important parts of the Dotnet ArupCompute client. It controls all authentication and most settings related to the client. It is a required input in most other functions related to ArupCompute.
This object also controls when to use AC Local.
The Connection
object also replaces the old authentication methods. If you are working on an older Dotnet project that has not yet updated to use the Connection
object then you should perform this upgrade as older authentication methods may stop working.
Constructor properties
Name | Description | Default |
---|---|---|
string jobNumber | The Job Number this call is associated with. This is for usage tracking purposes only and will not result in any charges to the job | N/A |
Connect.ConfigMode Mode | The "Mode" that Connect will run in. This primarily affects how/why/when Connect will call AC Local or remote. Change to Connect.ConfigMode.PROXY to always use remote, recommended for instances where Connect is being used on a server | ConfigMode.DEFAULT |
Task<string> tokenTask | The task object that contains the authentication method. In most cases this should be left to Connection to handle. Should only be used in scenarios where the auth to Arup systems are being handled outside of Connect | null |
Connection modes
The Connection
object can run in multiple different "modes". These modes control when/how Connect will try to connect to AC Local and when it will instead send requests directly to the remote server. This mode is changed through changing the Connect.ConfigMode Mode
argument in the constructor.
Most users should not change the mode that Connect is using. If you are using Connect inside a Compute function then you should not change the mode. The correct mode will be set automatically by ArupCompute.
Name | Description | When to use |
---|---|---|
DEFAULT | Connect will prefer AC Local over using the remote server. It will only use remote if AC Local cannot be found | This is the default mode that should be used in the vast majority of programs. Specifically it should be used on any program that is running on user's machines |
PROXY | Connect will always use the remote server, it will not look for whether AC Local is running | This should be used when a dotnet program is running on a server where AC Local will not be present |
FUNC_SERVICE | Connect will always use AC Local and will throw an error if AC Local cannot be found. It makes calls to AC Local through Unix Domain Sockets rather than HTTP | This mode should not be set directly by users. It is primarily used when Connect is being used inside an ArupCompute calc running on AC Local |
Example use
string jobNumber = "00000000"
Connection connection = new Connection(jobNumber); // The job number will not be charged
Non-primitive inputs / outputs - JSON
The recommended library for working with JSON in C# is Newtonsoft.JSON. However, the arupcompute-connect-dotnet
library uses this in the background and can deal with serialisation / deserialisation for you.
Parallel Mode
When making calls to AC Local you can use "parallel mode" to run a batch of calcs. This will make AC Local run the calculations in the batch in parallel, meaning that the batch will run faster. There is additional setup time required on AC Local when running calcs in parallel, so for small batches it is better to run the batch not in parallel mode. From testing we have found that if the batch is larger than 10 calcs then running in parallel will be faster than in regular batch mode.
To run a calc in parallel, set the parallel
param in Call.ExecuteCalculationAsync
to true
.
Connection connection = new Connection("00000-00"); // The job number will _not_ be charged
int calcId = 11416564; // Sample Library - Basic calculation
Dictionary<string, object> inputs = new Dictionary<string, object>()
{
{ "a", new List<int>() { 1, 2, 3, 4, 5 } },
{ "b", new List<int>() { 2, 3, 4, 5, 6 } }
};
Task<CalcRecord> resultTask = Call.ExecuteCalculationAsync(connection, calcId, batch: true, inputs, parallel: true); // Note: parallel and batch are set to true
CalcRecord calcRecord = resultTask.Result;
useFanOut
parallel
should not be set to True
at the same time as useFanOut
. Doing this would mean that parallel
would have no effect
Optional Inputs
When you want to use the default value for an optional input you can either set the value of the input to be null
, or leave out the input entirely from your inputs dictionary:
// for single invocation
Dictionary<string, object> inputs = new Dictionary<string, object>()
{
{ "a", 1 },
{ "b", 2 },
{ "optional-input", null } // or leave out this line
};
Task<CalcRecord> resultTask = Call.ExecuteCalculationAsync(connection, calcId, batch: false, inputs);
CalcRecord calcRecord = resultTask.Result;
// for batch call
Dictionary<string, object> inputs = new Dictionary<string, object>()
{
{ "a", new List<int>() { 1, 2, 3, 4, 5 } },
{ "b", new List<int>() { 2, 3, 4, 5, 6 } },
{ "optional-input", new List<object>() { null, 3, 4, 1 } } // NOTE: This list is not as long as the above two lists
};
Task<CalcRecord> resultTask = Call.ExecuteCalculationAsync(connection, calcId, batch: true, inputs);
CalcRecord calcRecord = resultTask.Result;