WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

ReportViewer にハイパーリンク設定

by WebSurfer 23. November 2020 18:23

ASP.NET Web Forms アプリ用の ReportViewer のテキストにハイパーリンクを設定する方法を備忘録として書いておきます。LocalReport の場合ですので注意してください。ServerReport で同じことができるかは不明です。

ReportViwer にハイパーリンク設定

上の画像は Product Name 列のテキストがハイパーリンクとなるように設定したものです。上から 3 番目の Aniseed Syrup をマウスでポイントして、それに設定したリンク先が画面の左下に表示されています。

ReportViewer のハイパーリンクの設定方法は以下の Microsoft のドキュメントに説明があります。

ドキュメントにある「プロパティ」とか「アクション」は何かと言うと、Visual Studio で .rdlc ファイルを開いてテキストボックスを右クリックすると出てくるメニューの[テキストボックスのプロパティ...]で表示される「テキストボックスのプロパティ」ダイアログと[アクション]タブのことです。

テキストボックスのプロパティ

そのダイアログで[URL に移動する(U)]を選択すると、テキストをクリックしたときの遷移先の URL を入力する[URL の選択(S)]テキストボックスが現れます。

テキストボックスに http または https から始まる絶対 URL を入力すると、ブラウザに表示されたとき、テキストがその URL へのハイパーリンクとして設定されます。相対 URL では無視されますので注意してください

.aspx ファイルの ReportViewer のコードの LocalReport 要素に EnableHyperlinks="True" を設定するのを忘れないようにしてください。忘れると "レポート 'Report1' にハイパーリンクが含まれます。このレポートの EnableHyperlinks プロパティが設定されていません" というエラーになります。

