DevJojo.WAdapter 1.0.0

dotnet add package DevJojo.WAdapter --version 1.0.0
                    
NuGet\Install-Package DevJojo.WAdapter -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="DevJojo.WAdapter" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DevJojo.WAdapter" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="DevJojo.WAdapter" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add DevJojo.WAdapter --version 1.0.0
                    
#r "nuget: DevJojo.WAdapter, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package DevJojo.WAdapter@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=DevJojo.WAdapter&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=DevJojo.WAdapter&version=1.0.0
                    
Install as a Cake Tool

DevJojo.WAdapter

A WhatsApp adapter for Microsoft Bot Framework, enabling seamless integration of WhatsApp messaging with Bot Framework applications.

Overview

DevJojo.WAdapter bridges WhatsApp Business API with Microsoft Bot Framework, allowing you to build sophisticated chatbots that can communicate through WhatsApp using familiar Bot Framework patterns and dialogs.

Features

  • 🤖 Bot Framework Integration: Full compatibility with Microsoft Bot Framework
  • 📱 WhatsApp Native: Support for all WhatsApp message types and features
  • 💬 Rich Conversations: Interactive buttons, lists, and quick replies
  • 🔄 Activity Translation: Seamless conversion between Bot Framework activities and WhatsApp messages
  • 🎯 Dialog Support: Full support for Bot Framework dialogs and conversation flow
  • 📊 Channel Data: Access to WhatsApp-specific features through channel data
  • 🔐 Secure: Built-in webhook validation and security

Installation

Install the package via NuGet Package Manager:

dotnet add package DevJojo.WAdapter

Or via Package Manager Console:

Install-Package DevJojo.WAdapter

Quick Start

Basic Setup

using DevJojo.WAdapter;
using Microsoft.Bot.Builder;
using Microsoft.Extensions.DependencyInjection;

public void ConfigureServices(IServiceCollection services)
{
    // Add Bot Framework services
    services.AddBotFramework();
    
    // Add WhatsApp adapter
    services.AddWhatsAppAdapter(configuration);
    
    // Add your bot
    services.AddTransient<IBot, YourBot>();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // Configure WhatsApp webhook endpoint
    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapPost("/api/whatsapp", async (HttpContext context) =>
        {
            var adapter = context.RequestServices.GetService<WhatsAppAdapter>();
            var bot = context.RequestServices.GetService<IBot>();
            await adapter.ProcessAsync(context.Request, context.Response, bot);
        });
    });
}

Simple Echo Bot

using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;

public class EchoBot : ActivityHandler
{
    protected override async Task OnMessageActivityAsync(
        ITurnContext<IMessageActivity> turnContext, 
        CancellationToken cancellationToken)
    {
        var replyText = $"Echo: {turnContext.Activity.Text}";
        await turnContext.SendActivityAsync(
            MessageFactory.Text(replyText), 
            cancellationToken);
    }
}

WhatsApp-Specific Features

using Wadapter.src.Converter;
using static Wadapter.src.WhatsappAdapter;

public class WhatsAppBot : ActivityHandler
{
    protected override async Task OnMessageActivityAsync(
        ITurnContext<IMessageActivity> turnContext, 
        CancellationToken cancellationToken)
    {
        // Send WhatsApp quick reply
        var quickReplyActivity = MessageFactory.Text(string.Empty);
        quickReplyActivity.ChannelData = new QuickReplyChannelData
        {
            Type = WhatsappMessageTypes.QUICK_REPLY,
            Body = "Choose an option:",
            Buttons = new[]
            {
                new() { Id = "option1", Title = "Option 1" },
                new() { Id = "option2", Title = "Option 2" }
            }
        };
        
        await turnContext.SendActivityAsync(quickReplyActivity, cancellationToken);
    }
}

Configuration

App Settings

{
  "WhatsApp": {
    "ApiBaseUrl": "https://graph.facebook.com/v17.0",
    "PhoneNumberId": "your-phone-number-id",
    "AccessToken": "your-access-token",
    "WebhookVerifyToken": "your-webhook-verify-token"
  },
  "MicrosoftAppId": "",
  "MicrosoftAppPassword": ""
}

Startup Configuration

using Wadapter.Extensions;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Configure WhatsApp adapter
        services.AddWhatsAppServices(Configuration);
        
        // Add Bot Framework
        services.AddBotFramework()
            .AddWhatsAppAdapter();
            
        // Register your bot
        services.AddTransient<IBot, MyBot>();
    }
}

WhatsApp Message Types

Interactive Lists

var listActivity = MessageFactory.Text(string.Empty);
listActivity.ChannelData = new ListChannelData
{
    Type = WhatsappMessageTypes.LIST,
    Heading = "Choose a service:",
    ButtonText = "Services",
    Menus = new[]
    {
        new() { Id = "service1", Title = "Service 1", Description = "Description 1" },
        new() { Id = "service2", Title = "Service 2", Description = "Description 2" }
    }
};

await turnContext.SendActivityAsync(listActivity, cancellationToken);

Quick Replies

var quickReplyActivity = MessageFactory.Text(string.Empty);
quickReplyActivity.ChannelData = new QuickReplyChannelData
{
    Type = WhatsappMessageTypes.QUICK_REPLY,
    Body = "Select your preference:",
    Buttons = new[]
    {
        new() { Id = "yes", Title = "Yes" },
        new() { Id = "no", Title = "No" }
    }
};

await turnContext.SendActivityAsync(quickReplyActivity, cancellationToken);

Media Messages

// Send image
var imageActivity = MessageFactory.Attachment(new Attachment
{
    ContentType = "image/jpeg",
    ContentUrl = "https://example.com/image.jpg",
    Name = "image.jpg"
});

await turnContext.SendActivityAsync(imageActivity, cancellationToken);

