ASP.NET MVC 処理順番

Posted in ASP.NET on 10月 18th, 2011 by Site Administrator

controllerクラスの処理順番は下記の通り
1.Execute
2.OnAuthorization
3.OnActionExecuting
4.指定コントローラの指定アクションメソッド
5.View
6.OnActionExecuted
7.OnResultExecuting
8.OnResultExecuted

ASP.NET Sessionフィクセーション対策

Posted in ASP.NET on 9月 16th, 2011 by Site Administrator

[セキュリティ]ASP.NETのセッション固定対策

ASP.NETではSessionIDの再発行処理が扱いにくい(タイミングがAbandonを実行した次のリクエスト時になる)
ということもあり、フィクセーション対策の常套手段である
「認証後にSessionIDを再発行」をどのようにすべきか考えていましたが、上記リンクの下のほうにある
「シンプルにする」が解の一つかと思います。

「新しいSessionを使う」という観点でなく、「誰かに用意されたSessionIDを使わない」という逆の観点での実装ですね。

LINQ 1レコードのみデータ取得

Posted in ASP.NET on 9月 9th, 2011 by Site Administrator
Dim userData As User = (From d In db.Users Where d.username = userAccount).FirstOrDefault

1件もしくは0件のデータを明示的に取得する場合、FirstOrDefaultを使用すれば
単独レコードが取得できます。もしもレコードがなければ、Nothingが格納されます。

ASP.NET MVC 部分ビューへのパラメータ渡し

Posted in ASP.NET on 9月 5th, 2011 by Site Administrator
    Dim viewData As ViewDataDictionary = New ViewDataDictionary()
    viewData.Add("Param1", "param1")
    viewData.Add("Param2", "param2")

    Html.Partial("parts.vbhtml", viewData)

引数にViewDataDictionaryインスタンスを渡せば、部分ビュー内で

    viewData("Param1")

とすれば参照することが可能です。

と、上記の書き方だと問題が発生します。。。

    Dim tmpViewData As ViewDataDictionary = New ViewDataDictionary()
    tmpViewData.Add("Param1", "param1")
    tmpViewData.Add("Param2", "param2")

    ViewData.Add("Param0", "param0")

    Html.Partial("parts.vbhtml", tmpViewData)

上記はコントローラとビューの仲介に使われる「ViewData」も併用している例です。
この場合、Html.Partialが呼ばれると子要素内でViewDataの値はParam1、Param2となります。
子要素内のViewDataが引数のtmpViewDataで上書きされるんですね。
なお、親に戻った場合はViewDataはparam0となります。

    Dim tmpViewData As New ViewDataDictionary(ViewData)
    tmpViewData.Add("Param1", "param1")
    tmpViewData.Add("Param2", "param2")

    Html.Partial("parts.vbhtml", tmpViewData)

パラメータを渡す際は、あくまでViewDataへ追加という形で渡す必要があります。

.NET Framework 4 メンバーシップでSQL Azureを指定する際の設定

Posted in ASP.NET, Azure on 9月 1st, 2011 by Site Administrator

SQL Azureを指定する場合です。
(参考).NET Framework 4 メンバーシップでSQLServerを指定する際の設定

SQL AzureにASP.NETメンバーシップ、ロールデータベース構成

aspnet_regsqlazure.exe -s SERVER.database.windows.net –d DATABASE -u USER -p PASS -a all
※「Cannot grant, deny, or revoke permissions to sa, dbo, entity owner, information_schema, sys, or yourself.」
とエラーが出ても無視して良いみたいです。
専用のツールを使用することで、SQLServerと同様の初期設定を行うことができます。

.NET Framework 4 メンバーシップでSQLServerを指定する際の設定

Posted in ASP.NET on 9月 1st, 2011 by Site Administrator

VisualStudio2010でWebプロジェクトを作成すると、ログイン機能などが実装された
テンプレートがデフォルトで読み込まれます。
このユーザー管理機能はメンバーシップフレームワークを使用するのですが、
初期設定はデータはすべてローカルDBファイルに格納されます。
外部のSQLServerを指定することも可能ですが、その場合はメンバーシップフレームワークに
関連するテーブル等を作成することが必要です。

ユーザー情報を SQL Server 上に作成する

C:WindowsMicrosoft.NETFrameworkv4.0.30319aspnet_regsql.exe
このウィザードを実行することで、必要な初期設定が完了します。

ASP.NET Razor カスタムヘルパー内でのActionLinkの使用

Posted in ASP.NET on 7月 20th, 2011 by Site Administrator

Razorのカスタムヘルパー内でActionLinkを使用する場合、

@helper CustomActionLink(label As String, action As String, controller As String)
    @Html.ActionLink(label, action, controller)
End Helper

上記のように@Helper内でHtml.ActionLinkを使用するとエラーとなります。
Helperのインスタンスが
System.Web.WebPages.Html.HtmlHelper
となっているためです。System.Web.Mvc.HtmlHelperを使うため、

