テナントごとの Favicon
ブラウザのタブに出る Favicon を、テナントの管理画面からアップロードして切り替えられるようにする設計メモです。本体の標準機能ではありません。 テナントのロゴ画像(CorpLogo)と同じ作りにすると、DB のスキーマを変えずに実装できます。調査は 1.5.1.0 で行い、前提にした部分を 1.5.8.1 のソースで確かめています。
前提にした現行実装
Favicon
<head> の Favicon は HtmlHeadLinks.LinkedHeadLink が出力します。パスは favicon.ico で固定です(HtmlHeadLinks.cs#L105-L119)。
html
<link href="/favicon.ico" rel="shortcut icon">| 項目 | 現行 |
|---|---|
| ファイル | wwwroot/favicon.ico の 1 つだけ |
| テナント・ユーザーごとの切り替え | なし |
| パラメータでの差し替え | なし |
apple-touch-icon・Web App Manifest | 出力しない |
いまできるのは wwwroot/favicon.ico を差し替えることだけで、全テナント共通になり、本体の更新で元に戻ります。<head> に <link> を足す拡張機能(ExtendedHeadLinks)はソースにあるものの動きません(拡張ヘッドリンク(ExtendedHeadLinks)は動かない)。
テナントのロゴ画像(CorpLogo)
| 部品 | 1.5.8.1 のソース | 内容 |
|---|---|---|
| 表示の種類 | TenantModel.cs#L1774-L1778 | LogoTypes(ImageOnly / ImageAndTitle) |
| 有無の確認 | BinaryUtilities.cs#L81 | ExistsTenantImage(BinaryType が TenantImage の行) |
| 保存 | BinaryModel.cs#L1047-L1078 | UpdateTenantImage。ロゴのサイズにリサイズした PNG を、ReferenceId(テナント ID)と BinaryType で UpdateOrInsert。ローカル保存のプロバイダーならファイルに書く |
| 削除 | BinaryModel.cs#L1112 | DeleteTenantImage |
| 出力 | HtmlHeaders.cs#L176-L200 | 画像があれば Binaries/TenantImageLogo/?yyyyMMddHHmmss(更新日時でキャッシュを破る)、なければ logo-corp.png などの既定画像 |
| 配信 | BinariesController.cs#L56-L71 | [ResponseCache(Duration = int.MaxValue)] を付けた GET |
| アップロード・削除の口 | BinariesController.cs#L88、#L116 | UpdateTenantImage(POST)・DeleteTenantImage |
| 画像の種類 | ImageData.cs#L36-L48 | Types(SiteImage / TenantImage)、SizeTypes(Regular / Thumbnail / Icon / Logo) |
図を読み込み中…
改修の方針
ロゴと同じ流れを、BinaryType を TenantFavicon にして足します。Binaries テーブルの BinaryType で区別するので、スキーマの変更は要りません。
| ファイル | 改修 | 種別 |
|---|---|---|
Libraries/HtmlParts/HtmlHeadLinks.cs | LinkedHeadLink で、テナントの Favicon があればその URL を出す | 既存の改修 |
Models/Binaries/BinaryModel.cs | UpdateTenantFavicon / DeleteTenantFavicon | 追加 |
Models/Binaries/BinaryUtilities.cs | 有無の確認・取得・更新日時・アップロード・削除 | 追加 |
Models/Binaries/BinaryValidators.cs | 形式・サイズのチェック | 追加 |
Controllers/BinariesController.cs | 取得(GET、長期キャッシュ)・アップロード(POST)・削除の 3 つ | 追加 |
Models/Tenants/TenantUtilities.cs | テナントの管理画面にアップロード欄を足す(ロゴの設定欄と同じ作り) | 追加 |
Libraries/Images/ImageData.cs | 必要なら Types に値を足す | 既存の改修 |
LinkedHeadLink の改修イメージです。
csharp
public static HtmlBuilder LinkedHeadLink(
this HtmlBuilder hb, Context context, SiteSettings ss)
{
var faviconHref = BinaryUtilities.ExistsTenantFavicon(
context: context,
referenceId: context.TenantId)
? Responses.Locations.Get(
context: context,
parts: new string[]
{
"Binaries",
"TenantFavicon",
BinaryUtilities.TenantFaviconUpdatedTime(context: context)
.ToString("?yyyyMMddHHmmss")
})
: Responses.Locations.Get(
context: context,
parts: "favicon.ico");
return hb
.Link(href: faviconHref, rel: "shortcut icon")
.EsModuleLinks(/* 既存のまま */);
}決めておくこと
| 項目 | 内容 |
|---|---|
| 形式 | ICO(1 つのファイルに複数の解像度を持てる)と PNG を受け付けたい。ロゴは ImageSharp でリサイズして PNG で保存するが、Favicon はアップロードされたものをそのまま保存し、Content-Type も保存時のもの(image/x-icon / image/png)で返す |
| キャッシュ | ロゴと同じく長期キャッシュ+更新日時のクエリ文字列で破る。ただしブラウザは Favicon を強くキャッシュするので、変更後にすぐ変わらないことがある |
apple-touch-icon | iOS のホーム画面用に <link rel="apple-touch-icon"> も出すかどうか。出すなら同じ仕組みで別のサイズの画像を返す |
テナントごとに Favicon が変わると、マルチテナントの環境でどのテナントのタブかを見分けやすくなります。