Windows 認証、または SQL Server 認証 sa ユーザー以外のユーザーに SQL Server エージェントのジョブ実行権限を付与する方法

メモ書きです。

  1. SQL Server Management Studio から「セキュリティ」-「ログイン」を開き、対象ユーザーのプロパティを開く
  2. 「ユーザーマッピング」を選択し、「msdb」にチェックを入れる。
  3. さらに msdb を選択した状態でメンバーシップから以下のメンバーシップにチェックを入れる
    • SQLAgentUserRole
    • SQLAgentReaderRole
    • SQLAgentOperatorRole
  4. 後はプログラムなどから対象ユーザーの接続文字列を使用してジョブが実行されるかチェックする

[ASP.NET] IE の互換表示で ReportViewer コントロールのサイズを小さくすると IE がフリーズする現象を回避する方法

ReportViewer+SSRS のレポートを IE で互換表示すると高確率でフリーズする」で質問させていただいたのですが、回避方法が見つかったのでこちらにも書いておきます。

【環境】(現象確認環境であるため、似たような環境でも発生すると思います)

❏サーバー

  • Windows Server 2008 R2 Standard (SPなし)
  • IIS 7.5
  • ASP.NET MVC 3
  • ReportViewer コントロール バージョン 10.0.0.0 (.NET Runtime 2.0.50727)
  • SQL Server 2008 R2 (SPなし)
  • 見出しマップを表示されたレポート (.rdl)

 

❏クライアント

  • OS : Windows XP, Vista, Windows Server 2008 R2
  • ブラウザ:IE8, 9

 

【現象】

ReportViewer コントロールに見出しマップがあるレポートをバインドさせ、その Web ページを IE 8, または 9 の「互換表示」で開き、ReportViewer コントロールのサイズを小さく表示させると IE がフリーズする。(ReportViewer コントロールのサイズがウインドウサイズに追従する場合は、IE のウインドウサイズを小さくしていけば現象は確認できる)

おそらくではあるが、IE の内部処理でレイアウトを計算する際に無限ループ、またはそれに近い再起処理が行われているためだと思われる。

 

【対処法】

IE のレイアウトの解析処理を変更させることでフリーズを回避させることができる。具体的には HTML の解析は DOCTYPE で変えられるため、この宣言の内容を変更することによって可能。

・修正前

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

↓↓↓↓

・修正後

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

 

しかし、HTML 4.01 Transitional を指定すると今度は逆に互換表示していない IE での表示が崩れてしまうという現象に見舞われる。そのため、HTML で互換表示かそうでないか (正確には IE のレンダリングバージョン)で条件分けをして現象を回避します。

下記では「IE 8 以降であるか」「IE 8 未満であるか」「それ以外のブラウザであるか」で分岐しています。

<!--[if gte IE 8]>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<![endif]-->
<!--[if lt IE 8]>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<![endif]-->
<![if !IE]>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<![endif]>

 

別案としてサーバーから「<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />」のようなメタ情報を返してクライアントで互換モードを指定するという方法もあるが、最終的な互換モードの決定権はクライアントにあるため、必ずしも有効であるとは限らない。(でも何もしないよりはいいと思います。)


Web サイト PDF 変換サービスの修正

URL に「&(アンパサンド)」が含まれている場合に PDF ファイルがダウンロードできない不具合がありましたので修正しました。今まで変換する URL がひとつの場合には PDF ファイルをそのままダウンロードする形になっていましたが、1つでも複数の場合でも ZIP ファイルにまとめてダウンロードできるようにしました。


[ASP.NET MVC] FilePathResult でファイルを返すと IE8 以前のブラウザで意図しないファイル名でダウンロードされる

アクションメソッド内で File メソッド (FilePathResult) を使用してファイルを返している処理があったのですが、IE でファイルをダウンロードした際にすべて同じファイル名でダウンロードされてしまうという報告を受けたので調べてみました。

理由については「ASP.NET MVC2 の FileContentResult で日本語ファイル名で返すと IE で日本語ファイル名にならない」のリンク先を見てもらえればそのままなのですが、IE8 以前だと、File メソッドの fileDownloadName 引数にファイル名を指定してもアクション名でファイル名が返ってしまうみたいです。

対応策はやはりリンク先のようにクラスを派生させて対応できました。私の場合はローカルにあるファイルからダウンロードさせるようにしていたので「FilePathResult」クラスから派生させています。コードは下のような感じです。(クラス名は適当なので気にしないでください)

/// <summary>
/// IE 8 以前でファイル名を正常に返せない不具合に対応した FilePathResult。
/// </summary>
public class FilePathResultEx : FilePathResult
{
    public FilePathResultEx(string fileName,
                            string contentType,
                            string fileDownloadName)
        : base(fileName, contentType)
    {
        base.FileDownloadName = fileDownloadName;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        // IE 以外では基底の処理に任せる(RFC2231)
        if (context.HttpContext.Request.Browser.Browser != "IE")
            base.ExecuteResult(context);
        else
        {
            var fileName = this.FileDownloadName;
            fileName = HttpUtility.UrlEncode(fileName).Replace("+", "%20");
            var response = context.HttpContext.Response;
            response.ContentType = this.ContentType;
            response.AddHeader("content-disposition", "attachment; filename=" + fileName);
            this.WriteFile(response);
        }
    }
}

 

