• Stars
    star
    106
  • Rank 325,871 (Top 7 %)
  • Language
    C#
  • License
    Apache License 2.0
  • Created over 9 years ago
  • Updated about 1 month ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Vonage REST API client for .NET, written in C#. API support for SMS, Voice, Text-to-Speech, Numbers, Verify (2FA) and more.

Vonage Client Library for .NET

Build Status MultiFramework Build Status Quality Gate Status Coverage CodeScene Code Health Mutation testing badge Contributor Covenant

This library allows you to integrate feature from Vonage's APIs to your application.

It requires you to create a Vonage account first.

Installation

Migration guides

Upgrading from v6.x.x to v7.0.0

Disclaimer: Due to a forgotten breaking changes, versions v7.0.0 and v7.1.0 have been unlisted to make v7.2.0 the logical upgrade when migrating towards the new major version.

Please see the dedicated migration guide.

Upgrading from v5.x.x to v6.0.0

Changes in version 6.0.0

  • Enum values are now capitalised in alignment with accepted coding practices and are Pascal Case
  • All classes that were marked as deprecated in 5.x are now removed
  • NCCO now inherits from List, it no longer has the Actions property, to add an action use ncco.Add(action);
  • Strings with values "true" or "false" are now represented as bool in code

Migrating from OpenTok for Video API

If you are migrating from the OpenTok .NET SDK to the Vonage .NET SDK, please see the dedicated migration guide.

Targeted frameworks

The SDK targets towards netstandard2.0. It is compatible with any .NET projects targeting a supported version.

Tested frameworks

  • .NET 6.0
  • .NET 7.0
  • .NET 8.0

For accessibility reasons, we removed all .NET Framework versions from our target frameworks. we don't want to discourage people from contributing as Windows isn't the only development environment for .NET anymore.

Also, targeting older frameworks prevents us from using features from recent .NET and C# releases in our test project.

Nonetheless, it doesn't compromise our test results nor the compatibility with .NET Framework versions.

Configuration

Setup

There are various ways to initialize a VonageClient with your custom values.

Overall, we encourage you to specify your configuration (Vonage URLs, credentials, etc.) in appsettings.json, in an appsettings section:

{
  "vonage": {
    "UserAgent": "myApp/1.0",
    "Url.Rest": "https://rest.nexmo.com",
    "Url.Api": "https://api.nexmo.com",
    "Url.Api.EMEA": "https://api-eu.vonage.com",
    "Url.Api.AMER": "https://api-us.vonage.com",
    "Url.Api.APAC": "https://api-ap.vonage.com",
    "Url.Api.Video": "https://video.api.vonage.com",
    "Api.Key": "VONAGE-API-KEY",
    "Api.Secret": "VONAGE-API-SECRET",    
    "Application.Id": "ffffffff-ffff-ffff-ffff-ffffffffffff",
    "Application.Key": "VONAGE_APPLICATION_PRIVATE_KEY",
    "PooledConnectionIdleTimeout": "60", 
    "PooledConnectionLifetime": "600"
  }
}

The configuration is automatically loaded in the Configuration singleton.

Lazy registration (recommended for .NET Core and above)

Note: This implementation is not available for .NET Framework usages, given IConfiguration has been introduced in .NET Core.

You can register a client in your IServiceCollection using the following extension methods:

  • AddVonageClientScoped: registers using Scoped registration.
  • AddVonageClientTransient: registers using Transient registration.
// For 'Scoped' lifecycle
builder.Services.AddVonageClientScoped(builder.Configuration);
// Foor 'Transient' lifecycle
builder.Services.AddVonageClientTransient(builder.Configuration);

Note: Using builder.Configuration allow us to use settings you decided to load at runtime, including environment-specific settings.

var credentials = ...
// For 'Scoped' lifecycle
builder.Services.AddVonageClientScoped(credentials);
// Foor 'Transient' lifecycle
builder.Services.AddVonageClientTransient(credentials);

It will register the main VonageClient, but also all sub client interfaces:

  • IMessagesClient
  • IVerifyV2Client
  • IMeetingsClient
  • IVoiceClient
  • etc.

Finally, you can inject them in any of your components.

Manual initialization (recommended for .NET Framework)

Create a Vonage Client instance and pass in credentials in the constructor; this will only affect the security credentials (Api Key, Api Secret, Signing Secret, Signing Method Private Key, App Id).

var credentials = Credentials.FromApiKeyAndSecret(
    VONAGE_API_KEY,
    VONAGE_API_SECRET
    );

var vonageClient = new VonageClient(credentials);

If required, you can override values directly in the Configuration singleton:

Configuration.Instance.Settings["vonage:Url.Api"] = "https://www.example.com/api";
Configuration.Instance.Settings["vonage:Url.Rest"] = "https://www.example.com/rest";

Note: Private Key is the literal key - not a path to the file containing the key

Note: Modifying the Configuration instance will be deprecated in the upcoming release, to keep the configuration immutable.

Configuration Reference

Key Description
Api.Key Your API key from the dashboard
Api.Secret Your API secret from the dashboard
Application.Id Your application ID
Application.Key Your application's private key
Security_secret Optional. This is the signing secret that's used for signing SMS
Signing_method Optional. This is the method used for signing SMS messages
Url.Rest Optional. Vonage REST API base URL. Defaults to https://rest.nexmo.com
Url.Api Optional. Vonage API base URL. Defaults to https://api.nexmo.com
Url.Api.EMEA Optional. Vonage API base URL for Europe, Middle East and Africa. Defaults to https://api-eu.vonage.com
Url.Api.AMER Optional. Vonage API base URL for North, Central and South America. Defaults to https://api-us.vonage.com
Url.Api.APAC Optional. Vonage API base URL for Asia and Pacific. Defaults to https://api-ap.vonage.com
Url.Api.Video Optional. Vonage API base URL for Video. Defaults to https://video.api.vonage.com
RequestsPerSecond Optional. Throttle to specified requests per second.
RequestTimeout Optional. The timeout (in seconds) applied to every request. If not provided, the default timeout will be applied.
UserAgent Optional. Your app-specific usage identifier in the format of name/version. Example: "myApp/1.0"
PooledConnectionIdleTimeout Optional. The time (in seconds) that a connection can be idle before it is closed. Defaults to 60 seconds.
PooledConnectionLifetime Optional. The time (in seconds) that a connection can be alive before it is closed. Defaults to 600 seconds.

Logging

The Library uses Microsoft.Extensions.Logging to preform all of it's logging tasks. To configure logging for you app simply create a new ILoggerFactory and call the LogProvider.SetLogFactory() method to tell the Vonage library how to log. For example, to log to the console with serilog you can do the following:

using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using Vonage.Logger;
using Serilog;

var log = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .WriteTo.Console(outputTemplate: "{Timestamp:HH:mm} [{Level}]: {Message}\n")
    .CreateLogger();
var factory = new LoggerFactory();
factory.AddSerilog(log);
LogProvider.SetLogFactory(factory);

Monads

Most recent features expose responses/results using Monads. While the name may be scary at first, this is just another data structure that offers various benefits. We can picture them as a box containing our value, and we manipulate the box instead of manipulating a value.

Their purpose is to provide a value that can have multiple states, and deal with each state using a similar workflow. This is a alternative to exception handling - see Railway Oriented Programming.

Result

The Result<T> monad represents a value that can have one of the following states:

  • Success - indicates the process was a success
  • Failure - indicates the process failed

The goal is to provide an exception-free process.

  • Transparency - the signature is fully transparent about the possible outputs (aka. a method can fail)
  • Less intrusive - no try-catch required
// This method allows to Divide a number
private static Result<decimal> Divide(decimal value, decimal divider) =>
    divider == 0
        // If divider is 0, failure is returned
        ? Result<decimal>.FromFailure(ResultFailure.FromErrorMessage("Cannot divide by 0."))
        // If divider is allowed, success is returned
        : Result<decimal>.FromSuccess(value / divider);

