前言
上一篇我们通过实战分享了使用Go推送钉钉消息,由于技痒,笔者现在也编写了一个.NET Core的Demo,作为简单的对照和说明。
最后,由于精力有限,笔者希望有兴趣的朋友可以分享下使用CoreRT将.NET Core编译成机器代码这块的实践。
目录
使用.NET Core推送钉钉消息
获取参数
设置消息数据格式
发送请求
设置Dockerfile
运行并设置环境变量推送消息
使用.NET Core推送钉钉消息
这里我们使用.NET Core来完成相关需求,注意,这里是.NET Core,而不是ASP.NET Core。需求和上面类似,工程相关依赖如下所示:
<PackageReferenceInclude="Microsoft.Extensions.Configuration"Version="2.2.0"/>
<PackageReferenceInclude="Microsoft.Extensions.Configuration.CommandLine"Version="2.2.0"/>
<PackageReferenceInclude="Microsoft.Extensions.Configuration.EnvironmentVariables"Version="2.2.0"/>
<PackageReferenceInclude="Microsoft.Extensions.Http"Version="2.2.0"/>
<PackageReferenceInclude="Newtonsoft.Json"Version="12.0.1"/>
以下是相关的主体代码:
获取参数
从环境变量或者命令行参数获取配置:
///<summary>///环境变量列表
///</summary> privatestaticreadonlystring[] EnvList = {
//钉钉机器人地址"WEBHOOK",
//@的手机号码"AT_MOBILES",
//@所有人"IS_AT_ALL",
//消息内容"MESSAGE",
//消息类型(仅支持文本和markdown)"MSG_TYPE" };
privatestaticvoid Main(string[] args)
{
varconfig = newConfigurationBuilder()
//支持命令行参数 .AddCommandLine(args)
//支持环境变量 .AddEnvironmentVariables()
.Build();
#region参数检查
foreach(varenvNamein EnvList)
{
varvalue =config[envName];
if(string.IsNullOrWhiteSpace(value)&& envName !="AT_MOBILES"&& envName !="IS_AT_ALL")
{
Console.WriteLine($"{envName}不能为空!");
return;
}
}
if(string.IsNullOrWhiteSpace(config["AT_MOBILES"]) &&string.IsNullOrWhiteSpace(config["IS_AT_ALL"]))
{
Console.WriteLine("必须设置参数 AT_MOBILES 和 IS_AT_ALL 两者之一!");
return;
}
#endregiontry {
//推送消息 SetDataAndSendWebhooks(config).Wait();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
设置消息数据格式
设置消息格式,为了简单,这里我们使用匿名类:
///<summary>///设置消息并调用Webhook
///</summary>///<param name="config"></param>///<returns></returns> privatestaticasync Task SetDataAndSendWebhooks(IConfigurationRoot config)
{
varat =new {
AtMobiles = config["AT_MOBILES"]?.Split(','),
IsAtAll = Convert.ToBoolean(config["IS_AT_ALL"] ??"false")
};
switch(config["MSG_TYPE"])
{
case"text":
{
vardata =new {
Msgtype ="text",
Text =new {
Content =config["MESSAGE"]
},
At = at
};
awaitSendWebhooks(config["WEBHOOK"], data);
break;
}
case"markdown":
{
vardata =new {
Msgtype ="markdown",
Markdown =new {
Title ="钉钉通知",
Text = config["MESSAGE"]
},
At = at
};
awaitSendWebhooks(config["WEBHOOK"], data);
break;
}
default:
{
Console.WriteLine($"不支持的格式:{config["MSG_TYPE"]}");
break;
}
}
}
发送请求
此处代码使用Newtonsoft.Json做JSON序列化,然后使用Microsoft.Extensions.Http的HttpClient库来发送Post请求。
在数据格式这块,我们通过配置做了以下设置:
忽略Null值。也就是为null的属性不做JSON序列化。
设置属性命名规则为Camel-Case驼峰式命名法,首字母小写。
主体代码如下所示:
///<summary>///调用webhook
///</summary>///<typeparamname="T"></typeparam>///<param name="url">webhook地址</param>///<param name="data">消息</param>///<returns></returns> privatestaticasync Task SendWebhooks(stringurl, T data)whereT :class {
JsonConvert.DefaultSettings = newFunc(() =>newJsonSerializerSettings()
{
NullValueHandling =NullValueHandling.Ignore,
ContractResolver = newCamelCasePropertyNamesContractResolver()
});
varjsonData =JsonConvert.SerializeObject(data);
Console.WriteLine(jsonData);
using(varhttpClient =new HttpClient())
{
varcontent = newStringContent(jsonData);
content.Headers.ContentType = newMediaTypeHeaderValue("application/json");
varresult = awaithttpClient.PostAsync(url, content);
result.EnsureSuccessStatusCode();
Console.WriteLine($"Send webhook succeed. StatusCode:{result.StatusCode}");
}
}
设置Dockerfile
在之前我们已经讲述过,使用了分阶段构建。整个Dockerfile基本上使用VS Docker tool生成:
FROMmicrosoft/dotnet:2.2-runtime ASbaseWORKDIR /app
FROMmicrosoft/dotnet:2.2-sdk AS build
WORKDIR /src
COPY DingTalk.NET/DingTalk.NET.csprojDingTalk.NET/RUN dotnet restoreDingTalk.NET/DingTalk.NET.csproj
COPY . .
WORKDIR /src/DingTalk.NET
RUN dotnet buildDingTalk.NET.csproj -c Release -o /app
FROM build AS publish
RUN dotnet publish DingTalk.NET.csproj-c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish/app .
ENTRYPOINT ["dotnet","DingTalk.NET.dll"]
# 注意不要单独使用 MAINTAINER 指令,MAINTAINER已被Label标签代替
LABEL MAINTAINER ="xinlai@xin-lai.com"# LABEL指令用于将元数据添加到镜像,支持键值对和JSON,我们可以使用 docker inspect 命令来查看
LABELDingtalkComponent='{\"description":"使用钉钉发送通知消息.",\
"input": [\
{"name":"WEBHOOK","desc":"必填, 钉钉机器人Webhook地址"},\
{"name":"AT_MOBILES","desc":"非必填,被@人的手机号"},\
{"name":"IS_AT_ALL","desc":"非必填,@所有人时:true, 否则为:false"},\
{"name":"MESSAGE","desc":"必填,自定义发送的消息内容"},\
{"name":"MSG_TYPE","desc":"必填,自定义发送的消息类型,目前仅支持text和markdown"}\
]\
}'
编译完成后,我们来查看下镜像大小:
注意:
通过上图我们可以看到,镜像大小不到200M,相比GO体重大了许多,但是相比其他语言却轻了不少。不过,我们可以通过官方开源库CoreRT将.NET Core编译成机器代码,也就是.NET Core也可以做到编译完成后只有几M大小。有兴趣的朋友可以分享下这块的实践。
运行并设置环境变量推送消息
我们使用PowerShell编写简单脚本如下所示:
docker build --rm-f"Dockerfile"-t dingtalk.net:latest .
docker run --rm -e"WEBHOOK=https://oapi.dingtalk.com/robot/send?access_token={yourAccess Token}" `
-e"MESSAGE=*使用.NET Core发送钉钉消息。*" `
-e"IS_AT_ALL=true" `
-e"MSG_TYPE=markdown" `
-d dingtalk.net
效果如图: