tekitoumemo’s diary

C#、.NET系の技術ブログを書いています。みんなの洋楽ランキングを運営しています。

AzureでSendGridを扱う

https://sendgrid.kke.co.jp/blog/wp/wp-content/uploads/2016/09/SG_Logo_Blog.jpg

SendGridイイね!

Azure App Service on Linuxに移行する為にテストをしていたところ、メール送信に失敗するようになりました( ゚д゚)
tekitoumemo.hatenablog.com
色々調べてみるとAzureではメール送信を推奨していないことがわかりました。
Azure 上にメールサーバー/SMTP サーバーを構築する場合の注意事項 – Japan Azure IaaS Support Blog

Azure 上の VM から、外部ドメインに対して直接 SMTP 等を使ってメール送信することは、Azure プラットフォームとしてサポートをしておりません。

メールが失敗する原因がAzureのせいじゃないとは思うのですが、原因特定に力を使っても意味がないのでこの際Slackやらに通知する方法を考えていたのですが、「SendGrid使ってみたい!」と思ったのでSendGridにしました。stackoverflowに質問投げたのですが、ビビるほど音沙汰がないので知ってる人いたら教えて欲しいです(TLSで弾かれてるとこまではわかった)。
ja.stackoverflow.com

ということでAzureで動くまで説明します。

AzureでSendGridアカウントを作成する

SendGrid Accountsの[追加]を押下してアカウントを作成します。Resource Groupまで適当に入れてください。
f:id:tekitoumemo:20181017000439p:plain
pricing tierをクリックするとプランが出てきます。25000通まで無料(安杉)なのでFreeを選びました。
f:id:tekitoumemo:20181017000706p:plain
Contact Informationには、名前やら自分の情報を入れてください。
f:id:tekitoumemo:20181017000821p:plain
法律条例は[作成]を押下すると同意したことになるので同意しましょう。
f:id:tekitoumemo:20181017001005p:plain

SendGrid管理画面でAPIキーを発行

デプロイが完了したらリソースに移動して[Manage]を押下するとSendGridの管理画面に遷移します。
f:id:tekitoumemo:20181017001342p:plain
管理画面に移動したらメニューのSettingsを押下してApiKeyをクリックします。
f:id:tekitoumemo:20181017001504p:plain
Create API Keyを押下して、権限やらを設定します。発行したAPI Keyは一度しか見れないので厳重に保管しておいてください。
f:id:tekitoumemo:20181017001628p:plain

コード

C#用のSendGridライブラリがあるのでNugetから取ってきます。

dotnet add package Sendgrid --version 9.10.0

www.nuget.org

コードは以下です。

var apiKey = "{発行したAPI Key}";
var client = new SendGridClient (apiKey);
var msg = new SendGridMessage () {
    From = new EmailAddress ("{メールアドレス}"),
    Subject = "Hello World from the SendGrid CSharp SDK!",
    PlainTextContent = "Hello, Email!",
    HtmlContent = "<strong>Hello, Email!</strong>"
};
msg.AddTo (new EmailAddress ("{メールアドレス}"));
var response = await client.SendEmailAsync (msg);

response.StatusCodeで送信出来たか確認できます。

あとは管理画面でメールが送信されたか確認出来ます。

感想

SendGridは知ってましたが、一休のブログとか見てると大規模サービスに使われるクラウドぐらいの感覚でしかなかったのですが
25000通まで無料なので気軽にいじれてよかったです。
user-first.ikyu.co.jp
日本語の情報が多く、値段も手頃なのでかなり気に入りました。
f:id:tekitoumemo:20181017003657p:plain

最近の記事で気になったこと

日本語の検索結果を排除する設定にせざるを得なくなってる

すごいなこれ。技術ブログを書くのに億劫になってる人ってこういうやつがいるからなんだろうな。好きに書きなさいよまったく。っか記事の絶対数が少なすぎるだけで、外国人は仕事中に書いてるから多いんだろ!羨ましい!