アクションメソッドでは下のように変更して返します。

string localFilePath = @"<ローカルのファイルパス>";
string contentType = "<ファイルのコンテンツタイプ>";
string downloadFileName = "<ダウンロードさせるファイル名>";

// 下のメソッドはやめる
//return File(localFilePath, contentType, downloadFileName);

// ヘッダーを変更したレスポンスを返す FilePathResul 拡張クラスで対応
return new FilePathResultEx(localFilePath, contentType, FileName);

[ASP.NET MVC] Release ビルドでコントローラークラスが消える…?

実はさっきまで sorceryforce.net のルートページを開こうとしてもエラーになっていました。原因ははっきりとはしていないのですが、HomeController クラスで何らかの処理をさせようとすると NullRefenenceException で落ちるというエラーが発生していました。単純に Index メソッド内で「int a = 0;」とさせるだけでも Null 参照で落ちます。おそらく HomeController のインスタンス自体が null になっているような感じでした。(C++言語なんかだと自分自身のインスタンスを delete するなんて裏ワザもあったりするんですけどね。インスタンス要素にアクセスしなければ処理は継続できるという)

私が想定する原因としては Release ビルドを行う際にコードの最適化が実行されるのですが、HomeController クラスに処理を入れた場合でも、HomeController クラスは実際にはどこからも参照されていないクラスなので最適化した際にごっそり削られたのではないかと思っています。ためしに「コードの最適化」のチェックを外して Web サイトにアップロードすると問題なく動作します。なので今は適当なクラスで HomeController クラスのインスタンスを生成するコードを入れておいてビルドするようにしています。こうするとコードの最適化が実行されても HomeController クラスは正常に動作します。でも他のコントローラークラスは正常に動作するんですよね…。


Web ページ PDF 化サービス

最近 Web サービスの構築に力を入れようかなーと思っていろいろ手を入れこんでいました。その分他のところに手が回らなくて申し訳ありませんでした。

そのサービスのひとつとして Web ページを PDF 化してダウンロードできるサービスを作ってみました。とはいっても変換のしくみは外部サービス依存なんですけどね^^;。

ちなみにこのサービス作った理由は私が欲しかったからですw。本家サイトを使った場合、PDF は一般的な余白あり縦向きレイアウトで出力されるのですが、私は印刷とかせずに単純に PDF という形で残したかったので余分な余白を削り、横向きでできる限り実際の Web ページのレイアウトで出力できるように設定しました。本当は細かいところも設定できるのですが、とりあえず私自身が欲しいレイアウトができればよかったので特に設定項目はありません。URLを入れるだけです。

一応外部サービス依存型なので外部サービスが変更、または停止する可能性を考慮して常にβ版として提供しています。他にもテスト目的や外部サービスに関係するサービスを作成した場合はβ版としてリリースしていくかもしれません。


[ASP.NET MVC] Redirect メソッドと RedirectPermanent メソッドの違い

Redirect メソッドと RedirectPermanent メソッドはどちらも同じ別ページに遷移するためのメソッドですが、クライアントに返すステータスが異なります。Redirect メソッドが「302 (Moved Temporarily)」を返し、RedirectPermanent メソッドが「301 (Moved Permanently)」を返します。

これはサイトを閲覧しているユーザーのためというよりは検索エンジンのクローラーに対してのメッセージとして使われます。302 は一時的に生成したページに遷移するという意味を持ち、クローラーはそのリダイレクト先の情報を収集しようとはしません。301 は古いページから新しいページに移動させるためのリダイレクトとして解釈され、クローラーは新しいリダイレクト先の情報を収集します。(収集しない、すると明言して書いていますが、実際の挙動はクローラーに依存します)

ですので、ユーザー登録のための画面や一時的なダウンロードページなど、クローラーに収集されたくないページへリダイレクトする場合は「Redirect メソッド」、遷移先のページをクロールされてもいい場合は「RedirectPermanent メソッド」のように使い分けをします。


ドメイン間ポリシーファイルの配置場所

Silverlight や Flash などのアプリケーションが提供されたドメインと異なる URL の Web サービスを使用するには「ドメイン間ポリシーファイル」が「Web サービス側」に配置されている必要があります。(Silverlightドメイン間ポリシー(clientaccesspolicy.xml)や Flashドメイン間ポリシー(crossdomain.xml))

イントラネットワーク内のサイトで提供している Web サービスでも同様でドメイン間ポリシーファイルを配置する必要がありますが、配置する場所は必ずホスト名直下の URL で取得できる位置に配置する必要があります。(例:http://<サーバー名>/clientaccesspolicy.xml など)

IIS などで同じポートで複数のアプリケーションを配置するために Default Web Site の下にアプリケーションを作成する場合があると思いますが、その場合も個々のアプリケーションごとにドメイン間ポリシーファイルを配置するのではなく、Default Web Site が使用している物理フォルダ (デフォルト「C:inetpubwwwroot」)に配置する必要があります。