Maybe

The Maybe<T> monad represents a value that can have one of the following states:

  • Some - indicates the presence of a value
  • None - indicates the absence of a value

The goal is to mitigate the 'billion-dollar mistake': null.

// This method allows to retrieve phone number
private static Maybe<PhoneNumber> Find(string number) =>
    this.numbers.FirstOrDefault(phoneNumber => phoneNumber.Number.Equals(number)) 
    ?? Maybe<PhoneNumber>.None;

How to extract a value from a Monad?

Given we cannot predict the state at build-time, we need to provide an operation for each scenario.

The following methods are all available for both Result<T> and Maybe<T>, but examples will focus on Result<T>.

Match

.Match() expects two operations, and will evaluate the one corresponding to the current state. It supports transformation, and can be used with both Actions and Functions.

Result<int> monad = ...
// Supports transformation    
string result = monad.Match(
    // Will be executed if Result<int>.IsSuccess
    some => $"The process is a success: {some}.",
    // Will be executed if Result<int>.IsFailure 
    failure => $"The process is a failure: {failure.GetFailureMessage()}");

// Using Actions    
monad.Match(
    some => Console.WriteLine($"The process is a success: {some}."),
    failure => Console.WriteLine($"The process is a failure: {failure.GetFailureMessage()}"));

IfFailure / IfNone

If you want to retrieve the value without transforming it, you can use .IfFailure() which expects a fallback value in case the state is Failure.

Result<int> monad = ...
// Using the failure reason (recommended)
string result = monad.IfFailure(failure => $"The process is a failure: {failure.GetFailureMessage()}");
// Using a default value
string result = monad.IfFailure("Something failed.");
// Using an Action
monad.IfFailure(failure => Console.WriteLine($"The process is a failure: {failure.GetFailureMessage()}"));    

Features

Both Result<T> and Maybe<T> also exposes more capabilities:

  • Map: transforms the value (if success/some) that will wrap the result into a new Monad.
  • Bind: transforms the value (if success/some) that will return a new Monad.
  • Merge: merges (or flatten) two monads.
  • IfSuccess / IfSome: provide an operation that will be executed if the Monad is in the expected state.
  • IfFailure / IfNone: provide an operation that will be executed if the Monad is in the expected state.
  • Implicit operators
  • Async support
  • etc.

You can see how to benefit from these capabilities in our Tests.

What if you don't want to use Monads?

You can use GetUnsafe() if you prefer having an exception thrown when a Monad is not in the desired state.

Result<int> result = ...
try
{
    int output = result.GetSuccessUnsafe();
}
// The exception type cannot be defined at build-time
// It depends of the failure reason:
// - Authentication failure
// - Serialization/Deserialization failure
// - Http failure
// - Validation failure
// - etc.
catch (Exception exception)
{
    ...
}
Maybe<int> maybe = ...
try
{
    int output = maybe.GetUnsafe();
}
catch (NoneStateException exception)
{
    ...
}

Examples

All snippets are available in a separate repository.

The following examples show how to:

Sending a Message

Use Vonage's SMS API to send an SMS message.

var credentials = Credentials.FromApiKeyAndSecret(
    VONAGE_API_KEY,
    VONAGE_API_SECRET
    );

var vonageClient = new VonageClient(credentials);

var response = await vonageClient.SmsClient.SendAnSmsAsync(new Vonage.Messaging.SendSmsRequest()
{
    To = TO_NUMBER,
    From = VONAGE_BRAND_NAME,
    Text = "A text message sent using the Vonage SMS API"
});

Receiving a Message

Use Vonage's SMS API to receive an SMS message. Assumes your Vonage webhook endpoint is configured.

The best method for receiving an SMS will vary depending on whether you configure your webhooks to be GET or POST. Will Also Vary between ASP.NET MVC and ASP.NET MVC Core.

ASP.NET MVC Core

