在前篇「Microsoft ASP.NET WebHook Preview」中說明透過2個 WebAPI 專案來演示,
Sender 專案需要登入系統後才能將 WebHook 的 URL 註冊到資料庫之中,
但是在實際的應用之中,或許需要的是透過一個簡單的 UI 來管理這些 WebHook 資訊。
本文就介紹如何透過 Windows Forms 程式來新增 WebHook 到 SQL Server 之中,並且發送訊息到 Receiver 專案。
其實 WebHook 就是簡單的 Event Subscriptions 的關係,如下圖,
如上圖所示,我們要新增一個 Windows Forms App 來新增 WebHook Subscriptions 及發送通知。
首先新增 Windows Forms App 專案,然後加入 Microsoft.AspNet.WebHooks.Custom.SqlStorage 套件,
在 app.config 中的 connectionStrings 請加入 MS_SqlStoreConnectionString 的設定,如下,
<connectionStrings>
<add name="MS_SqlStoreConnectionString"
connectionString="Data Source={你的DBServer};Initial Catalog={DB Name};user id={userid};password={password};"
providerName="System.Data.SqlClient" />
</connectionStrings>
在 DB 中,請新增 [WebHooks].[WebHooks] 這個 Table,如下,
CREATE TABLE [WebHooks].[WebHooks](
[User] [nvarchar](256) NOT NULL,
[Id] [nvarchar](64) NOT NULL,
[ProtectedData] [nvarchar](max) NOT NULL,
[RowVer] [timestamp] NOT NULL,
CONSTRAINT [PK_WebHooks.WebHooks] PRIMARY KEY CLUSTERED
(
[User] ASC,
[Id] ASC
)ON [PRIMARY]
)
因為筆者的 Logger 是使用 TraceLogger,所以在 app.config 中也要設定如下,
<system.diagnostics>
<trace autoflush="true" indentsize="4">
<listeners>
<add name="myListener" type="System.Diagnostics.TextWriterTraceListener"
initializeData="TextWriterOutput.log" />
<remove name="Default" />
</listeners>
</trace>
</system.diagnostics>
再來就是拉 UI,如下,
程式中,設定全域變數,如下,
public IWebHookManager Manager { get; set; }
public IWebHookStore Store { get; set; }
public ILogger Logger { get; set; }
Load Method 要初始設定 Logger, Store 及 Manager , 如下,
private void Form1_Load(object sender, EventArgs e)
{
//設定 Logger
Logger = new TraceLogger();
//設定 SQL 來存 WebHook 的資料
Store = SqlWebHookStore.CreateStore(Logger);
//Sender 使用 DataflowWebHookSender
var webhookSender = new DataflowWebHookSender(Logger);
Manager = new WebHookManager(Store, webhookSender, Logger);
}
在「Register WebHook」 Button ,按下後,要新增一個 WebHook 然後呼叫 Store 的 InsertWebHookAsync Method,
將資料存到 SQL Server 之中,如下,
private async void btnRegisterHook_Click(object sender, EventArgs e)
{
var webhook = new WebHook
{
Secret=txtSecret.Text,
WebHookUri=new Uri(txtWebHookUrl.Text),
};
// 這個值在 Send 通知時,會用 ActionId 去 Filter,
// * 或是 ActionId == txtActionFilter.Text
webhook.Filters.Add(txtActionFilter.Text);
var result = await Store.InsertWebHookAsync(txtUserId.Text, webhook);
MessageBox.Show(result.ToString());
}
而在「發送通知」 Button ,按下後,會從 Store 中取出可通知的 WebHook 訂閱資訊,
然後將內容發送給這些 WebHook 訂閱者,如下,
private async void btnSendNotifyAll_Click(object sender, EventArgs e)
{
var notifyBody = JObject.Parse(txtNotifyBody.Text);
//透過 WebHookManager 來傳送通知
var result = await Manager.NotifyAllAsync(txtActionId.Text, notifyBody);
}
測試時,相關的資訊會寫到 bin 目錄中的 TextWriterOutput.log 檔案中,
可以透過 Log 來看傳送是否OK,如下,
筆者在測試過程中,一開始通知並沒有成功,後來看 WebHook Source 才知道 webhook 的 Filters 要給值。
如果您想要知道 NotifyAllAsync 是如何取出要通知的 WebHook 訂閱資料,
可以從 github 「WebHookSaveSendFromWinForms」 下載筆者的測試專案來測試看看。
var notifications = new NotificationDictionary[] { new NotificationDictionary(txtActionId.Text, notifyBody) };
string[] actions = notifications.Select(n => n.Action).ToArray();
Func<WebHook, string, bool> predicate = null;
var webHooks = await Store.QueryWebHooksAcrossAllUsersAsync(actions, predicate);
var wkItems = GetWorkItems(webHooks, notifications);
var webhookSender = new DataflowWebHookSender(Logger);
//webhookSender.SendWebHookWorkItemsAsync 就相當於 foreach ... LaunchWebHook
foreach (var item in wkItems)
{
await LaunchWebHook(item);
}
測試時,請開啟2個VS.NET專案,分別 debug 哦!
註:筆者目前的 Receiver 是使用 MS BOT 的 WebAPI 專案,這樣就可以透過 BOT 通知到使用者。
參考資料
Microsoft ASP.NET WebHook Preview
Hi,
亂馬客Blog已移到了 「亂馬客 : Re:從零開始的軟體開發生活」
請大家繼續支持 ^_^