同意。俺も勉強会きらいー。勉強会に行く人は、技術オタクか無駄に意識高い系か出会い厨(異性を探す以外に人脈増やしたがる人も含む)しかいないんで、一部の人にあたったのかなーと。っか仕事終わって勉強会行く人謎。家帰って寝っ転がりながらパソコン開いてる方がよっぽど楽なのに。



これ、何年議論されてんのか謎。

これも。

「だからここら辺はまじめに勉強するのが嫌いなんだよねー。」



seo系の記事ってなんでちゃんと内容書いてくれないのか。その過程を知りたいんだが。普通にseo困ってんのにこの記事見てスマホカチ割りそうになった


結論「学歴は関係ない」

嬉しいね、こういう記事。

結論「クッソ勉強すれば高学歴と同じレベルもしくは超えられるよ」

は?結局勉強しなきゃいけないの?


この人は前提でしっかりツッコミどころをなくしているのでこの記事は良い記事だな。知り合い経由で転職はちょっと微妙だけど

結論

記事に対して物申す人はクソ(え

Azure Logic Appsを試す

https://azure.microsoft.com/svghandler/logic-apps?width=600&height=315

Azure Logic Appsを導入しました。なぜ導入したかと言うと以前に書いたAzure Schedulerが2019年9月で終了するからです。
tekitoumemo.hatenablog.com
こんなメールきてびっくりしました。Azure Scheduler作った時に教えてよ!って感じですがまぁ良いです。
f:id:tekitoumemo:20181011223709p:plain

Azure Logic Appsとは

AzureのサービスやいろんなAPIやらを組み合わせてサービス作れるよってやつです。

業務上重要なアプリやサービスを Azure Logic Apps に接続して、コードを 1 行も書かずにワークフローを自動化します。

が謳い文句ってやつでしょうか。
azure.microsoft.com

導入方法

AppServiceから「Logic App」とフィルタかけると見つかります。
f:id:tekitoumemo:20181011224334p:plain

トリガーを作る

「ロジック アプリ デザイナー」から作ります。
f:id:tekitoumemo:20181011224529p:plain

あまり説明するところはないのですが、スケジュール決めてあとは好き勝手にHTTPやらAzureやらいろんな物を組み合わせてくサービスです。最近流行ってるRPAツールですね。

スケジュール

f:id:tekitoumemo:20181011224933p:plain

HTTP

f:id:tekitoumemo:20181011225001p:plain

なんかいっぱいある

f:id:tekitoumemo:20181011225039p:plain

値段

僕の場合は3(アクション)×24(毎時)×30(日)で2160(アクション)回動かすので以下でした。
f:id:tekitoumemo:20181011225602p:plain
6円?安くね?ほんとこれ?ちょっと疑問はありますがまぁ値段かかってから確認します。

よくわかってない

トリガーってAppServiceごとにしか作れないのだろうか?
まぁいつか調べます(絶対調べない)

感想

AzureのサービスはAzure Schedulerみたいな微妙なサービスがいっぱいあるのでおそらくここに統合されたサービスがいっぱいあると思います。なのでAzure Logic Appsをみて物足りなかったら他を探すでいいかなと思いました。Azure Schedulerとか1500円したので高杉。

後日

1週間でかかった値段
f:id:tekitoumemo:20181017215857p:plain
ひと月8円かかる計算(安杉
トリガーも複数設定できるみたいなのですが、デザイナーからは出来ないようです。

Azure App Service on Linuxで.Net Coreアプリを公開

https://msdnshared.blob.core.windows.net/media/2017/05/1-TryAppLinuxLanding.png

.Net Coreアプリ作ったのならLinuxで公開したい!って思ったものの、あまり必要性が感じられなかったので手付かずだったのですが値段見たらまぁびっくり!

Linux

f:id:tekitoumemo:20181010214208p:plain

3000円近くも変わるじゃん!前はほぼ値段変わらなかったのになぜにこんな差が。。まぁそんなこんなでみんなの洋楽ランキングLinuxサーバに移行計画を立てました。PaaSだからGithubブランチ指定してすんなり行くと思いきや、まったくダメで情報も全然無くて結構大変だったので丁寧に書いておきます。

Web Appをたてる

OSはLinux、公開はコード、ランタイムスタックは.Net Core 2.1で。Dockerの方が値段安いっぽいけどちゃんと調べてないから次回へ(たぶんやる)。しかも今ならB1インスタンスが1ヶ月無料なのでやりたい放題っす。
f:id:tekitoumemo:20181010215008p:plain

Githubのブランチからデプロイ

Github、Bitbucket、その他もろもろから合ったものを選んでください。
f:id:tekitoumemo:20181010221240p:plain
ブランチにPushされたら勝手にデプロイされます。

エラーが出る

f:id:tekitoumemo:20181010221727p:plain
はい、ダメでした。原因を探ります。失敗したところをクリックすると以下の画面が表示されます。ログを表示をクリックします。
f:id:tekitoumemo:20181010222118p:plain
f:id:tekitoumemo:20181010222210p:plain
「Object reference not set to an instance of an object」とでます。おなじみのメッセージですが、意味不明です。これはプロジェクトにsln(ソリューション)ファイルを含めるとkuduが解析出来ないのでダメみたいです。slnを消してプロジェクトを一つにすれば問題ないのですが、テストやライブラリなど複数のプロジェクトがあることが多いのでプロジェクトを一つにする方法はイケてませんし、マルチプラットフォームの意味がないですね。みんなの洋楽ランキングもDapperの自作拡張ライブラリ、定期更新系のAPIライブラリ、テストなどプロジェクトが分かれているので一つにする選択肢はありません。これを回避する方法があります。

ちなみにkuduとは

f:id:tekitoumemo:20181010223638p:plain
Kudu is the engine behind git deployments in Azure App Service.
Kuduは、Azure App Serviceのgitデプロイメントの背後にあるエンジンです。(翻訳ママ)

.deploymentファイルとCustom Deployment Scriptを設置する

Custom Deployment Scriptを準備

deploy.shファイルのWebApplication1はプロジェクトに合わせて変えてください。deploy.shはシェルスクリプトなんで名前はなんでもよいです。

#!/bin/bash

# ----------------------
# KUDU Deployment Script
# Version: 1.0.13
# ----------------------

# Helpers
# -------

exitWithMessageOnError () {
  if [ ! $? -eq 0 ]; then
    echo "An error has occurred during web site deployment."
    echo $1
    exit 1
  fi
}

# Prerequisites
# -------------

# Verify node.js installed
hash node 2>/dev/null
exitWithMessageOnError "Missing node.js executable, please install node.js, if already installed make sure it can be reached from current environment."

# Setup
# -----

SCRIPT_DIR="${BASH_SOURCE[0]%\\*}"
SCRIPT_DIR="${SCRIPT_DIR%/*}"
ARTIFACTS=$SCRIPT_DIR/../artifacts
KUDU_SYNC_CMD=${KUDU_SYNC_CMD//\"}

if [[ ! -n "$DEPLOYMENT_SOURCE" ]]; then
  DEPLOYMENT_SOURCE=$SCRIPT_DIR
fi

if [[ ! -n "$NEXT_MANIFEST_PATH" ]]; then
  NEXT_MANIFEST_PATH=$ARTIFACTS/manifest

  if [[ ! -n "$PREVIOUS_MANIFEST_PATH" ]]; then
    PREVIOUS_MANIFEST_PATH=$NEXT_MANIFEST_PATH
  fi
fi

if [[ ! -n "$DEPLOYMENT_TARGET" ]]; then
  DEPLOYMENT_TARGET=$ARTIFACTS/wwwroot
else
  KUDU_SERVICE=true
fi

if [[ ! -n "$KUDU_SYNC_CMD" ]]; then
  # Install kudu sync
  echo Installing Kudu Sync
  npm install kudusync -g --silent
  exitWithMessageOnError "npm failed"

  if [[ ! -n "$KUDU_SERVICE" ]]; then
    # In case we are running locally this is the correct location of kuduSync
    KUDU_SYNC_CMD=kuduSync
  else
    # In case we are running on kudu service this is the correct location of kuduSync
    KUDU_SYNC_CMD=$APPDATA/npm/node_modules/kuduSync/bin/kuduSync
  fi
fi

if [ "x$DEPLOYMENT_TEMP" = x ]; then
    DEPLOYMENT_TEMP=/tmp/`date +%s`
    CLEAN_LOCAL_DEPLOYMENT_TEMP=true
fi

if [ "x$CLEAN_LOCAL_DEPLOYMENT_TEMP" = xtrue ]; then
    rm -rf "$DEPLOYMENT_TEMP"
    mkdir "$DEPLOYMENT_TEMP"
fi
##################################################################################################################################
# Deployment
# ----------

echo Handling ASP.NET Core Web Application deployment.

# 1. Restore nuget packages
dotnet restore "WebApplication1/WebApplication1.csproj"
exitWithMessageOnError "dotnet restore failed"

# 2. Build and publish
dotnet publish "WebApplication1/WebApplication1.csproj" --output "$DEPLOYMENT_TEMP" --configuration Release
exitWithMessageOnError "dotnet publish failed"

# 3. KuduSync
"$KUDU_SYNC_CMD" -v 50 -f "$DEPLOYMENT_TEMP" -t "$DEPLOYMENT_TARGET" -n "$NEXT_MANIFEST_PATH" -p "$PREVIOUS_MANIFEST_PATH" -i ".git;.hg;.deployment;deploy.sh"
exitWithMessageOnError "Kudu Sync failed"


##################################################################################################################################
echo "Finished successfully."
.deploymentファイルを準備

.deploymentファイルはデプロイ時に実行されるスクリプトを記述するファイル(正直よくわかってない)で先ほど準備したCustom Deployment Scriptを指定します。フルパスにしないとNot Foundが出るのでちゃんと指定します。

[config]
command = /home/site/repository/deploy.sh

準備が出来たらPushしてください。

Custom Deployment Scriptは以下を参考に
github.com

再度デプロイする

次はデプロイが成功するはずなので、サイトを見に行きます。
f:id:tekitoumemo:20181010230041p:plain
そうするとサイトが立ち上がりません。
f:id:tekitoumemo:20181010230126p:plain
MVCテンプレ作ってデプロイしたらちゃんと動いたので、謎です。

スタートアップ ファイルを指定する

[アプリケーションの設定]からスタートアップ ファイルを指定します。ここで重要なのは、各フレームワークによって指定の仕方が違います。.Net Coreは以下の通りです。こんな記述方法知らんがな。

dotnet <myapp>.dll

ここにフレームワーク毎の指定方法が書いてあります。
docs.microsoft.com

サイトを確認する(二度目)

f:id:tekitoumemo:20181010230857p:plain
はい。動いたけど動いていません(え
心折れそうになったんですが、一つ心当たりが合ったのでそれを実施しました。

.Net Coreのバージョンを下げる

以前の記事で.Net Coreのバージョンを2.1.5にあげました。
tekitoumemo.hatenablog.com
公式ではApp Service反映してるよ!って言ってたのですがエラーの内容から怪しいのでバージョン指定なしでプロジェクトファイルの内容を変更します。

<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.5" />
↓
<PackageReference Include="Microsoft.AspNetCore.App" />

何も指定しないと2.1.1になるみたいです。
f:id:tekitoumemo:20181010232833p:plain
はい、確認しましょう。

サイトを確認する(三度目)

f:id:tekitoumemo:20181010233033p:plain
よっしゃー!ざっと見た感じ、Reactも動いてるしいい感じですね!もうちょっと動作確認したり、Coreのバージョンを下げたのでそれに伴ってNugetのバージョンを下げる必要がありそうです。また、移行する時間、告知、メンテナンス中のページとか作らなきゃいけないですので今月いけるかな〜?って感じです。

さいごに

記事では流れで書いているので簡単そうに見えますが、昨日の夜から今日も仕事でしたが適当にタスク2つぐらい終わらせてあとはずっと調べてました(クビ。開発もMacでやってるしWEBサーバーもマルチプラットフォームで実現出来たのでサービス開始から5ヶ月でようやく完全マルチプラットフォーム化実現しそうです。一応、Windowsでも動くような構成にしてるので(Windows機ないからわかりませんが)どの環境からも開発できるようになりました。.Net CoreのリリースノートにApp Serviceも反映したよって書いてあったのですがAzure App Service on Linuxは完全別物なんですね。3000円浮くし、application insightsとかゆくゆくはKubernetesとか試して見ようかなと思います。最後に参考になったサイトのリンクを貼っておきます。

Deploying ASP.NET Core to App Service on Linux – Honza's Blarg
Azure web app on linux deployment failed on deploy.ssh - Stack Overflow
Azure App Service on Linux の FAQ | Microsoft Docs

ASP.NET MVCにおけるモデル検証について

https://4.bp.blogspot.com/-NZWVQX1HeY0/W4tss_UVZmI/AAAAAAABOQ0/xBD5M6o3HAs82NfznQPvkgoxCHtO1RDHQCLcBGAs/s450/fashion_model_woman.png

かなり一般的なネタですが、以外に実装されている現場が少なく、色々処理した後にエラーチェックしてバグる現象が発生していることが多い気がするので備忘録として。以下に書いているコードは.Net Core2.1です。Frameworkでもほぼ一緒なので参考になるかなと思います。

モデル検証って言うとなんか小難しく感じるのですが、要はエラーチェックです。公式はこう言ってます。

アプリでは、データベースにデータを格納する前に、データを検証する必要があります。 データにセキュリティ上の脅威がないかどうかを確認し、種類とサイズが適切に設定されていることを検証しなければなりません。また、ご自身のルールに準拠している必要もあります。

で、ASP.NETだと簡単にできるよって言ってます。

検証を実装するのは冗長で面倒な場合がありますが、必要不可欠です。 MVC では、検証はクライアントとサーバーの両方で発生します。
さいわい、.NET では検証が検証属性に抽象化されています。 これらの属性には検証コードが含まれているため、開発者が記述しなければならないコードの量は少なくて済みます。

まぁ、他のフレームワークでもあるよねって感じですが。

本題に入ります。

モデル

Personというモデルがあり、名前と年齢が定義されています。

public class Person {

    public string Name { get; set; }

    public int Age { get; set; }

}

名前は10文字まで、年齢は99歳までというバリデーションをつける場合はAttributeをつけます。

[Display (Name = "名前")]
[MaxLength (10)]
public string Name { get; set; }

[Display (Name = "年齢")]
[Range (0, 99)]
public int Age { get; set; }

これで条件通りのバリデーションをつけれますが以下のようなエラーが出力されます。

"The field 名前 must be a string or array type with a maximum length of '10'."

これだとアプリ毎に適切なメッセージじゃないのでメッセージをつけます。

[Display (Name = "名前")]
[MaxLength (10, ErrorMessage = "{0}は10文字まで")]
public string Name { get; set; }

[Display (Name = "年齢")]
[Range (0, 99, ErrorMessage = "{0}は99歳まで")]
public int Age { get; set; }

これで以下のようなメッセージが出力されます。

"年齢は99歳まで"
"名前は10文字まで"

バリデーションはいろんな種類があるので以下を参考にしてください。
docs.microsoft.com

次にアプリ独自の検証は必ず必要なので、CustomValidationAttributeで検証します。今回はsaitoって名前で29歳(僕)だったらエラーにします。

public class Person {

    [Display (Name = "名前")]
    [CustomValidation (typeof (Person), "CheckName")]
    public string Name { get; set; }

    [Display (Name = "年齢")]
    public int Age { get; set; }

    public static ValidationResult CheckName (string value, ValidationContext context) {
        var model = (Person) context.ObjectInstance;
        if (model.Name == "saito" && model.Age == 29) {
            return new ValidationResult ("この人はダメです。");
        }
        return ValidationResult.Success;
    }
}

上記のコードでモデルを取得して組み合わせ技で検証出来るのでだいたいは事足りるかなと思います。

コントローラ

次にコントローラー側の検証します。

WEBAPIなどに使われるApiControllerAttributeを指定している場合はコントローラ側に来る前に以下のエラーを吐きました。ちょっと独自のエラーを返したい場合はどうするのかよくわかりません。いつか調べます(絶対調べない)

{
    "Age": [
        "年齢は99歳まで"
    ],
    "Name": [
        "名前は10文字まで"
    ]
}

MVCの場合は以下のように検証します。ModelState.IsValidはモデルにエラーがあるか判定するフラグでfalseだったらエラーがあるってことです。

[HttpPost]
public string Post ([FromBody] Person person) {

    if (!ModelState.IsValid) {
        // ここでエラーチェック
    }
    return "Success";
}

独自のエラーモデルなどを使っている場合はModelStateからエラーメッセージとプロパティを取得できます。

// プロパティ毎のエラーを保持
ModelState.Values
// 一番最初のプロパティのエラーを保持
ModelState.Values.First ().Errors
// 一番最初のプロパティのエラーの最初のメッセージ(エラーが複数ある場合)
ModelState.Values.First ().Errors.First ().ErrorMessage
// エラーがあるプロパティの名前
ModelState.Keys

いろいろ書きましたが、これだけ覚えていればだいたいのエラーチェックがAttributeで済むと思います。エラーチェックは作り込んでから直すと結構大変なんでここら辺は習得しておく必要があるかなと思います。いつものごとく雑ですが、githubにあげましたので参考になればと思います。個人の趣味ブログなのですげーテキトーにコード書いてますのでご注意を。
github.com

.NET Core 2.1.5にアップデートした

2018年10月2日に「.NET Core 2.1.5」がリリースされました。僕の運用してるみんなの洋楽ランキングが2.1.0だったので備忘録として残しておきます。まぁ超簡単。

更新内容をざっくり

2.1.3 バグ修正
2.1.4 脆弱性あったのでその修正←ここ重要
2.1,5 バグ修正

詳しくはgithubに書いてあるので興味ある人は見てください。個人的にはパフォーマンス系の改善が欲しかったな>2.2に期待
github.com

注意事項

.NET Coreのバージョンが公開されたからと言ってAzure AppServicesで最新バージョンが使えるとは限りません。Azure AppServicesを使っている人は必ずリリースノートを確認してください。今回は同日にデプロイされたのですが、2.1.3は6日も誤差がありました。
core/2.1.5.md at master · dotnet/core · GitHub
ちゃんとデプロイした日付も書いてくれてます(やさしい

Deployment of .NET Core 2.1.5 to Azure App Services will begin on today, October 2, 2018. Deployment will proceed to additional regions and is expected to complete by the end of the week.

アップデート

SDKをダウンロード

以下のURLからSDKをダウンロードしてきます。WindowsMacインストーラーで。
www.microsoft.com
Debianは以下を参考に。Ubuntuの「ソフトウェアの更新」はあまり信用出来ないからコマンドからやった方が良い気がする。
.NET Core その32 - .NET Core 2.1.5がリリースされました・.NET Core 2.1.5をインストールするには - kledgeb

Microsoft.AspNetCore.Appを2.1.5に

csprojを書き換えれば良いです。

<PackageReference Include="Microsoft.AspNetCore.App" Version="***" />
↓
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.5" />

2.14以上には最低でもあげたいですね。下の画像にも書いてあるし。
f:id:tekitoumemo:20181006002102p:plain

おわり

.Net系のフレームワークのバージョンアップはまじで優秀な印象。

ついでに

nuget周りもとりあえずあげときました。
僕は以下2つが対象でした。

dotnet add package MailKit --version 2.0.6
dotnet add package AutoMapper.Extensions.Microsoft.DependencyInjection --version 5.0.1
雑談

モバイルアプリを作ろうと思っててxamarinをやってます。WEBは.Net CoreとReact勉強になったし(我ながらどちらも素晴らしい選定だった)、SEOに怯えてちまちまくだらない改善してもしょうがない感じがするんで心機一転によいかなと。あとreact naitiveと迷ったんですが、IDEが整っていること、手抜き(コードが共通して使える)が出来るのが最強かなと。コードは書けば書くほど負債になるので、出来るだけプログラミングやらない方向で進めたいのです>エンジニア失格

スクレイピングにはAngleSharpが良いらしい

https://raw.githubusercontent.com/AngleSharp/AngleSharp/master/header.png

github.com

C#スクレイピングライブラリはHtml Agility Packがメジャーですが、昔使った感じだとなんか微妙なので(XPathとかだるい)他のライブラリを探してみたらAngleSharpってのが良さそうなのでこちらを使ってみました。ちなみに僕が運用しているみんなの洋楽ランキングでは、情報の収集と自動化にAngleSharpを使っています。
mygkrnk.com

AngleSharpをダウンロードします。

dotnet add package AngleSharp --version 0.9.10

余談ですが、メジャーバージョンが出ていない理由は.net coreの進みが早くてライブラリが追っついていないようです。作者はこう嘆いています。

One of the greatest killers was Microsoft's ever growing change
最大の殺人者の1人は、マイクロソフトの絶え間ない変化(翻訳ママ)

killersってすげー表現だな、どういうニュアンスで言ってんだろ?
Request for stable release (=version 1.0) · Issue #709 · AngleSharp/AngleSharp · GitHub

using

using AngleSharp.Parser.Html;

stackoverflowとか見てて名前空間がわからない調べることが多いんだけど、みんなどうしてんのかな?

htmlをパースする

htmlは適当に取ってきてください。

var parser = new HtmlParser ();
var doc = parser.Parse (html);

属性を取得

今回はみんなの洋楽ランキングのいいね数を取得します。一番最初に取得するいいね数なので10位のいいね数が取得されます。
これ
f:id:tekitoumemo:20180921003302p:plain
f:id:tekitoumemo:20180921003423p:plain

var likeApp = doc.GetElementsByClassName ("like-app");
var count = likeApp.First().Attributes["react-prop-counts"].Value;
// count : "5"

InnerHtmlを取得

せっかくなんで曲名で検索します。
f:id:tekitoumemo:20180921003631p:plain
f:id:tekitoumemo:20180921003646p:plain

var enrryTitles = doc.GetElementsByClassName ("entry-title");
var title = enrryTitles.Where(x => x.InnerHtml.Contains("In My Feelings")).First().InnerHtml;
// title : <a href=\"/music/784\">In My Feelings</a>

HtmlAgilityPackに比べてめちゃめちゃ使いやすくなってるので、スクレイピングを検討している人は試してみてはどうでしょうか。まだまだいろんなやり方はあるので、ドキュメントを見てください。一応、調べてる最中にタラタラ書いたコードをGithubに上げたので参考になれば。個人の趣味ブログなのですげーテキトーにコード書いてますのでご注意を。
github.com