GET
[HttpGet("webhooks/inbound-sms")]
public async Task<IActionResult> InboundSmsGet()
{
    var inbound = Vonage.Utility.WebhookParser.ParseQuery<InboundSms>(Request.Query);
    return NoContent();
}
POST
[HttpPost("webhooks/inbound-sms")]
public async Task<IActionResult> InboundSms()
{
    var inbound = await Vonage.Utility.WebhookParser.ParseWebhookAsync<InboundSms>(Request.Body, Request.ContentType);
    return NoContent();
}

ASP.NET MVC

GET
[HttpGet]
[Route("webhooks/inbound-sms")]
public async Task<HttpResponseMessage> GetInbound()
{
    var inboundSms = WebhookParser.ParseQueryNameValuePairs<InboundSms>(Request.GetQueryNameValuePairs());
    return new HttpResponseMessage(HttpStatusCode.NoContent);
}
POST
[HttpPost]
[Route("webhooks/inbound-sms")]
public async Task<HttpResponseMessage> PostInbound()
{
    var inboundSms = WebhookParser.ParseWebhook<InboundSms>(Request);
    return new HttpResponseMessage(HttpStatusCode.NoContent);
}

Receiving a Message Delivery Receipt

Use Vonage's SMS API to receive an SMS delivery receipt. Assumes your Vonage webhook endpoint is configured.

The best method for receiving an SMS will vary depending on whether you configure your webhooks to be GET or POST. Will Also Vary between ASP.NET MVC and ASP.NET MVC Core.

ASP.NET MVC Core

GET
[HttpGet("webhooks/dlr")]
public async Task<IActionResult> InboundSmsGet()
{
    var dlr = Vonage.Utility.WebhookParser.ParseQuery<DeliveryReceipt>(Request.Query);
    return NoContent();
}
POST
[HttpPost("webhooks/dlr")]
public async Task<IActionResult> InboundSms()
{
    var dlr = await Vonage.Utility.WebhookParser.ParseWebhookAsync<DeliveryReceipt>(Request.Body, Request.ContentType);
    return NoContent();
}

ASP.NET MVC

GET
[HttpGet]
[Route("webhooks/dlr")]
public async Task<HttpResponseMessage> GetInbound()
{
    var dlr = WebhookParser.ParseQueryNameValuePairs<DeliveryReceipt>(Request.GetQueryNameValuePairs());
    return new HttpResponseMessage(HttpStatusCode.NoContent);
}
POST
[HttpPost]
[Route("webhooks/dlr")]
public async Task<HttpResponseMessage> PostInbound()
{
    var dlr = WebhookParser.ParseWebhook<DeliveryReceipt>(Request);
    return new HttpResponseMessage(HttpStatusCode.NoContent);
}

Redacting a message

Use Vonage's Redact API to redact a SMS message.

var credentials = Credentials.FromApiKeyAndSecret(VONAGE_API_KEY, VONAGE_API_SECRET);
var client = new VonageClient(credentials);
var request = new RedactRequest() { Id = VONAGE_REDACT_ID, Type = VONAGE_REDACT_TYPE, Product = VONAGE_REDACT_PRODUCT };
var response = await client.RedactClient.RedactAsync(request);

Initiating a Call

Use Vonage's Voice API to initiate a voice call.

NOTE: You must have a valid Application ID and private key in order to make voice calls. Use either Vonage.Application or Vonage's Node.js-based CLI tool to register. See the Application API documentation for details.

var creds = Credentials.FromAppIdAndPrivateKeyPath(VONAGE_APPLICATION_ID, VONAGE_PRIVATE_KEY_PATH);
var client = new VonageClient(creds);

var command = new CallCommand() { To = new Endpoint[] { toEndpoint }, From = fromEndpoint, AnswerUrl=new[] { ANSWER_URL}};
var response = await client.VoiceClient.CreateCallAsync(command);

Receiving a Call

Use Vonage's Voice API to receive a voice call.

