2016年12月29日木曜日

[ASP.NET MVC] BindAttribute

こういうのです。

public ActionResult Create([Bind(Include = "ItemNo,ItenName,Category,CreateDate")] Item item)

データバインドするプロパティを絞りたいときに使うみたいです。

IncludeとExcludeがあって、

Includeで指定するとカンマ区切りで指定されたプロパティのみがバインド対象になる。

Excludeで指定すると逆にそれらのプロパティがバインド対象外になる。

参考:
http://stackoverflow.com/questions/19490121/need-guide-line-for-mvc-action-method-with-bind-attribute

2013年8月29日木曜日

TFS Workbench がイイ感じ

http://blogs.msdn.com/b/tomohn/archive/2011/11/01/team-foundation-server-tfs-workbench-tfs.aspx

TFS Workbenchというアプリ。

複数のタスクをレーンで区切って見れるがとてもイイ。
一つタスクが終わったら、マウスのドラッグ&ドロップで簡単に完了済みに状態変更できる。
 実際に使って、重宝しています。

ASP.NET MVC HtmlAttributes に CSS classを指定する

引っかかったのでメモ

http://www.wduffy.co.uk/blog/css-class-property-asp-net-mvc-htmlattributes/

class はC#の予約語だからエラーが出ちゃう。だけど先頭に@をつければおk。らしい。

<%= Html.ActionLink("My Link", "MyLink", null, new { @class = "test" }) %>

2013年3月4日月曜日

[EntityFramework]SaveChanges() 時の検証

EntityFramework5で確認


DBの最大文字列長に合わせて、エンティティにもMaxLengthプロパティが表示されるけど


MaxLengthより長い文字列をエンティティに突っ込んでSaveChanges()したら何が起こるの?と思ってやってみた。
(普通はデータアノテーションとかで事前に検証するから、なかなかそんな状況にならないと思うけど)

エンティティのプロパティに文字列をセットした時点では何も起こらず。
SaveChanges()時に例外発生。DbEntityValidationExceptionとな。


SQLExceptionになると思ってたけど、EntityFramework側でちゃんと検証してるんだ…。
検証の内容を出力するには下記のようなコードになった。深い。深いぞう。

                try
                {
                    db.SaveChanges();
                }
                catch (System.Data.Entity.Validation.DbEntityValidationException ex)
                {
                    foreach (var errors in ex.EntityValidationErrors)
                    {
                        foreach (var error in errors.ValidationErrors)
                        {
                            System.Diagnostics.Trace.WriteLine(error.ErrorMessage);    // VisualStudioの出力に表示
                        }
                    }
                    throw ex;
                }



■出力に表示されたエラーメッセージ
フィールド Name は、最大の長さが '50' の文字列型または配列型でなければなりません。



SaveChanges()時の検証の実行は DbContextConfiguration.ValidateOnSaveEnabled プロパティで制御できるみたい。デフォルトはtrue。(EntityFramework5)
http://msdn.microsoft.com/en-us/library/system.data.entity.infrastructure.dbcontextconfiguration.validateonsaveenabled%28v=vs.103%29.aspx


試しにfalseにして、先ほどのコードを動かしてみると
                db.Configuration.ValidateOnSaveEnabled = false;

先ほどと違う例外発生。 DbUpdateExceptionとな。


InnerExceptionのInnerException(深い)にSQLExceptionいた!
ちゃんとEFの検証が無効になって、SQLが発行されているんですなあ~(当たり前)


古いバージョンのEntityFramework2.0だとValidateOnSaveEnabled自体が無かった。
デフォルトでEF側の検証もされないようであった(そもそも検証の仕組みが無い?)

2013年2月12日火曜日

[ASP.NET MVC] テンプレートデリゲート



元々はこのブログ内で紹介されているのを見て気になった。
http://devadjust.exblog.jp/17749006/

> Phill Haack 氏のブログを参照されたし。


参照してみる。

Template Razor Delegate
http://haacked.com/archive/2011/02/27/templated-razor-delegates.aspx

なにこれ…という事で動かしてみたメモ。


上のブログの最初にあるコードがいきなりわからない。


@{
  Func<dynamic, object> b = @<strong>@item</strong>;
}
<span>This sentence is @b("In Bold").</span>




分解して考えてみる


Func<dynamic, object> 

     dynamic 型の引数を取って object 型を返すFuncデリゲート型

@<strong>@item</strong>
     Razorでこのように書くとたぶんFuncデリゲート型のオブジェクトが生成されるのだろう

@b("In Bold")
     b はFuncデリゲート型なので関数として実行できる



ブログ内の英語をがんばって読むと

・Razorでこう書くとFunc<T, HelperResult>が生成されるんだぜ
・@itemが特別なパラメータなんだぜ
・@itemはテンプレート内で何度も呼べるんだぜ

と書いてあるように見える(自信がない)



自分でなにか書いてみる。


■Razor(.chtml)のソース

@model IEnumerable<MvcApplication1.Models.SchoolViewModel>

@{
    ViewBag.Title = "TemplateRazorDelegateTest";
}

<h2>TemplateRazorDelegateTest</h2>

