Implementing DingTalk Webhook Integration
This implementation demonstrates how to send notifications to DingTalk using .NET Core console applications. The solution supports both text and markdown message formats with flexible configuration options.
Required Dependencies
The project requires the following NuGet packages:
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="2.2.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
Configuration Parameter Handling
The application retrieves configuration from both environment variables and command-line arguments:
private static readonly string[] RequiredParams =
{
"WEBHOOK",
"AT_MOBILES",
"IS_AT_ALL",
"MESSAGE",
"MSG_TYPE"
};
private static void Main(string[] args)
{
var configuration = new ConfigurationBuilder()
.AddCommandLine(args)
.AddEnvironmentVariables()
.Build();
// Validate required parameters
foreach (var param in RequiredParams)
{
var value = configuration[param];
if (string.IsNullOrWhiteSpace(value) &&
param != "AT_MOBILES" && param != "IS_AT_ALL")
{
Console.WriteLine($"{param} is required!");
return;
}
}
if (string.IsNullOrWhiteSpace(configuration["AT_MOBILES"]) &&
string.IsNullOrWhiteSpace(configuration["IS_AT_ALL"]))
{
Console.WriteLine("Either AT_MOBILES or IS_AT_ALL must be specified!");
return;
}
try
{
ProcessMessageDelivery(configuration).Wait();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
Message Format Configuration
The application constructs appropriate message payloads based on the specified message type:
private static async Task ProcessMessageDelivery(IConfigurationRoot config)
{
var mentionSettings = new
{
AtMobiles = config["AT_MOBILES"]?.Split(','),
IsAtAll = Convert.ToBoolean(config["IS_AT_ALL"] ?? "false")
};
switch (config["MSG_TYPE"])
{
case "text":
var textPayload = new
{
Msgtype = "text",
Text = new { Content = config["MESSAGE"] },
At = mentionSettings
};
await ExecuteWebhookCall(config["WEBHOOK"], textPayload);
break;
case "markdown":
var markdownPayload = new
{
Msgtype = "markdown",
Markdown = new
{
Title = "DingTalk Notification",
Text = config["MESSAGE"]
},
At = mentionSettings
};
await ExecuteWebhookCall(config["WEBHOOK"], markdownPayload);
break;
default:
Console.WriteLine($"Unsupported message type: {config["MSG_TYPE"]}");
break;
}
}
HTTP Request Execution
The webhook execution method handles JSON serialization and HTTP POST requests:
private static async Task ExecuteWebhookCall<t>(string webhookUrl, T payload) where T : class
{
JsonConvert.DefaultSettings = () => new JsonSerializerSettings()
{
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
var jsonContent = JsonConvert.SerializeObject(payload);
Console.WriteLine(jsonContent);
using (var httpClient = new HttpClient())
{
var requestContent = new StringContent(jsonContent);
requestContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await httpClient.PostAsync(webhookUrl, requestContent);
response.EnsureSuccessStatusCode();
Console.WriteLine($"Webhook call successful. Status: {response.StatusCode}");
}
}
</t>
Docker Container Configuration
The Dockerfile uses multi-stage build for optimized image size:
FROM mcr.microsoft.com/dotnet/runtime:2.2 AS base
WORKDIR /app
FROM mcr.microsoft.com/dotnet/sdk:2.2 AS build
WORKDIR /src
COPY DingTalkSender/DingTalkSender.csproj DingTalkSender/
RUN dotnet restore DingTalkSender/DingTalkSender.csproj
COPY . .
WORKDIR /src/DingTalkSender
RUN dotnet build DingTalkSender.csproj -c Release -o /app
FROM build AS publish
RUN dotnet publish DingTalkSender.csproj -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "DingTalkSender.dll"]
LABEL Description="DingTalk notification sender component"
LABEL InputConfig='{
"WEBHOOK": "Required: DingTalk webhook URL",
"AT_MOBILES": "Optional: Phone numbers to mention",
"IS_AT_ALL": "Optional: Mention all users (true/false)",
"MESSAGE": "Required: Message content",
"MSG_TYPE": "Required: Message type (text/markdown)"
}'
Deployment and Execution
Build and run the container with environment variables:
docker build -t dingtalk-sender:latest .
docker run --rm \
-e "WEBHOOK=https://oapi.dingtalk.com/robot/send?access_token={token}" \
-e "MESSAGE=*Notification from .NET Core application*" \
-e "IS_AT_ALL=true" \
-e "MSG_TYPE=markdown" \
dingtalk-sender