[HttpGet("webhooks/answer")]
public string Answer()
{
    var talkAction = new TalkAction()
    {
        Text = $"Thank you for calling from " +
        $"{string.Join(" ", Request.Query["from"].ToString().ToCharArray())}"
    };
    var ncco = new Ncco(talkAction);
    return ncco.ToString();
}

Get Details About a Call

var credentials = Credentials.FromAppIdAndPrivateKeyPath(VONAGE_APPLICATION_ID, VONAGE_PRIVATE_KEY_PATH);
var client = new VonageClient(credentials);

var response = await client.VoiceClient.GetCallAsync(UUID);

Sending 2FA Code

Use Vonage's Verify API to send 2FA pin code.

var credentials = Credentials.FromApiKeyAndSecret(VONAGE_API_KEY, VONAGE_API_SECRET);
var client = new VonageClient(credentials);

var request = new VerifyRequest() { Brand = BRAND_NAME, Number = RECIPIENT_NUMBER };
var response = await client.VerifyClient.VerifyRequestAsync(request);

Checking 2FA Code

Use Vonage's Verify API to check 2FA pin code.

var credentials = Credentials.FromApiKeyAndSecret(VONAGE_API_KEY, VONAGE_API_SECRET);
var client = new VonageClient(credentials);

var request = new VerifyCheckRequest() { Code = CODE, RequestId = REQUEST_ID };
var response = await client.VerifyClient.VerifyCheckAsync(request);

Supported APIs

The following is a list of Vonage APIs and whether the Vonage .NET SDK provides support for them:

API API Release Status Supported?
Account API General Availability
Alerts API General Availability
Application API General Availability
Audit API Beta
Conversation API Beta
Dispatch API Beta
External Accounts API Beta
Media API Beta
Meetings API General Availability
Messages API General Availability
Number Insight API General Availability
Number Insight V2 API General Availability
Number Management API General Availability
Pricing API General Availability
Proactive Connect API General Availability
Redact API Developer Preview
Reports API Beta
SMS API General Availability
SubAccounts API General Availability
Users API General Availability
Verify API General Availability
Verify V2 API General Availability
Video API General Availability
Voice API General Availability

Contributing

Pick your preferred IDE:

  • Visual Studio (Community is fine)
  • Visual Studio Code
  • Jetbrains Rider

Keep in mind the SDK is built on netstandard2.0 and tested against several framework versions (.NET6.0 and above). Therefore, they should be installed on your machine for tests to run.

  1. Get the latest code either by cloning the repository or downloading a snapshot of the source.
  2. Open "Vonage.sln"
  3. Build! NuGet dependencies should be brought down automatically; check your settings if they are not.
  4. Tests! Run all the tests to verify everything's fine.

Pull requests are welcome!

License

This library is released under the MIT License.

More Repositories

1

vonage-php-sdk-core

Vonage REST API client for PHP. API support for SMS, Voice, Text-to-Speech, Numbers, Verify (2FA) and more.
PHP
917
star
2

vonage-node-sdk

Vonage API client for Node.js. API support for SMS, Voice, Text-to-Speech, Numbers, Verify (2FA) and more.
TypeScript
382
star
3

vonage-ruby-sdk

Vonage REST API client for Ruby. API support for SMS, Voice, Text-to-Speech, Numbers, Verify (2FA) and more.
Ruby
218
star
4

vonage-python-sdk

Vonage Server SDK for Python. API support for Voice, SMS, WhatsApp, Verify (2FA), Video Meetings and more.
Python
193
star
5

Grafana_Status_panel

A panel plugin for Grafana to monitor multiple parameters at once
TypeScript
179
star
6

vonage-php-sdk

Wrapper package to bring in the vonage/client-core code and an HTTP client
109
star
7

vonage-java-sdk

Vonage Server SDK for Java. API support for SMS, Messages, Voice, Text-to-Speech, Numbers, Verify (2FA), Video and more.
Java
97
star
8

vonage-node-code-snippets

NodeJS code examples for using Vonage
JavaScript
70
star
9