@{
    Func<dynamic, object> hogeFunc =
        @<div>
            @item.Grade 年
            @item.Class 組
            @item.Name さん
         </div>;

}

@foreach (var row in Model)
{
    @hogeFunc(row)
}



動いた。

row 変数には下記のクラスオブジェクトが入っている。


    public class SchoolViewModel
    {
        public int Grade { get; set; }
        public int Class { get; set; }
        public string Name { get; set; }
    }




ところで、@item 以外を書くとどうなるの?
だめだった。@item は特別なパラメータなんだぜ(ってちゃんと書いてあるし)



2013年1月18日金曜日

knockout.jsを動かしてみたメモ


公式ドキュメントを見たほうがいいじゃない
http://knockoutjs.com/documentation/introduction.html


■インストール

VisualStudioのパッケージマネージャーコンソールで以下をタイプしてインストール
Install-Package knockoutjs



当然だけどhtmlに読み込まないと使えない

    <script src="/Scripts/knockout-2.1.0.js" type="text/javascript"></script>


■その1

observableオブジェクトの値を変えてUIも更新させてみる


<span data-bind="text: personName"></span>
<span data-bind="text: personAge"></span>
<button data-bind="click: change">変更</button>

<script type="text/javascript">

    function viewModel() {
        // observableオブジェクトセット(初期値も設定している)
        this.personName = ko.observable("hoge");
        this.personAge = ko.observable(20);

        // ボタンが押されたら変更!
        this.change = function () {
            this.personName("foo");
            this.personAge(22);
        };
    }

    // knockout.jsにview modeをバインド
    ko.applyBindings(new viewModel());

</script>



実行結果




変更ボタンを押すとテキストが変わる。それだけ。
observableオブジェクトの値を変える→UIも更新される の流れ。


■その2

foreachバインドで一覧を生成してみる

<!-- $indexで配列のインデックス値を取得できる(0始まり) -->
<!-- $parentで親のコンテキストを取得できる -->
<table>
  <tbody data-bind="foreach: people">
     <tr>
        <td>[No.<span data-bind="text: $index() + 1"></span>]</td>
        <td data-bind="text: lastName"></td>
        <td data-bind="text: firstName"></td>
        <td>
            <a href="#" data-bind="click: $parent.remove">削除</a>
        </td>
     </tr>
  </tbody>
</table>
<button data-bind="click: change">追加</button>

<script type="text/javascript">

    function viewModel() {
        var self = this;

        // observableArrayをセット(配列で初期化している)
        self.people = ko.observableArray([
            { firstName: '太郎', lastName: 'ほげ' },
            { firstName: '一郎', lastName: 'ふー' },
            { firstName: '三郎', lastName: 'ほげほげ' }
        ]);


        // 追加が押されたら要素追加!
        self.change = function () {
            self.people.push(
                { firstName: '追加分', lastName: '私は' }
            );
        };
        // 削除が押されたら要素削除!
        self.remove = function () {
            self.people.remove(this);
        };
    }

    ko.applyBindings(new viewModel());

</script>



実行結果



いろいろ詰め込みすぎた。

■その3

ko.computedで他のobservableオブジェクトが変更された時に一緒に更新

<!-- valueバインドはコントロールの入力値をview modelに反映させる事ができる -->
氏:<input type="text" data-bind="value: lastName, valueUpdate: 'afterkeydown'" />
名:<input type="text" data-bind="value: firstName, valueUpdate: 'afterkeydown'" />

<br />

<span data-bind="text: personName"></span>

<script type="text/javascript">

    function viewModel() {
        this.lastName = ko.observable('ほげ');
        this.firstName = ko.observable('太郎');
       
        // lastNameとfirstNameが更新されたらpersonNameも更新される
        this.personName = ko.computed(function () {
            return this.lastName() + " " + this.firstName();
        }, this);
    }

    ko.applyBindings(new viewModel());

</script>



実行結果



テキストボックスを編集するとリアルタイムで下のテキストも変わる


■その4

templateバインドでテンプレートを切り替える。あとforeachオプションと一緒に使ってみる。

<!-- nameでテンプレート名の指定を行っている -->

<table>
  <tbody data-bind="template: { name: 'simple-template', foreach: people }">
  </tbody>
</table>

<table>
  <tbody data-bind="template: { name: 'number-template', foreach: people }">
  </tbody>
</table>

<script type="text/html" id="simple-template">
     <tr>
        <td data-bind="text: lastName"></td>
        <td data-bind="text: firstName"></td>
     </tr>
</script>

<script type="text/html" id="number-template">
     <tr>
        <td>[No.<span data-bind="text: $index() + 1"></span>]</td>
        <td data-bind="text: lastName"></td>
        <td data-bind="text: firstName"></td>
     </tr>
</script>

<script type="text/javascript">

    function viewModel() {
        this.people = ko.observableArray([
            { firstName: '太郎', lastName: 'ほげ' },
            { firstName: '一郎', lastName: 'ふー' },
        ]);
    }

    ko.applyBindings(new viewModel());

</script>



実行結果





knockout.jsを使うとhtmlがシンプルになってイイネ!