@helper CustomActionLink(html As System.Web.Mvc.HtmlHelper, label As String, action As String, controller As String)
    @html.ActionLink(label, action, controller)
End Helper

と明示的にHtmlヘルパーのインスタンスを渡すようにして回避しました。

ASP.NET MVC コードファースト EF 4.1の規約とデータベースの初期化方法

Posted in ASP.NET on 7月 14th, 2011 by Site Administrator

連載:Entity Framework 4.1入門 第2回 EF 4.1の規約とデータベースの初期化方法

まだまだまとまった記事がないので貴重です。
既存のDBに合わせてコードファーストを使う場合に必要なテクニックになりますので
最初に読んでおいたほうがいいでしょう。

ASP.NET MVC コントローラの非公開メソッド

Posted in ASP.NET on 7月 13th, 2011 by Site Administrator

メソッドにNonActionAttribute属性を付与することで、外部公開されなくなる

    <NonAction()>
    Function Index() As ViewResult
    ...
    End Function

ASP.NET MVC コードファースト エンティティ数とパフォーマンス

Posted in ASP.NET on 7月 13th, 2011 by Site Administrator

コードファーストで、定義したエンティティクラスはcontextクラスにプロパティとして登録することになります。
便利な機能なのですが、ここでふと疑問が。contextはどういう単位で作成すべきなのか?
エンティティ単位にcontextを作成すべきなのか、一つのcontextに詰め込むべきなのか。
はたまた使用するエンティティの種類によって適宜切り替えるべきなのか。
(可能であれば一つのcontextに詰め込んだほうが作りがすっきりする)
想像するに、内部ではエンティティクラスを参照してSQLを組み立てたりしているので、登録されるエンティティが
多くなると、きっとパフォーマンスが悪くなっていくのでしょう。

しかし、いろいろなサンプルを参照しても、一つのcontextにすべてのエンティティをまとめているものばかり。
いったいどれだけのエンティティを詰め込んだらパフォーマンス的に支障が出るのか調べてみました。

調査

エンティティは下記の3クラスを1組とします。各クラスでリレーションが張ってあります。

Public Class SizeTest1Item1
     <Key()>
     <DatabaseGenerated(DatabaseGeneratedOption.Identity)>
     Public Property id As Integer
     Public Property option1_id As Integer
     Public Property data1 As String
     <ForeignKey("option1_id")>
     Public Overridable Property Item() As SizeTest1Item2
End Class
Public Class SizeTest1Item2
     <Key()>
     <DatabaseGenerated(DatabaseGeneratedOption.Identity)>
     Public Property id As Integer
     Public Property option2_id As Integer
     Public Property data2 As String
     <ForeignKey("option2_id")>
     Public Overridable Property Item2() As SizeTest1Item3
End Class
Public Class SizeTest1Item3
     <Key()>
     <DatabaseGenerated(DatabaseGeneratedOption.Identity)>
     Public Property id As Integer
     Public Property data3 As String
End Class

上記の組を名前を変えつつ1、10、20、…、300、500と増やし、contextに登録して計測します。

計測は下記の2つで計測します。
1.contextクラスのインスタンス生成
2.データ取得
2ではincludeを使用して、遅延ロードが行われないよう(joinしたSQLが発行されるよう)にしています。

        Dim sw As New Stopwatch
        sw.Start()
        Dim db As SizeTestContext = New SizeTestContext
        sw.Stop()
        Dim sec As Double = sw.ElapsedTicks / Stopwatch.Frequency
        System.Diagnostics.Debug.WriteLine("time " + sec.ToString())

        Dim id As Integer = DateTime.Now.Ticks Mod 10000
        sw.Reset()
        sw.Start()
        Dim data3 = (From a In db.SizeTest1Item1s.Include("Item").Include("Item.Item2")
                    Where a.id > id).ToList()
        sw.Stop()
        sec = sw.ElapsedTicks / Stopwatch.Frequency
        System.Diagnostics.Debug.WriteLine("sql time " + sec.ToString())

結果

組数 エンティティ数 インスタンス生成(s) データ取得(s)
初回 2回目以降 初回 2回目以降
1 3 0.0040139000 0.00002185 0.380862 0.00700525
10 30 0.0367546 0.000054625 0.6435081 0.0074485
20 60 0.085165 0.000098675 0.9136356 0.010602125
30 90 0.1359965 0.000155375 1.4051476 0.00925665
50 150 0.2135294 0.000204075 2.5750359 0.0142086
100 300 0.4460645 0.000499725 9.8501423 0.02892025
200 600 0.921872 0.001003225 53.739042 0.064910225
300 900 1.3339758 0.00120595 168.6336884 0.1096848
500 1500 2.2109845 0.0026371 718.1666749 0.3085771




組数として30(エンティティ数90)くらいが境目でしょうか。
これを過ぎると急激にパフォーマンスが悪化します。

逆に言えばエンティティ数90程度のシステムであれば、一つのcontextにまとめてしまっても
問題ないとも言えます。

このあたりは、システムの規模に合わせて要検討というところで。