Demo code for building a request

更新时间:
复制 MD 格式

This page shows a complete C# example for authenticating and sending a request to the OpenSearch API, including signing, retry logic, and response handling.

Prerequisites

Before you begin, make sure you have:

  • An Alibaba Cloud account with OpenSearch enabled

  • An AccessKey pair for a Resource Access Management (RAM) user with the AliyunServiceRoleForOpenSearch role granted. See Create a RAM user and Access authorization rules

Important

Use a RAM user's AccessKey pair rather than your Alibaba Cloud account's AccessKey pair. An account-level AccessKey pair grants access to all API operations and poses a higher security risk if leaked. Never include credentials directly in your code.

Set environment variables

Set the following environment variables with your RAM user's AccessKey ID and secret.

  • Linux and macOS

    export ALIBABA_CLOUD_ACCESS_KEY_ID=<access_key_id>
    export ALIBABA_CLOUD_ACCESS_KEY_SECRET=<access_key_secret>
  • Windows

    1. Create an environment variable file and add the ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET variables, set to your AccessKey ID and secret.

    2. Restart Windows for the changes to take effect.

Install dependencies

Install the following NuGet packages. Use the exact versions listed — these four packages must be version-compatible with each other.

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.0

Download packages from https://www.nuget.org/packages.

Note

If you use incompatible package versions, the following error occurs at runtime. Install the exact versions listed above to resolve it.

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)

Sample code

The following example builds and sends a signed HTTP request to the OpenSearch API. The Client class handles credential loading, header construction, request signing, and retry on failure.

// 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();
        // Load credentials from environment variables set earlier.
        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;
        // Build required headers: Date, host, and a nonce for replay protection.
        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))
        {
          // Serialize the request body to JSON and add Content-MD5 for integrity verification.
          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))
        {
          // Include the security token when using STS temporary credentials.
          request_.Headers["X-Opensearch-Security-Token"] = securityToken;
        }

        // Sign the request using the AccessKey ID and secret.
        request_.Headers["Authorization"] =
          AlibabaCloud.OpenSearchUtil.Common.GetSignature(request_, accesskeyId, accessKeySecret);
        _lastRequest = request_;
        TeaResponse response_ = TeaCore.DoAction(request_, runtime_);

        // Parse the response body as JSON.
        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);

        // Throw on 4xx or 5xx status codes.
        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 the code works

The _request method follows this sequence for every API call:

  1. Load credentials — reads ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET from environment variables. If the config includes a security token (for STS temporary credentials), it is retrieved via GetSecurityToken().

  2. Build headers — sets the required HTTP headers: Date, host (defaults to opensearch-cn-hangzhou.aliyuncs.com), and X-Opensearch-Nonce (a one-time value that prevents replay attacks).

  3. Serialize the request body — if the request has a body, it is serialized to JSON. A Content-MD5 header is added for integrity verification, and Content-Type is set to application/json.

  4. Sign the request — the Authorization header is computed from the request using the AccessKey ID and secret. This is required for every API call.

  5. Send and retry — the request is sent via TeaCore.DoAction. If it fails with a retryable error, the loop retries up to MaxAttempts times (default: 1) with the configured backoff policy (default: none). On retry exhaustion, TeaUnretryableException is thrown.

  6. Handle the response — the response body is parsed as JSON. Status codes in the 4xx or 5xx range throw a TeaException with the status code, message, and response data.

SettingDefault value
Endpoint (host header)opensearch-cn-hangzhou.aliyuncs.com
ProtocolHTTP
Credential typeaccess_key
Max retry attempts1
Backoff policyno