WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

VS2010 で ASP.NET MVC 4

by WebSurfer 2014年7月14日 14:30

何を今さらと言われるるかもしれませんが、VS2010 でも ASP.NET MVC 4 を使用しての開発ができるということを知って、自分の開発マシンにもインストールしてみました。

VS2010 で ASP.NET MVC 4

実は、MVC4 は VS2012 以上でなければサポートされてないと誤解しており、VS2012 はシステム要件が Windows 7 以上ということで(自分の開発マシンの OS は Vista)諦めてました。(汗)

Visual Studio 2012 / ASP.NET MVC 4 正式リリース というブログに書いてあった Microsoft のダウンロードサイト Visual Studio 2010 SP1 および Visual Web Developer 2010 SP1 用 ASP.NET MVC 4 から AspNetMVC4Setup.exe と AspNetMVC4Setup_JPN.exe を入手してインストールしました。

インストールした結果、上の画像のように VS2010 でも MVC4 のテンプレートが利用できるようになりました。

この画面で[OK]ボタンをクリックすると下の画像のダイアログが現れ、MVC4 用に用意された (1) 空、(2) 基本、(3) インターネットアプリケーション、(4) イントラネットアプリケーション、(5) モバイルアプリケーション、(6) Web API という 6 種類のテンプレートから選べるようになっています。

MVC4 用テンプレート

VS2012 に実装されているテンプレートとは少し違いがあって、VS2010 には MVC4 の新機能の一つである Single Page Application 用のテンプレートがありません。ベータ版には実装されていたが、開発が間に合わず RC 版で削除されたそうです。

全ての機能はとてもまだ使いこなせてません。なので、Web や本の記事の受け売りですが、以下に主な新機能の概要を書いておきます。

  1. モバイルアプリケーション・テンプレート
    基本的な構造は、「インターネットアプリケーション」テンプレートで提供されるフォーム認証を使用するアカウントコントローラーを含むアプリケーションと同じだそうです。ただし、View のデザインに jQuery Mobile を使用することで、モバイル端末でのタッチ操作を行いやすい Web アプリケーションを開発できるようになっているそうです。
  2. Display Modes によるビューの切り替え
    デスクトップ PC ブラウザ向けの View と、モバイル端末ブラウザ向けの View をそれぞれ用意しておくことにより、ASP.NET MVC4 フレームワークが自動的にブラウザ種類を判断して View の切り替えを行う機能です。モバイル端末の種類ごとに View を用意し(例えば、iPhone 用とAndroid 用)切り替えることも可能とのことです。
  3. jQuery Mobile, View Switcher と Browser Overriding
    モバイル向け Web アプリケーション作成には、上に述べた「モバイルアプリケーション」テンプレートを利用するアプローチの他に、「インターネットアプリケーション」テンプレートをベースとした Web アプリケーションにモバイル端末向け View を追加するアプローチがあります。
    それには NuGet パッケージとして提供されている jQuery.Mobile.MVC を VS2010 の[ツール(T)]メニューからプロジェクトに追加します。それにより jQuery Mobile と Display Modes をベースとした View Switcher 機能が利用できるようになります。
    Browser Overriding は、ブラウザ上に表示されるリンクの操作で、デスクトップ用の表示とモバイル端末用の表示を切り替えるのに用いる MVC4 の新しい機能だそうです。
  4. ASP.NET Web API
    ブラウザやモバイルデバイスを含むさまざまなクライアントに対して RESTful なサービスを提供するのに適した HTTP サービス構築用のフレームワークです。
    このテンプレートを利用して、RESTful な CRUD (Create, Read, Update, Delete)処理に必要な HTTP サービスのため、POST, GET, PUT, DELETE それぞれの HTTP メソッドに対応したアクションメソッドの雛形を作成できます。 概要は MSDN Blog の記事 ASP.NET Web API を使ってみよう: MVC 4 新機能シリーズ が参考になると思います。
  5. ASP.NET Single Page Application
    JavaScript と Web API をベースとし、AJAX と HTML 5 を使用して、定期的にページを再読み込みしないで、ユーザーのアプリケーション操作に合わせてページを動的に更新し、滑らかで応答性の高い Web アプリケーションを作成するためのテンプレートだそうです。
    概要は MSDN マガジンの記事 単一ページ アプリケーション: ASP.NET を使用して最新の応答性の高い Web アプリケーションを構築する が参考になると思います。
    ベータ版の時点からサポートが外された JavaScript ライブラリもあるそうなので、VS2010 にこの機能を追加する場合はその点に注意する必要がありそうです。(VS2012 を使用したほうがよさそうです)

上記以外の MVC4 の新機能としては、Razor 構文(ASP.NET Web Pages 2)の新機能、JavaScript/CSS ファイルの縮小化と結合処置の自動化機能、Visual Studio コード生成のためのレシピ機能、非同期コントローラーの Task サポート、NuGet パッケージングマネージャーによるコンポーネント管理があります。

・・・が、とてもついていけないので説明は割愛します。もっと勉強しないと世の中の技術の進歩に付いていけないようです。(汗)

Tags:

MVC

loginUrl に絶対 URL を指定した際の問題

by WebSurfer 2014年6月18日 17:56

Fiddler2 で見たログインプロセス

web.config 内の forms 要素の loginUrl 属性に絶対 URL を指定した場合、ログイン後のリダイレクトがうまく行かないという問題と、その対応方法の紹介です。

左の画像はログインに成功して HTTP 302 応答が返ってきたところを Fiddler2 でキャプチャして見たものです。

クリックすると拡大画像が表示されますので、応答ヘッダ(右下のウィンドウ内)の Location に注目してください。本来 /Default.aspx であるべきところが /Account/Login.aspx になっています。

具体的にどういう問題かを以下に説明します。

ASP.NET Web Forms アプリケーションのフォーム認証で、Login コントロール を使った Login.aspx ページでログイン操作を行っているとします。

ログインに成功すると、Login.aspx の ReturnUrl クエリ文字列に指定されたページ(上の画像では /Default.aspx)か、クエリ文字列がない場合は forms 要素の defaultUrl 属性に指定されたページにリダイレクトされるのが普通の動作です。

ところが、以下のように loginUrl 属性に絶対 URL を指定すると、ログイン後に loginUrl 属性に指定した URL(即ち、/Account/Login.aspx ページ)にリダイレクトされてしまいます。← これが今回紹介する問題です。

<authentication mode="Forms">
  <forms loginUrl="http://<hostname>/Account/Login.aspx" />
</authentication>

何故そうなるかと言うと、Login.aspx でログイン成功後、認証クッキーを設定する HTTP 302 応答が帰ってきますが、応答ヘッダの Location が何故か ReturnUrl クエリ文字列(それがない場合は defaultUrl 属性の指定)を無視して /Account/Login.aspx となるからです。

上の画像で、左側のウィンドウ内で上から 4 番目の行がそのときの応答です。右下のウィンドウ内が応答ヘッダの内容で、その一番下の行 Location が /Account/Login.aspx となっています。ブラウザはこれを見て /Account/Login.aspx を GET 要求するという訳です。

なお、loginUrl 属性に相対 URL やルート演算子 (~) を使用した場合(例: loginUrl="~/Account/Login.aspx")は問題なく、期待通り ReturnUrl クエリ文字列に指定されたページにリダイレクトされます。

何故、絶対 URL を指定したいかと言えば forms 要素の requireSSL 属性 を True に設定して、認証 Cookie を送信するために SSL 接続を必須としたいからです。

その場合、loginUrl="https://<hostname>/Account/Login.aspx のように https で始まる絶対 URL を指定しないとサーバーエラーとなってログインできません。

