プログラムの事とか

お約束ですが「掲載内容は私個人の見解です」

WEB PUSHをASP.NETとか使ってC#でやってみる

EdgeもPreview版では対応しているらしいしハードルも当初に比べると下がっているらしいので試してみました

WEB PUSHの詳しいあれこれはググってください、私はよくわかってませんので

今回の記事で出来上がったものはこちらに上げてあります

github.com

簡単な動き

  • サーバー側で公開鍵と秘密鍵を準備する

  • クライアント側で通知先のURLとか作る

  • 通知したい人が上の情報を使って通知する

って感じらしいです

鍵の作り方とかよくわかってないので偉い人の作ってくれたライブラリをつかいましょう

作ってみる

Webサーバー

まずは基本となるWebページをASP.NET MVC5のテンプレート使って準備して

Install-Package WebPush

そのままなやつがNuGetにあるので入れましょう、これが面倒なところをみんなやってくれます。らくちんちんちんですね

クライアント表示時に公開鍵を教えてあげる必要があるのでControllerに処理を書きます

public ActionResult Index()
{
    var model = new HomeModel();
    var pushInformation = PushInformation.Load(AppDomain.CurrentDomain.BaseDirectory + "../info.xml");   // 保存先はてきとうに
    if (pushInformation == null)    // VAPIDで使用する公開鍵を作成
    {
        pushInformation = new PushInformation();
        var vapidKeys = VapidHelper.GenerateVapidKeys();
        pushInformation.VapidPublic = vapidKeys.PublicKey;
        pushInformation.VapipPrivate = vapidKeys.PrivateKey;
        PushInformation.Save(pushInformation, AppDomain.CurrentDomain.BaseDirectory + "../info.xml");    // 作ったら保存しとく
    }
    model.VapidPublic = pushInformation.VapidPublic;
    model.Data = Request.QueryString.Get("data");
    return View(model);
}

あとはクライアントから通知に必要な情報もらう口をつくっておきます

[HttpPost]
public void Post(NotificationTarget target)
{
    var pushInformation = PushInformation.Load(AppDomain.CurrentDomain.BaseDirectory + "../info.xml");  // 保存先はてきとうに
    if (pushInformation == null) return;
    pushInformation.Targets.Remove(pushInformation.Targets.FirstOrDefault(t => t.EndPoint == target.EndPoint));
    pushInformation.Targets.Add(target);
    PushInformation.Save(pushInformation, AppDomain.CurrentDomain.BaseDirectory + "../info.xml");
}

Webクライアント

javascriptを頑張って書きましょう

developers.google.com

この辺参考にすればなんとかなるんじゃないでしょうか

一つ気を付けるのはserviceWorkerに読み込ませるスクリプトはルートに置かないといつまでたっても読み込めない、ってところくらいですね

javascriptだからってScriptsフォルダに入れてもだめだよ!!

ここまで出来たらChromeでページを開いてみます

f:id:puni-o:20180309171412j:plain

通知の許可が出て許可すると購読が始まります

Pushアプリ

コンソールアプリを起動すると起動時パラメーターを上で登録したクライアントにPushするアプリを作ります

Install-Package WebPush
var pushInformation = PushInformation.Load(AppDomain.CurrentDomain.BaseDirectory + "../../../info.xml");  // ASP.NETが保存しているファイルを見ます

var webPushClient = new WebPushClient();
var vapidDetails = new VapidDetails("mailto:yourname@mail.net", pushInformation.VapidPublic, pushInformation.VapipPrivate);
var targetList = pushInformation.Targets.ToArray();
foreach (var target in targetList)
{
    try
    {
        var subscription = new PushSubscription(target.EndPoint, target.PublicKey, target.AuthSecret);
        webPushClient.SendNotification(subscription, args[0], vapidDetails);
    }
    catch (Exception exp)
    {
        if (exp.Message == "Subscription no longer valid")  // 購読者がいなくなるとこんな感じの例外を吐くので送信先から消しておこう
        {
            pushInformation.Targets.Remove(target);
        }
    }
}
PushInformation.Save(pushInformation, AppDomain.CurrentDomain.BaseDirectory + "../../../info.xml");

Webサーバーが保存した情報を使って通知するだけです

実行すると

f:id:puni-o:20180309183143j:plain

通知がやってきて

f:id:puni-o:20180309183202j:plain

ページが開きました

これだけでAndroidChromeだとロックしていても通知受けてくれるようになるんですよね

iOSも頑張ってほしいけど望み薄ですかねー