vivid-3

Vonage's web UI 🎨 toolbelt
TypeScript
54
star
10

vonage-go-sdk

A lightweight library to help Go users everywhere integrate with the Vonage APIs. Issues and PRs all really welcome!!
Go
51
star
11

vivid

Vonage's web UI 🎨 toolbelt
JavaScript
42
star
12

rxzu

RxZu Diagrams
TypeScript
41
star
13

vonage-laravel

Laravel Service Provider for integrating Vonage APIs
PHP
34
star
14

vonage-python-code-snippets

Python code examples for using Vonage communications APIs
Python
32
star
15

vonage-php-code-snippets

PHP code examples for using Vonage APIs
PHP
29
star
16

micro-frontends

TypeScript
27
star
17

vonage-curl-code-snippets

Curl examples for working with Vonage APIs
Shell
26
star
18

gosrvlib

Go library to provide base service components
Go
20
star
19

vonage-cli

Vonage CLI tool.
TypeScript
18
star
20

vonage-java-code-snippets

Java code examples for using Vonage
Java
11
star
21

vonage-dotnet-code-snippets

.NET code samples for using Nexmo
C#
11
star
22

kafka-glue

Kafka Glue is a collection of libraries for kafka consumers and producers integrated with AWS Glue schema registry with RXJS to expose streaming of the kafka.
TypeScript
8
star
23

vonage-ruby-code-snippets

Ruby code examples for working with Vonage
Ruby
8
star
24

vbc-developer

Vonage Developer Portal documentation
HTML
6
star
25

vivid-react

Typescript friendly Reactjs :atom: wrappers/bindings for Vonage's web UI 🎨 toolbelt
JavaScript
5
star
26

acl-express

A stateless Access Control List middleware for Express
JavaScript
5
star
27

vonage-go-code-snippets

Repo of "howto" examples for using Vonage APIs with Go.
Go
4
star
28

cloud-runtime-cli

Vonage cloud runtime - CLI
Go
4
star
29

vonage-firebase-extensions

Firebase Extensions created by Vonage
JavaScript
3
star
30

sippy

A mirror of python-sippy b2bua library (and rtp_cluster): http://b2bua.org/
Python
3
star
31

aws-systems-manager-toolkit

aws-systems-manager-toolkit is a Python library that provides wrapper tools around AWS Systems Manager functionality.
Python
3
star
32

verify-silent-auth-sdk-android

This SDK enables making a HTTP request over cellular even when on WiFi.
Kotlin
3
star
33

vonage-media-transformers-samples

Vonage Media Transformers Examples
TypeScript
3
star
34

numkey

Numerical Encoding for Short Codes or E.164 LVN
C
3
star
35

video-express-plus-sample

This Repository demonstrates how to use Vonage Video Express Plus
HTML
2
star
36

vonage-python-jwt

A JWT Generator for Python. Creates JWTs for use with Vonage APIs.
Python
2
star
37

vivid-bindings-vue

Fully automated typescript bindings generated for Vivid web components to be used in VueJS
TypeScript
2
star
38

vivid-react-wrapper

A thin wrapper around an arbitrary custom HTML element to mitigate the gaps in :atom: React versions until 19.x
TypeScript
2
star
39

vonage-client-sdk-ios

Swift
1
star
40

vscode

A Visual Studio Code extension for accessing the Vonage communication APIs.
TypeScript
1
star
41

api-specification

JavaScript
1
star
42

cli-plugin-scaffold

TypeScript
1
star
43

vivid-design-tokens-properties

JavaScript
1
star
44

exprees-socket-server

JavaScript
1
star
45

vonage-jwt-jdk

Library to assist with generating JWT tokens in JVM-based languages for use with the Vonage API.
Kotlin
1
star
46

vonage-kotlin-sdk

Vonage Server SDK for Kotlin. API support for SMS, RCS, Messages, Voice, Text-to-Speech, Numbers, Verify (2FA), Video and more.
Kotlin
1
star