ちなみに、loginUrl="~/Account/Login.aspx" requireSSL="true" とすると、Login.aspx ページは SSL 経由せずに表示されますが、ID とパスワードを入力して[ログイン]ボタンをクリックするとサーバーエラーとなり、以下のエラーメッセージが返ってきます。

"System.Web.HttpException: アプリケーションは、セキュリティで保護されたクッキーを発行するように構成されています。これらのクッキーでは、サーバーが SSL (https プロトコル) 経由で要求を発行することが必要ですが、現在の要求は SSL 経由ではありません。"

defaultUrl 属性の指定が無視されるという事例は聞いたことがありませんし、ググって調べても同様な事例は見つかりませんでした。

MSDN フォーラムASP.NET Forum で聞いてみましたが回答は得られませんでした。

というわけで、何故 loginUrl に絶対 URL を指定するとログイン後のリダイレクト先がその URL になってしまうかの原因は、現在のところ分かっていません。(汗)

この問題の解決方法ですが、原因が分かってないので対症療法的ではありますが、一応、以下の手段で回避できることは分かりました。

  1. Login コントロールを使わない。
  2. Login コントロールを使うなら、
    (1) Login.DestinationPageUrl プロパティでリダイレクト先を指定、または
    (2) Login.LoggedIn イベントで強制的にリダイレクトする。

上記 1 の具体的な例は FormsAuthentication.GetRedirectUrl メソッド のサンプルコードを見てください。

上記 2 の (2) の具体例は以下のコードを参考にしてください。

// LoggedIn イベントは、認証プロバイダによってユーザーの資格
// 情報がチェックされ、次の応答でブラウザに送信するために認証 
// Cookie がキューに置かれた後に発生。
protected void LoginUser_LoggedIn(object sender, EventArgs e)
{        
  string userName = LoginUser.UserName;
  string redirectUrl = 
      FormsAuthentication.GetRedirectUrl(userName, false);
  Response.Redirect(redirectUrl);

  // ちなみに以下ではいずれも問題は回避できないので注意。
  // Response.Redirect(redirectUrl, false);
  // FormsAuthentication.RedirectFromLoginPage(userName, false);
}

自分が検証に使った環境は以下の通りです。ASP.NET 4.5 で解決されているかどうかは分かりません。

  • ASP.NET 3.5 および 4
  • Vista 32-bit SP2 の IIS7
  • Visual Studio 2010 Professional
  • SQL Server 2008 Express で aspnetdb.mdf 使用
  • Login コントロールを使用
  • Web Forms アプリ(MVC は問題なし。たぶん Login を使わないため)

Tags:

Authentication

ClientTarget の利用

by WebSurfer 2014年6月14日 16:20

ClientTarget を利用すると ASP.NET によるブラウザの判定を自由に設定できます。

下の画像は、IE9 でアクセスして(一番上の行の HttpRequest.UserAgent プロパティで取得した User Agent 参照)、HttpBrowserCapabilities が Firefox30 と判定されている例です。

ClientTarget の利用

例えば、開発環境で IE11 を持ってなくても、IE11 でアクセスした場合に ASP.NET がどのような html や JavaScript をレンダリングするかを調べるなどに役立つと思います。

ただ、User Agent を偽装するなら Fiddler2 を使えばもっと簡単にできます。なので、あまり使い道はないかもしれませんが、せっかく調べたので書いておきます。

web.config の clientTarget 要素の add 子要素 に任意のブラウザのエイリアスと User Agent を設定します。

ASP.NET 4 の場合、ルート(C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config)の web.config を調べてみると、uplevel と downlevel が定義済みでした。

しかし、appcmd コマンドで調べてみると、以下の画像の通り、uplevel と downlevel に加えて、何故か ie4 と ie5 も定義されています。自分で ie4 と ie5 の定義を追加した覚えはないのですが・・・

デフォルトの clientTarget 要素