フィールドのデータに URL を含めてそれをリンク先として設定することもできます。また、上の画像のダイアログの[fx」をクリックすると表示されるダイアログで以下のように式を入力することもできます。

式の設定

上の画像で、式は C# の文字列の結合の場合と似ていますが、C# と違って ToString() を付けないと URL が設定されないので注意してください。エラーも出ず設定が無視されます。

最後に、ハイパーリンクのスタイルですが、下の画像のように、color: Black; text-decolation: none; が設定されています。

ハイパーリンクの CSS

なので、何もしなければ文字の色は他のテキストと同じ黒で、マウスをポイントしても何も変わりません。変えたい場合は以下のような CSS を追加すれば可能です。

<style type="text/css">
    a {
        text-decoration: none !important;
        color: #5C80B1 !important;
    }

    a:hover {
        text-decoration:underline !important;
    }
</style>

この記事の一番上の画像は上の CSS を適用したものです。色が他のテキストと違っていますし、マウスをポイントするとアンダーラインが表示されるのが分かりますでしょうか。

Tags: ,

ASP.NET

ReportViewer v15 のツールバー

by WebSurfer 22. November 2020 14:04

ASP.NET Web Forms アプリ用の ReportViewer v15 のツールバーの話です。Width プロパティで指定する幅がツールバーのアイコンを一行で表示するのに十分でない場合、その幅に入りきらないアイコンはツールバーに表示されません。

ReportViewer v15

上の画像は Width がデフォルトの 400px の場合ですが、ズーム、エクスポート、印刷、検索のアイコンが 400px の幅に入りきらず、表示されていません。(アプリは「チュートリアル : ローカル処理モードでの ReportViewer Web サーバー コントロールとデータベースのデータ ソースの使用法」のものです。本題とは関係ないことですがご参考まで)

それを以下の画像のように表示する方法を書きます。

ツールバーに全アイコンを表示

ちなみに、v12 では以下の画像のように、何もしなくても全部のアイコンが表示されます。(なぜ、v15 でも同じにしなかったのかの理由は不明です。わざわざ手間をかけて非表示しているということは何かそうせざるを得ない事情があるのかもしれません・・・)

v12 のツールバー

ならば、わざわざ v15 にアップグレードしなくても v12 を使えば良いと思うかもしれませんが、v12 は印刷に ActiveX を使っているので IE でしか印刷ができないという問題があります。ズームと印刷のアイコンは Chrome, Edge, Firefox などでは表示さえされません。また、IE11 でも問題があって、ドキュメントモードを 10 以下にしないと Height プロパティの設定が無視されます。

v15 ではそのあたりの問題が解消されており、ズームと印刷は Chrome, Edge, Firefox でも使用可能となっています。

なので、新規開発で ReportViewer を使うなら v15 の一択になると思いますが、上に述べたツールバーの問題を解決しないと、エクスポートや印刷のアイコンが現れず Excel にエクスポートできないとか印刷できないとかで使い難いと思います。

解決方法としては:

  1. ReportViewer の Width プロパティの値を固定する場合、ツールバーに不要な項目は非表示にして、固定した幅に必要なアイコンが収まるようにする。
  2. ReportViewer 幅がブラウザの表示幅一杯になるようにする。即ち、Width プロパティを 100% に設定し親要素の幅は設定しない。ブラウザの表示幅に応じてアイコンは表示されるので、この解決方法が一番よさそうです。
  3. JavaScript を使って表示する。

・・・ということが考えられます。上の 1, 2 のやり方は説明するまでもないことですので、以下に 3 番目の方法だけを書きます。その結果がこの記事の上から 2 番目の画像です。

まず、なぜ表示されないかですが、Width で設定した幅からはみ出るアイコンが含まれる div 要素に ReportViewer が自動的に display: none を設定するからです。下の画像を見てください。

html ソース

これを何とかする方法はないかと、以下の記事などを読んでみましたが、プロパティの設定なとで簡単に解決する方法はなさそうでした。

上の 3 番目の記事の JavaScript API を利用して操作することも考えましたが、display: none を display: inline-block に書き換えることはできるものの、スクロールバーを操作したりすると元の display: none に戻ってしまいます。

元の display: none に戻ってしまうというところは何ともできないので、ツールバーをクリックすると display: none を display: inline-block に書き換えられる手段を提供するのがよさそうです。

JavaScript で書き換えても、スクロールバーを操作すると ReportViewer が自動的に display: none に戻してしまいますが、その場合は再度ツールバーをクリックして再表示するということで対応してもらう他なさそうです。

そのサンプルコードは以下の通りです。コードの中の ToolBarButtonsCell というのはツールバーの div 要素に付与されているクラス名です。上の html ソースの画像を見てください。それをハードコーディングするのはちょっと抵抗がありますが、他に適当な手段が見つかりません。

<script src="Scripts/jquery-3.4.1.js"></script>
<script type="text/javascript">
    //<![CDATA[

    // ツールバーに全項目を表示するための対応を考えたのが下記

    window.onload = function () {
        $("div.ToolBarButtonsCell").on('click', changecss);
    };

    function changecss() {
        $("div.ToolBarButtonsCell > div").each(function () {
            var display = $(this).css("display");
            if (display == "none") {
                $(this).css("display", "inline-block");
            }
        });
    };
    //]]>
</script>

上にも書きましたが、v12 では全部のアイコンが表示されていたのに、v15 でわざわざ手間をかけて非表示しているということは何かそうせざるを得ない事情があって、それを上のような方法で無理やり表示すると、予期せぬ好ましからざる副作用が出るかもしれません。今のところ問題には遭遇してませんが、それが気がかりです。

最後になりますが、ReportViewer v15 は Visual Studio には含まれておらず、ツールバーにも表れてきません。自力で NuGet インストールして設定する必要がありますので注意してください。

インストールの方法などは Microsoft のドキュメント「レポート ビューアー コントロールを使用した Reporting Services の統合 - 概要」を見てください。

Tags: , ,

ASP.NET

Web Forms アプリの Email Confirmation

by WebSurfer 10. August 2020 14:05

ASP.NET Web Forms アプリで登録・パスワード再取得のためのメール送信機能を利用する場合、テンプレートで実装されたコードを使うとメール本文に含まれる確認先の URL にアプリケーション名が含まれないという注意事項を書きます。(結果、メール本文に張られたリンクの URL が正しくないのでクリックしても確認できません)

アプリケーション名が含まれない

.NET Framework 版の ASP.NET Web Forms の Web アプリケーションプロジェクトを Visual Studio 2019 のテンプレートを使って、ユーザー認証に「個別のユーザーアカウント」(ASP.NET Identity) を選んで作った場合の話です。ASP.NET MVC5 ではこの問題はありません。

元の話は Teratail のスレッド「リセット画面のURLをアプリケーションルートにしたい」のものです。そのスレッドを見て初めてそういう問題があることを知りました。

メール本文に含めて送信する確認先の URL は、Models/IdentityModels.cs に含まれるヘルパーメソッド GetUserConfirmationRedirectUrl と GetResetPasswordRedirectUrl で Uri(Uri, String) コンストラクタを使って取得しています。

Uri(Uri, String) コンストラクタの第 1 引数に HttpRequest.Url プロパティで取得する Uri を、第 2 引数に "/Account/..." から始まる相対 URL の文字列を設定して Uri オブジェクトを作り、それから AbsoluteUri プロパティを使って絶対 URL を取得して確認メールの本文に張り付けています。

この記事の一番上のデバッグ画像を見てください。問題のヘルパーメソッド GetUserConfirmationRedirectUrl, GetResetPasswordRedirectUrl ではないですが、簡単に問題を再現するために Page_Load メソッドに同等のコードを書いて検証してみました。

なお、Visual Studio (IIS Express) では以下のように Request.Uri にアプリケーション名 myapp が含まれるよう[プロジェクトの URL (J)]を設定しています。

アプリケーション名 myapp を設定

上のデバッグ画像のとおり、ローカル変数の rquestUri にはアプリケーション名 myapp を含めた Uri オブジェクトを取得できています。ローカル変数 callbackUrl が確認先の URL になりますが、アプリケーション名 myapp は含まれません。これが問題です。

ちなみに、ASP.NET MVC アプリでは Url.Action を使ってアプリケーション名を含めた絶対 URL を取得していますのでこういう問題はないです。

対処方法として、ヘルパーメソッド GetUserConfirmationRedirectUrl と GetResetPasswordRedirectUrl 内にアプリケーション名をハードコーディングするのは好ましくはなさそうです。アプリケーション名の変更、アプリの移植で問題となりますので。

ルート演算子 (~) と VirtualPathUtility.ToAbsolute メソッドを利用して "~" に相当するパスを取得するのがよさそうです。具体例は以下の画像を見てください。

VirtualPathUtility.ToAbsolute メソッド利用

この記事の例のように、アプリケーション名が myapp の場合、VirtualPathUtility.ToAbsolute メソッドの引数に "~" を設定すると戻り値は "/myapp" になります。引数に "~/Account/ResetPassword" を設定すると(文字列先頭に "~" を付与している点に注意)戻り値は "/myapp/Account/ResetPassword" となります。以下の画像を見てください。

このようにすればアプリケーション名をハードコーディングしなくて済みます。


その他のパス設定の問題

テンプレートで生成されたコードのパス設定の問題は他にもあって、例えば Account/Manage.aspx ページでも以下のようにリンク先の URL にルート演算子 (~) が設定されてないです。

URL にルート演算子 (~) が設定されてない

リンクをクリックしても、普通はパスが通らないので、404 Not Found エラーとなってすぐ気が付くと思うかもしれませんが、開発環境ですと訳が分からないサーバーエラーになることがあるかもしれません。

実は、上の画像にあるように Visual Studio で[プロジェクトの URL (J)]を設定したのですが、その際 IIS Express 用の applicationHost.config 設定で application path="/" と application path="/myapp" が両方有効になって、/Account/ManagePassword.aspx に遷移できてしまったのです。

認証チケットは /mayapp/Acount/Login.aspx で取得しているのですが、/Account/ManagePassword.aspx では認証されないので User.Identity.GetUserId() でユーザー ID を取得できず訳が分からないサーバーエラーになりました。

これには半日ぐらい悩まされました。どうも Microsoft としては Web Forms アプリには力が入ってなくて、テンプレートで生成されるコードでも 100% 信頼できないような感じがします。

Tags: , ,

ASP.NET

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  November 2020  >>
MoTuWeThFrSaSu
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

View posts in large calendar