// Send document
var documentActivity = MessageFactory.Attachment(new Attachment
{
    ContentType = "application/pdf",
    ContentUrl = "https://example.com/document.pdf",
    Name = "document.pdf"
});

await turnContext.SendActivityAsync(documentActivity, cancellationToken);

Dialog Integration

Waterfall Dialog Example

using Microsoft.Bot.Builder.Dialogs;

public class GreetingDialog : ComponentDialog
{
    public GreetingDialog() : base(nameof(GreetingDialog))
    {
        var waterfallSteps = new WaterfallStep[]
        {
            NameStepAsync,
            ConfirmStepAsync,
            FinalStepAsync
        };

        AddDialog(new WaterfallDialog(nameof(WaterfallDialog), waterfallSteps));
        AddDialog(new TextPrompt(nameof(TextPrompt)));
        AddDialog(new ConfirmPrompt(nameof(ConfirmPrompt)));

        InitialDialogId = nameof(WaterfallDialog);
    }

    private async Task<DialogTurnResult> NameStepAsync(
        WaterfallStepContext stepContext, 
        CancellationToken cancellationToken)
    {
        return await stepContext.PromptAsync(
            nameof(TextPrompt),
            new PromptOptions { Prompt = MessageFactory.Text("What's your name?") },
            cancellationToken);
    }

    private async Task<DialogTurnResult> ConfirmStepAsync(
        WaterfallStepContext stepContext, 
        CancellationToken cancellationToken)
    {
        stepContext.Values["name"] = (string)stepContext.Result;
        
        return await stepContext.PromptAsync(
            nameof(ConfirmPrompt),
            new PromptOptions 
            { 
                Prompt = MessageFactory.Text($"Hello {stepContext.Values["name"]}, is this correct?") 
            },
            cancellationToken);
    }

    private async Task<DialogTurnResult> FinalStepAsync(
        WaterfallStepContext stepContext, 
        CancellationToken cancellationToken)
    {
        if ((bool)stepContext.Result)
        {
            await stepContext.Context.SendActivityAsync(
                MessageFactory.Text($"Great! Nice to meet you, {stepContext.Values["name"]}!"),
                cancellationToken);
        }
        
        return await stepContext.EndDialogAsync(null, cancellationToken);
    }
}

Webhook Handling

The adapter automatically handles WhatsApp webhooks and converts them to Bot Framework activities:

// Webhook endpoint
[HttpPost("api/whatsapp")]
public async Task PostAsync([FromServices] WhatsAppAdapter adapter, [FromServices] IBot bot)
{
    await adapter.ProcessAsync(Request, Response, bot);
}

// Webhook verification
[HttpGet("api/whatsapp")]
public async Task GetAsync([FromServices] WhatsAppAdapter adapter)
{
    await adapter.ProcessAsync(Request, Response, null);
}

Channel Data Types

The adapter provides several channel data types for WhatsApp-specific features:

  • QuickReplyChannelData - Quick reply buttons
  • ListChannelData - Interactive lists
  • MediaChannelData - Media messages with metadata
  • LocationChannelData - Location sharing
  • ContactChannelData - Contact sharing

Error Handling

public class ErrorHandlerBot : IBot
{
    public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken)
    {
        try
        {
            // Bot logic here
        }
        catch (WhatsAppApiException ex)
        {
            await turnContext.SendActivityAsync(
                MessageFactory.Text("Sorry, there was an issue with WhatsApp. Please try again."),
                cancellationToken);
        }
    }
}

Advanced Features

Custom Middleware

public class WhatsAppMiddleware : IMiddleware
{
    public async Task OnTurnAsync(
        ITurnContext turnContext, 
        NextDelegate next, 
        CancellationToken cancellationToken)
    {
        // Pre-processing
        if (turnContext.Activity.ChannelId == "whatsapp")
        {
            // WhatsApp-specific processing
        }
        
        await next(cancellationToken);
        
        // Post-processing
    }
}

State Management

services.AddSingleton<IStorage, MemoryStorage>();
services.AddSingleton<UserState>();
services.AddSingleton<ConversationState>();

Requirements

  • .NET 8.0 or later
  • Microsoft Bot Framework 4.23.0 or later
  • WhatsApp Business API account
  • DevJojo.WApi package

Dependencies

  • DevJojo.WApi (1.0.0) - Core WhatsApp API functionality
  • Microsoft.Bot.Builder.Integration.AspNet.Core (4.23.0) - Bot Framework integration

Supported Activities

The adapter supports the following Bot Framework activity types:

  • Message Activities: Text, media, and interactive messages
  • Event Activities: Member added/removed events
  • Typing Activities: Converted to WhatsApp read receipts
  • End of Conversation: Conversation termination

Best Practices

  1. Use Channel Data: Leverage WhatsApp-specific features through channel data
  2. Handle Errors Gracefully: Implement proper error handling for network issues
  3. Optimize Media: Compress images and videos for better performance
  4. User Experience: Design conversations that work well in WhatsApp's interface
  5. Rate Limiting: Respect WhatsApp's rate limits and implement backoff strategies

Examples

Check out the examples in the repository:

  • Echo Bot
  • Menu-driven Bot
  • Media Handling Bot
  • Dialog Flow Bot

Contributing

We welcome contributions! Please feel free to submit issues, feature requests, or pull requests.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

For support and questions:

  • Create an issue on GitHub
  • Check the Bot Framework documentation
  • Review the WhatsApp Business API documentation

Changelog

v1.0.0

  • Initial release
  • Bot Framework 4.23.0 compatibility
  • WhatsApp message type support
  • Interactive message support
  • Dialog integration
  • Webhook handling

DevJojo.WAdapter - Bringing the power of Microsoft Bot Framework to WhatsApp.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 379 9/17/2025