ところが、@ Page ディレクティブの ClientTarget 属性で ie4 を指定すると "ClientTarget が無効なエイリアス 'ie4' に設定されています。<clientTarget> 構成セクションは ClientTarget エイリアスを定義するために使用されます。" というエラーになります。(ie5 も同様にエラー。uplevel と downlevel は問題なし) 理由はどうしても分かりません。(汗)

やむをえず、以下のように一旦全て clear して、ie4, ie5, uplevel, downlevel を定義しなおし、IE11 と Firefox30 の定義を追加して検証しました。

<clientTarget>
  <clear/>
  <add alias="ie4" 
    userAgent="Mozilla/4.0 (compatible; MSIE 4.0; Windows NT 4.0)"/>
  <add alias="ie5" 
    userAgent="Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0)"/>
  <add alias="uplevel" 
    userAgent="Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.1)" />
  <add alias="downlevel" 
    userAgent="Generic Downlevel" />
  <add alias="ie11" 
    userAgent="Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"/>
  <add alias="ff30" 
    userAgent="Mozilla/5.0 (Windows NT 6.0; rv:30.0) Gecko/20100101 Firefox/30.0"/>
</clientTarget>

Page.ClientTarget プロパティ のページに書いてありますように、@ Page ディレクティブの ClientTarget 属性に、上の alias 属性に指定された文字列を設定すると、ASP.NET によるブラウザ検出機能が無効になり、userAgent 属性に指定された User Agent 文字列を使ってブラウザが判定されます。

一番上の画像のページの例では @ Page ディレクティブ で ClientTarget="ff30" としているので、実際にアクセスしているのは IE9 ですが、Firefox30 の User Agent でブラウザ判定が行われ、その判定結果が HttpBrowserCapabilities オブジェクトに反映されています。

一番上の画像を出力したコードを参考にアップしておきます。

protected string GetBrowswerCapabilities()
{
    HttpBrowserCapabilities browser = Request.Browser;
    StringBuilder sb = new StringBuilder();
    sb.Append("User Agent: " + Request.UserAgent + 
        "<br /><br />");
    sb.Append("HttpBrowserCapabilities are:<br />");
    sb.AppendFormat("Type = {0}<br />", 
        browser.Type);
    sb.AppendFormat("Name = {0}<br />", 
        browser.Browser);
    sb.AppendFormat("Version = {0}<br />", 
        browser.Version);
    sb.AppendFormat("Major Version = {0}<br />", 
        browser.MajorVersion);
    sb.AppendFormat("Minor Version = {0}<br />", 
        browser.MinorVersion);
    sb.AppendFormat("Platform = {0}<br />", 
        browser.Platform);
    sb.AppendFormat("Is Beta = {0}<br />", 
        browser.Beta);
    sb.AppendFormat("Is Crawler= {0}<br />", 
        browser.Crawler);
    sb.AppendFormat("Is AOL = {0}<br />", 
        browser.AOL);
    sb.AppendFormat("Is Win16 = {0}<br />", 
        browser.Win16);
    sb.AppendFormat("Is Win32 = {0}<br />", 
        browser.Win32);
    sb.AppendFormat("Supports Frames = {0}<br />", 
        browser.Frames);
    sb.AppendFormat("Supports Tables = {0}<br />", 
        browser.Tables);
    sb.AppendFormat("Supports Cookies = {0}<br />", 
        browser.Cookies);
    sb.AppendFormat("Supports VBScript = {0}<br />", 
        browser.VBScript);
    sb.AppendFormat("Supports JavaScript = {0}<br />", 
        browser.EcmaScriptVersion.ToString());
    sb.AppendFormat("Supports Java Applets = {0}<br />", 
        browser.JavaApplets);
    sb.AppendFormat("Supports ActiveX = {0}<br />", 
        browser.ActiveXControls);
    return sb.ToString();
}

Tags:

ASP.NET

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年4月  >>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

View posts in large calendar