Demo code for building a request
Set up a C# client for the OpenSearch Industry Algorithm Edition API: install the required NuGet packages, configure credentials from environment variables, and build a signed HTTP request.
Prerequisites
Before you begin, ensure that you have:
A .NET project with the
dotnetCLI availableAn Alibaba Cloud account with OpenSearch enabled
An AccessKey pair for a Resource Access Management (RAM) user that has the required OpenSearch permissions
Use a RAM user's AccessKey pair instead of your Alibaba Cloud root account credentials. Root account credentials grant full access to all API operations. For setup instructions, see Create a RAM user and Create an AccessKey pair. For the permissions required by the RAM user, see AliyunServiceRoleForOpenSearch and Access authorization rules.
Set environment variables
Store your AccessKey pair as environment variables to keep credentials out of your source code.
Linux and macOS — run the following commands, replacing the placeholders with your RAM user's AccessKey ID and AccessKey secret:
export ALIBABA_CLOUD_ACCESS_KEY_ID=<access_key_id> export ALIBABA_CLOUD_ACCESS_KEY_SECRET=<access_key_secret>Windows — create an environment variable file, add
ALIBABA_CLOUD_ACCESS_KEY_IDandALIBABA_CLOUD_ACCESS_KEY_SECRET, set each to the corresponding value, and restart Windows for the changes to take effect.
Install dependencies
Download and install the following packages from NuGet:
dotnet add package AlibabaCloud.TeaUtil --version 0.1.5
dotnet add package AlibabaCloud.OpenSearchUtil --version 1.0.2
dotnet add package Aliyun.Credentials --version 1.2.1
dotnet add package Tea --version 0.4.0Use the exact versions listed above. A version mismatch betweenTeaandAlibabaCloud.OpenSearchUtilcauses a runtime exception at theGetSignaturecall: If you see this error, remove the existing packages and re-add them at the exact versions above.
System.MissingMethodException: Method not found: 'System.String Tea.Utils.Extensions.Get(System.Collections.Generic.Dictionary`2<System.String,System.String>, System.String, System.String)'.
at AlibabaCloud.OpenSearchUtil.Common.GetSignature(TeaRequest request, String accessKeySecret)
at AlibabaCloud.OpenSearchUtil.Common.GetSignature(TeaRequest request, String accessKeyId, String accessKeySecret)
at Client._request(String method, String pathname, Dictionary`2 query, Dictionary`2 headers, Object body, RuntimeOptions runtime) in D:\workspace\C#_workspace\MyDoNet\Client.cs:line 131
at MyDoNet.Program.searchDoc(Client opensearchClient, String appName, Dictionary`2 queryParams, Dictionary`2 header, RuntimeOptions runTime) in D:\workspace\C#_workspace\MyDoNet\Program.cs:line 17
at MyDoNet.Program.Main(String[] args) in D:\workspace\C#_workspace\MyDoNet\Program.cs:line 84Sample code
The following Client class builds and signs HTTP requests to the OpenSearch API. It reads credentials from the environment variables you configured, attaches the required headers (Date, X-Opensearch-Nonce, Content-MD5, Authorization), and handles retries with configurable backoff.
// This file is auto-generated, don't edit it. Thanks.
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Tea;
using Tea.Utils;
public class Client
{
protected string _endpoint;
protected string _protocol;
protected string _userAgent;
protected Aliyun.Credentials.Client _credential;
public Client(Config config)
{
if (AlibabaCloud.TeaUtil.Common.IsUnset(config.ToMap()))
{
throw new TeaException(new Dictionary<string, string>
{
{"name", "ParameterMissing"},
{"message", "'config' can not be unset"},
});
}
if (AlibabaCloud.TeaUtil.Common.Empty(config.Type))
{
config.Type = "access_key";
}
Aliyun.Credentials.Models.Config credentialConfig = new Aliyun.Credentials.Models.Config
{
AccessKeyId = config.AccessKeyId,
Type = config.Type,
AccessKeySecret = config.AccessKeySecret,
SecurityToken = config.SecurityToken,
};
this._credential = new Aliyun.Credentials.Client(credentialConfig);
this._endpoint = config.Endpoint;
this._protocol = config.Protocol;
this._userAgent = config.UserAgent;
}
public Dictionary<string, object> _request(string method, string pathname, Dictionary<string, object> query,
Dictionary<string, string> headers, object body, AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime)
{
Dictionary<string, object> runtime_ = new Dictionary<string, object>
{
{"timeouted", "retry"},
{"readTimeout", runtime.ReadTimeout},
{"connectTimeout", runtime.ConnectTimeout},
{"httpProxy", runtime.HttpProxy},
{"httpsProxy", runtime.HttpsProxy},
{"noProxy", runtime.NoProxy},
{"maxIdleConns", runtime.MaxIdleConns},
{"retry", new Dictionary<string, object>
{
{"retryable", runtime.Autoretry},
{"maxAttempts", AlibabaCloud.TeaUtil.Common.DefaultNumber(runtime.MaxAttempts, 1)},
}
},
{"backoff", new Dictionary<string, object>
{
{"policy", AlibabaCloud.TeaUtil.Common.DefaultString(runtime.BackoffPolicy, "no")},
{"period", AlibabaCloud.TeaUtil.Common.DefaultNumber(runtime.BackoffPeriod, 1)},
}
},
{"ignoreSSL", runtime.IgnoreSSL},
};
TeaRequest _lastRequest = null;
Exception _lastException = null;
long _now = System.DateTime.Now.Millisecond;
int _retryTimes = 0;
while (TeaCore.AllowRetry((IDictionary) runtime_["retry"], _retryTimes, _now))
{
if (_retryTimes > 0)
{
int backoffTime = TeaCore.GetBackoffTime((IDictionary) runtime_["backoff"], _retryTimes);
if (backoffTime > 0)
{
TeaCore.Sleep(backoffTime);
}
}
_retryTimes = _retryTimes + 1;
try
{
TeaRequest request_ = new TeaRequest();
// Read AccessKey credentials from environment variables.
// Set ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET
// before running this code. See "Set environment variables" above.
string accesskeyId = System.Environment.GetEnvironmentVariable("ALIBABA_CLOUD_ACCESS_KEY_ID");
string accessKeySecret = System.Environment.GetEnvironmentVariable("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
string securityToken = this._credential.GetSecurityToken();
request_.Protocol = AlibabaCloud.TeaUtil.Common.DefaultString(_protocol, "HTTP");
request_.Method = method;
request_.Pathname = pathname;
request_.Headers = TeaConverter.merge<string>
(
new Dictionary<string, string>()
{
{"user-agent", AlibabaCloud.TeaUtil.Common.GetUserAgent(this._userAgent )},
{"Date", AlibabaCloud.OpenSearchUtil.Common.GetDate()},
{"host", AlibabaCloud.TeaUtil.Common.DefaultString(_endpoint, "opensearch-cn-hangzhou.aliyuncs.com")},
{"X-Opensearch-Nonce", AlibabaCloud.TeaUtil.Common.GetNonce()},
},
headers
);
if (!AlibabaCloud.TeaUtil.Common.IsUnset(query))
{
request_.Query = AlibabaCloud.TeaUtil.Common.StringifyMapValue(query);
}
if (!AlibabaCloud.TeaUtil.Common.IsUnset(body))
{
string reqBody = AlibabaCloud.TeaUtil.Common.ToJSONString(body);
request_.Headers["Content-MD5"] = AlibabaCloud.OpenSearchUtil.Common.GetContentMD5(reqBody);
request_.Headers["Content-Type"] = "application/json";
request_.Body = TeaCore.BytesReadable(reqBody);
}
if (!AlibabaCloud.TeaUtil.Common.IsUnset(securityToken))
{
request_.Headers["X-Opensearch-Security-Token"] = securityToken;
}
request_.Headers["Authorization"] =
AlibabaCloud.OpenSearchUtil.Common.GetSignature(request_, accesskeyId, accessKeySecret);
_lastRequest = request_;
TeaResponse response_ = TeaCore.DoAction(request_, runtime_);
string objStr = AlibabaCloud.TeaUtil.Common.ReadAsString(response_.Body);
object obj = AlibabaCloud.TeaUtil.Common.ParseJSON(objStr);
Console.WriteLine(objStr);
Dictionary<string, object> res = AlibabaCloud.TeaUtil.Common.AssertAsMap(obj);
if (AlibabaCloud.TeaUtil.Common.Is4xx(response_.StatusCode) ||
AlibabaCloud.TeaUtil.Common.Is5xx(response_.StatusCode))
{
throw new TeaException(new Dictionary<string, object>
{
{"message", response_.StatusMessage},
{"data", res},
{"code", response_.StatusCode},
});
}
return new Dictionary<string, object>
{
{"body", res},
{"headers", response_.Headers}
};
}
catch (Exception e)
{
if (TeaCore.IsRetryable(e))
{
_lastException = e;
continue;
}
throw;
}
}
throw new TeaUnretryableException(_lastRequest, _lastException);
}
}How it works
The
Clientconstructor initializes credentials and connection settings from theConfigobject._requestbuilds aTeaRequestwith the required headers:Date,X-Opensearch-Nonce,Content-MD5(when a body is present), andAuthorization(computed byGetSignature).If a security token is present, it is attached as
X-Opensearch-Security-Token.The retry loop uses the
BackoffPolicyandMaxAttemptssettings fromRuntimeOptions. The default policy is no backoff with a maximum of one attempt.HTTP 4xx and 5xx responses throw a
TeaExceptionwith the status code, status message, and response body.