Archive

Archive for 2010年4月

ASP.NET MVC 2 で簡単データ検証

EnableDynamicDataを利用してWebフォームでDataAnnotationを使ったデータ検証方法をまとめてきましたが、DataAnnotationはASP.NET MVC 2でも利用できます。
その動作を確認できるサンプルを作成してみました。

ただし、サンプルアプリケーション自体の作り方についてはこの記事では説明しません。
ウィザードが生成するスキャッフォールドの状態に最低限の手しか入れてないので、説明する内容もほとんどないですし。

リストページ

サンプルアプリケーションを起動すると上記のようなページが表示されます。
ここでEditリンクをクリックし、データを適当に修正して更新しようとすると、以下のようなエラーが表示されます。

エラー1

このサンプルではEntity Data Modelを利用しています。
そして、上記のエラーを表示させるためのDataAnnotationの設定は以下のプログラムで行っています。

——————————————————————————————————————-

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Data.Objects;

/// <summary>
/// Summary description for Person
/// </summary>
namespace MvcApplication2.Models
{
    [MetadataType(typeof(MetaPerson))]
    [CustomValidation(typeof(MetaPerson), "CheckAge_Mail")]
    public partial class Person
    {
    }

    public class MetaPerson
    {
        [DisplayName("ユーザID")]
        public int id { get; set; }

        [Required(ErrorMessage = "名前は必須項目です")]
        [DisplayName("名前")]
        public string name { get; set; }

        [DisplayName("年齢")]
        [Required(ErrorMessage = "年齢は必須項目です")]
        [Range(0, 120, ErrorMessage = "年齢に誤りがあります")]
        public int age { get; set; }

        [DisplayName("メールアドレス")]
        [RegularExpression(@"\w+([-+.’]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", ErrorMessage = "正しいメールアドレスを入力してください")]
        public string mail { get; set; }

        [DisplayName("備考")]
        [CustomValidation(typeof(MetaPerson), "CheckMinLength")]
        public string memo { get; set; }

        public static ValidationResult CheckMinLength(string memo, ValidationContext vCont)
        {
            if (memo == null || memo.Length < 5)
                return new ValidationResult("5文字以上入力入力してください");
            return ValidationResult.Success;
        }

        public static ValidationResult CheckAge_Mail(Person p)
        {
            if (p.age >= 20 && p.mail == null)
                return new ValidationResult("成人はメールアドレス必須です");
            return ValidationResult.Success;
        }
    }
}

——————————————————————————————————————-

ここで注目してほしいのはPersonクラスに対してCustomValidation属性を設定しているところです。
Personクラスが持つ複数のプロパティの状態をチェックしてエラーを表示することができます。
EnableDynamicDataを利用した場合は、クラスにCustomValidation属性を設定してもそこでのエラーをうまくひろって表示してくれませんでした。
そのため、イベントを登録してデータを保存する直前でValidationExceptionを返すといったプログラムを記述する必要がありました。
ASP.NET MVC 2では同じ内容をCustomValidation属性をクラスに付加することでこんなに簡単に実装できてしまいます。

このエラーは以下のように表示されます。

エラー2

このエラー表示のためにスキャッフォールドで作成されたViewに手を加える必要はありません。
デフォルトの状態でこういったModelレベルでのエラーの表示に対応しています。

ちなみにControllerのほうはちょっと手を加える必要があります。
スキャッフォールドで生成されるEditメソッドだとtry-catchでエラーを拾うようになっていますが、そこを以下のようにModelStateの状態を判断するようなプログラムに置き換えます。
メソッドの引数でModelを利用する点も注意が必要かな。

——————————————————————————————————————-

[HttpPost]
public ActionResult Edit(int id, Person editPerson)
{
    if(ModelState.IsValid)
    {
        pService.UpdatePerson(id, editPerson);
        return RedirectToAction("Index");
    }
    else
    {

        return View(editPerson);
    }
}

——————————————————————————————————————-

なお、このサンプルで利用しているCustomValidation属性ですが、これは.NET Framework 4で追加されたものです。
ASP.NET MVC 2は.NET Framework 3.5上でも動作しますし、その場合にDataAnnotationも使えるのですが、CustomValidation属性は使えませんので注意してください。

ASP.NET MVC 2のテンプレートで生成される認証用のModelではこのあたりを考慮しているのかValidationAttributeを拡張したクラスで独自の検証を行っています。
CustomValidation属性が使えない.NET Framework 3.5ではその方法がもっともシンプルだと思います。

カテゴリー:.NET, ASP.NET 備忘録

サーバへのRIA Servicesのインストール

Installing RIA Services on a server

SERVER=true オプションが重要ってことですね。
ホスティングサーバを借りている場合はどうしようもないでしょうけど、テストサーバを立てるときとか必要な情報になりますね。

カテゴリー:.NET

EnabelDynamicDataで簡単データ検証(SqlDataSource 編)

DataAnnotationによるデータ検証はSqlDataSourceを使っている場合でも有効です。
この場合のサンプルを見ていきます。
例によって動作は LINQ to SQL 編と同じになりますので、動きのほうはそちらを参考に。

SqlDataSourceを使っている場合は、適当な名前(なんでもよい)のクラスを作成し、データ項目と同名のプロパティを設定していきます。
たとえばこんなクラスを作成します。

——————————————————————————————————————-

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

public class Person
{
    [Editable(false)]
    [DisplayName("ユーザID")]
    public int id { get; set; }

    [Required(ErrorMessage = "名前は必須項目です")]
    [DisplayName("名前")]
    public string name { get; set; }

    [DisplayName("年齢")]
    [Required(ErrorMessage = "年齢は必須項目です")]
    [Range(0, 120, ErrorMessage = "年齢に誤りがあります")]
    public int age { get; set; }

    [DisplayName("メールアドレス")]
    [RegularExpression(@"\w+([-+.’]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", ErrorMessage = "正しいメールアドレスを入力してください")]
    public string mail { get; set; }

    [DisplayName("備考")]
    [CustomValidation(typeof(Person), "CheckMinLength")]
    public string memo { get; set; }

    public static ValidationResult CheckMinLength(string memo, ValidationContext vCont)
    {
        if (memo == null || memo.Length < 5)
            return new ValidationResult("5文字以上入力入力してください");
        return ValidationResult.Success;
    }

    public static ValidationResult CheckAge_Mail(int age, string mail)
    {
        if(age >= 20 && mail == string.Empty)
            return new ValidationResult("成人はメールアドレス必須です");
        return ValidationResult.Success;
    }
}

——————————————————————————————————————-

LinqDataSource や EntityDataSourceを利用している場合、データ項目間のチェックにはDynamicValidator に ValidationExceptionを渡すように実装すればよかったのですが、SqlDataSourceを利用している場合はDynamicValidatorが動作しません。
このため、後で述べるようにコードビハインドファイルの中でいくらか面倒な処理を記述しています。
ただ、データ項目間のチェックロジックだけでもまとめて記述したかったので、上記の CheckAge_Mail メソッドにまとめてみました。
このあたり、もっと工夫の余地がありそうにも思います。

Default.aspxは以下のようになります。

——————————————————————————————————————-

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

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

<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<head runat="server">
    <title></title>
    <style type="text/css">
        .DDControl
        {
            color: Red;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ValidationSummary ID="ValidationSummary1" runat="server"
            CssClass="DDControl" />
        <asp:CustomValidator ID="CustomValidator1" runat="server" Display="None" />
        <asp:GridView ID="GridView1" runat="server" DataKeyNames="id"
            DataSourceID="SqlDataSource1" onrowupdating="GridView1_RowUpdating">
            <Columns>
                <asp:CommandField ShowEditButton="True" />
            </Columns>
        </asp:GridView>
        <asp:SqlDataSource ID="SqlDataSource1" runat="server"
            ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
            DeleteCommand="DELETE FROM [Person] WHERE [id] = @id"
            InsertCommand="INSERT INTO [Person] ([name], [age], [mail], [memo]) VALUES (@name, @age, @mail, @memo)"
            SelectCommand="SELECT * FROM [Person]"
            UpdateCommand="UPDATE [Person] SET [name] = @name, [age] = @age, [mail] = @mail, [memo] = @memo WHERE [id] = @id" >
            <DeleteParameters>
                <asp:Parameter Name="id" Type="Int32" />
            </DeleteParameters>
            <InsertParameters>
                <asp:Parameter Name="name" Type="String" />
                <asp:Parameter Name="age" Type="Int32" />
                <asp:Parameter Name="mail" Type="String" />
                <asp:Parameter Name="memo" Type="String" />
            </InsertParameters>
            <UpdateParameters>
                <asp:Parameter Name="name" Type="String" />
                <asp:Parameter Name="age" Type="Int32" />
                <asp:Parameter Name="mail" Type="String" />
                <asp:Parameter Name="memo" Type="String" />
                <asp:Parameter Name="id" Type="Int32" />
            </UpdateParameters>
        </asp:SqlDataSource>
    </div>
    </form>
</body>
</html>

——————————————————————————————————————-

DynamicValidatorが使えないので、CustomValidatorを使ってます。
で、Default.aspx.csは次のようになります。

——————————————————————————————————————-

using System;
using System.Web.UI;
using System.ComponentModel.DataAnnotations;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Init(object sender, EventArgs e)
    {
        GridView1.EnableDynamicData(typeof(Person));
    }
    protected void Page_Load(object sender, EventArgs e)
    {

    }
    protected void GridView1_RowUpdating(object sender, System.Web.UI.WebControls.GridViewUpdateEventArgs e)
    {
        int age = Convert.ToInt32(e.NewValues["age"]);
        string mail = e.NewValues["mail"] == null ? string.Empty : e.NewValues["mail"].ToString();
        ValidationResult vresult = Person.CheckAge_Mail(age, mail);
        if (vresult != ValidationResult.Success)
        {
            CustomValidator1.ErrorMessage = vresult.ErrorMessage;
            CustomValidator1.IsValid = false;
            e.Cancel = true;
        }
    }
}

——————————————————————————————————————-

EnableDynamicDataメソッドに最初に作成したクラスを渡すのが重要です。
また、GridView1_RowUpdatingでデータを更新する前にCheckAge_Mailメソッドを呼び出してエラーチェックをしています。

データの追加を行っているDefault2.aspxもほぼ同じ作りになっています。

LinqDataSource、EntityDataSource、SqlDataSourceのそれぞれの場合について書いてきましたが、当然のようにObjectDataSourceも対応していたりします。
実はMSDNのチュートリアルはObjectDataSourceでの方法が記述されています

チュートリアル:ASP.NET データバインドコントロールの動的データの有効化

このチュートリアルがあることに気づいたのは今日だったりするのですが(w
ちょうどいいのでこのチュートリアルを紹介しておきます。

カテゴリー:.NET, ASP.NET 備忘録

Microsoft Web 開発ガイドライン オンライン版公開

Microsoft Web 開発ガイドライン

ダウンロード版が公開されていたWeb開発ガイドラインのオンライン版も公開されました。
MSDNドキュメントの各所に散らばっている情報が一括で読めて非常に参考になるので、ASP.NETで開発をしているひとはぜひ一度は目を通しておきましょう。
MSDNベースなので、同じ内容が数ヶ所にでてくる点はご愛嬌だと思って(w

これ、非常に良いドキュメントなんですが、読んでいて2点気になったところがあります。
どれも「4. パフォーマンスとスケーラビリティ」の中なのですが。

1点目

設計上の考慮事項 の「ラウンドトリップ数を減らす」という項目のところと ASP.NET ページ の 「Response.Redirect の代わりにServer.Transferの使用を検討する」という項目で同じ意味でServer.Transferを使うべき、というガイドラインが記述されています。
これ、"Response.Redirect" と "Server.Transfer" はどこがどう違うのか、よくわかっている人ならいいんですが、『ガイドラインにこう書いてあるから』というだけで鵜呑みにすると困ったことになりそうです。
"Response.Redirect" と "Server.Transfer" は同じものではありません、というかまったく異なった挙動をします。
単純に置き換えられるものではないので、"Server.Transfer" が使える状況であればたしかにラウンドトリップは減らせるのですが、通常はむしろ "Server.Transfer" は使わないようにしよう、というのが私の個人的なガイドラインだったりします。

2点目

文字列管理 の「出力の書式設定にはResponse.Writeを使う」の内容です。
ループを使って文字列を連結するぐらいなら確かにResponse.Writeのほうが早いのは間違いありません。
ただ、ASP.NETでコントロールを使ってページを構築している中で文字列を連結する場合というのはほとんどありません。
コントロールのレンダリング(HTMLの生成)のタイミングとResponse.Writeのタイミングは異なりますので、このあたり気をつけてプログラムを記述する必要があります。
やってみるとわかりますけど、Response.Writeを使うと、HTMLタグの外側にResponse.Writeで記述した内容が書き出されたりします。

ということで、上記2点は「"Server.Transfer" や "Response.Write" が使えるある特定の状況のときに限って」有効なガイドラインです。
この点には気をつけて読んでいただければと思います。

カテゴリー:.NET

EnableDynamicDataで簡単データ検証(Entity Data Model編)

LINQ to SQL編と同様のことをEntity Data Modelを使うとどう記述するのか、という部分をまとめます。
利用したテーブルの定義と動き方はLINQ to SQL編を参考にしてください。

作成したEntity Data Model(以下EDM)は次のようになります。

EntityDataModel

ここでMetaDataを関連づけたり、クラス内の項目間の関連チェックを行うには、以下のようなソースを記述する必要があります。

——————————————————————————————————————-

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Data.Objects;

namespace DatabaseModel
{
    public partial class DatabaseEntities
    {
        partial void OnContextCreated()
        {
            this.SavingChanges += new System.EventHandler(OnSavingChanges);
        }

        public void OnSavingChanges(object sender, System.EventArgs e)
        {
            var stateManager = ((DatabaseEntities)sender).ObjectStateManager;
            var changedEntities = ObjectStateManager.GetObjectStateEntries(EntityState.Modified | EntityState.Added);

            foreach (ObjectStateEntry stateEntryEntity in changedEntities)
            {
                if (stateEntryEntity.Entity is Person)
                {
                    Person p = (Person)stateEntryEntity.Entity;
                    if (p.age >= 20 && p.mail == null)
                        throw new ValidationException("成人はメールアドレス必須です");
                }
            }
        }
    }

    [MetadataType(typeof(MetaPerson))]
    public partial class Person
    {
    }

    public class MetaPerson
    {
        [Editable(false)]
        [DisplayName("ユーザID")]
        public int id { get; set; }

        [Required(ErrorMessage = "名前は必須項目です")]
        [DisplayName("名前")]
        public string name { get; set; }

        [DisplayName("年齢")]
        [Required(ErrorMessage = "年齢は必須項目です")]
        [Range(0, 120, ErrorMessage = "年齢に誤りがあります")]
        public int age { get; set; }

        [DisplayName("メールアドレス")]
        [RegularExpression(@"\w+([-+.’]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", ErrorMessage = "正しいメールアドレスを入力してください")]
        public string mail { get; set; }

        [DisplayName("備考")]
        [CustomValidation(typeof(MetaPerson), "CheckMinLength")]
        public string memo { get; set; }

        public static ValidationResult CheckMinLength(string memo, ValidationContext vCont)
        {
            if (memo == null || memo.Length < 5)
                return new ValidationResult("5文字以上入力入力してください");
            return ValidationResult.Success;
        }
    }
}

——————————————————————————————————————-

EDMを生成すると、namespace(ここではDatabaseModel)が設定されることに注意する必要があります。
また、LINQ to SQLでは項目間のチェックはOnvalidateパーシャルメソッドを記述するだけでよかったのですが、EDMでは独自のイベントを追加する記述が必要です。
この部分の書き方はMSDNの「方法:データモデルのデータフィールド検証をカスタマイズする」ページを参考にしています。

Default.aspxページは以下のようになります。

——————————————————————————————————————-

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

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

<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<head runat="server">
    <title></title>
    <style type="text/css">
        .DDControl
        {
            color: Red;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ValidationSummary ID="ValidationSummary1" runat="server"
            CssClass="DDControl" />
        <asp:DynamicValidator ID="DynamicValidator1" runat="server"
            ControlToValidate="GridView1" Display="None" />
        <asp:GridView ID="GridView1" runat="server" DataKeyNames="id"
            DataSourceID="EntityDataSource1">
            <Columns>
                <asp:CommandField ShowEditButton="True" />
            </Columns>
        </asp:GridView>
        <asp:EntityDataSource ID="EntityDataSource1" runat="server" EnableDelete="True"
            EnableFlattening="False" EnableInsert="True" EnableUpdate="True"
            EntitySetName="Person" ContextTypeName="DatabaseModel.DatabaseEntities">
        </asp:EntityDataSource>
    </div>
    </form>
</body>
</html>

——————————————————————————————————————-

実はここですごいはまりました。
EDMに追加したOnSavingChangesメソッドがどうやっても呼び出されないのです。
で、いろいろ検索してみたところ、このページが見つかりました。
ウィザードから作成したEntityDataSourceではDefaultContainerNameプロパティとConnectionStringプロパティが設定されているのですが、この設定を使うかわりにContextTypeNameプロパティを利用して使用するEDMの完全修飾型名を指定する必要があったんですね。
上記のソースはこのContextTypeNameを利用しています。

Default.aspx.csはLINQ to SQLとほぼ変わりません。
が、namespaceが設定されている点にだけ注意が必要です。

——————————————————————————————————————-

using System;
using System.Web.UI;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Init(object sender, EventArgs e)
    {
        GridView1.EnableDynamicData(typeof(DatabaseModel.Person));
    }
    protected void Page_Load(object sender, EventArgs e)
    {

    }
}

——————————————————————————————————————-

Default2.aspxのほうは同じ点に気をつけてソースを見てもらえばいいですね。

カテゴリー:.NET, ASP.NET 備忘録

EnabelDynamicDataで簡単データ検証(LINQ to SQL 編)

.NET Framework 4ではDataAnnotationによるデータ検証が様々なところで使えるようになっています。
WebフォームではDynamicDataプロジェクトの中であればこのDataAnnotationによるデータ検証が使えましたが、そのためだけにDynamicDataプロジェクトを採用するのはちょっとおおげさな感じでした。

ASP.NET 4ではEnableDynamicDataという拡張メソッドが導入され、簡単にデータ検証を設定することができるようになっています。
この記事ではLINQ to SQLクラスをベースに、GridViewとDetailsViewを使ったサイト構築に簡単にデータ検証を追加する方法をまとめています。

用意したテーブルは以下のような定義になっています。

Table

ここから作成したLINQ to SQLクラスはこのようになります。

L2Sclass

新規にクラスファイルを追加し、下記の内容を記述します。
LINQ to SQLクラスにMetaDataクラスを関連づけています。

——————————————————————————————————————-

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

[MetadataType(typeof(MetaPerson))]
public partial class Person
{
    partial void OnValidate(System.Data.Linq.ChangeAction action)
    {
        if (age >= 20 && mail == null)
            throw new ValidationException("成人はメールアドレス必須です");
    }
}

public class MetaPerson
{
    [Editable(false)]
    [DisplayName("ユーザID")]
    public int id { get; set; }

    [Required(ErrorMessage = "名前は必須項目です")]
    [DisplayName("名前")]
    public string name { get; set; }

    [DisplayName("年齢")]
    [Required(ErrorMessage = "年齢は必須項目です")]
    [Range(0, 120, ErrorMessage = "年齢に誤りがあります")]
    public int age { get; set; }

    [DisplayName("メールアドレス")]
    [RegularExpression(@"\w+([-+.’]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", ErrorMessage = "正しいメールアドレスを入力してください")]
    public string mail { get; set; }

    [DisplayName("備考")]
    [CustomValidation(typeof(MetaPerson), "CheckMinLength")]
    public string memo { get; set; }

    public static ValidationResult CheckMinLength(string memo, ValidationContext vCont)
    {
        if (memo == null || memo.Length < 5)
            return new ValidationResult("5文字以上入力入力してください");
        return ValidationResult.Success;
    }
}

——————————————————————————————————————-

Default.aspxにはGridViewとLinqDataSourceの設定(とValidation関係の設定をちょっと)を行います。
以下のように記述します。

——————————————————————————————————————-

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

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

<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<head runat="server">
    <title></title>
    <style type="text/css">
        .DDControl
        {
            color: Red;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ValidationSummary ID="ValidationSummary1" runat="server"
            CssClass="DDControl" />
        <asp:DynamicValidator ID="DynamicValidator1" runat="server"
            ControlToValidate="GridView1" Display="None" />
        <asp:GridView ID="GridView1" runat="server" DataKeyNames="id"
            DataSourceID="LinqDataSource1">
            <Columns>
                <asp:CommandField ShowEditButton="True" />
            </Columns>
        </asp:GridView>
        <asp:LinqDataSource ID="LinqDataSource1" runat="server"
            ContextTypeName="DataClassesDataContext" EnableDelete="True"
            EnableInsert="True" EnableUpdate="True" EntityTypeName="" TableName="Person">
        </asp:LinqDataSource>
    </div>
    </form>
</body>
</html>

——————————————————————————————————————-

GridViewに対してウィザードでLinqDataSourceを追加していくと、デフォルトではGridView内に各項目の定義が自動的に追加されてしまいます。
ここは必要ないので削除し、自動的に項目が追加されるようにしておきます。

Default.aspx.csクラスにはEnableDynamicDataの記述を行います。
GridViewに対してプログラムを記述するのはこの部分だけです。

——————————————————————————————————————-

using System;
using System.Web.UI;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Init(object sender, EventArgs e)
    {
        GridView1.EnableDynamicData(typeof(Person));
    }
    protected void Page_Load(object sender, EventArgs e)
    {

    }
}

——————————————————————————————————————-

さて、これで動かしてみましょう。

GridView検証テスト1

MetaDataクラスの中で設定した検証ルールが適用されていることがわかります。

GridView検証テスト2

DataAnnotationでは、予め用意されている検証方法の他に、CustomValidationという形で自分で検証内容を作成し、適用することができます。
上記でこのCustomValidationが正しく動作していることが確認できます。

GridView検証テスト3

クラス内の項目間の関連をチェックする検証はCustomValidationを使っても設定できないようです。
CustomValidationはクラスに対して設定することができる属性なのですが、GridViewとEnableDynamicDataの組み合わせではどうもクラスに設定したCustomValidationをチェックしてくれません。
なので、ここではLINQ to SQLクラスのOnValidateパーシャルメソッドを記述し、ValidationExceptionをDynamicValidatorに拾わせることで検証を行っています。

GridViewではデータの追加はできませんから、データ追加のためのDetailsViewをDefault2.aspxに設定します。

——————————————————————————————————————-

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>

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

<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<head runat="server">
    <title></title>
    <style type="text/css">
        .DDControl
        {
            color: Red;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ValidationSummary ID="ValidationSummary1" runat="server"
            CssClass="DDControl" />
        <asp:DynamicValidator ID="DynamicValidator1" runat="server"
            ControlToValidate="DetailsView1" Display="None" />
        <asp:DetailsView ID="DetailsView1" runat="server" DataKeyNames="id"
            DataSourceID="LinqDataSource1" DefaultMode="Insert">
            <Fields>
                <asp:CommandField ShowInsertButton="True" />
            </Fields>
        </asp:DetailsView>
        <asp:LinqDataSource ID="LinqDataSource1" runat="server"
            ContextTypeName="DataClassesDataContext" EnableDelete="True"
            EnableInsert="True" EnableUpdate="True" EntityTypeName="" TableName="Person">
        </asp:LinqDataSource>
    </div>
    </form>
</body>
</html>

——————————————————————————————————————-

Default2.aspx.csはこんなふうになります。

——————————————————————————————————————-

using System;
using System.Web.UI;

public partial class Default2 : System.Web.UI.Page
{
    protected void Page_Init(object sender, EventArgs e)
    {
        DetailsView1.EnableDynamicData(typeof(Person));
    }
    protected void Page_Load(object sender, EventArgs e)
    {

    }
}

——————————————————————————————————————-

これでDefault2.aspxを動かすと、検証機能が正しく動作することがわかります。

DetailsView検証テスト1

DetailsView検証テスト2

DetailsView検証テスト3

検証ルールは一箇所に書いてあるだけなのに、Default.aspx、Default2.aspxの2つのページで同じ検証が実行されます。
GridViewやDetailsViewにValidationコントローラを埋め込む作業も要りません。
うまく使えると便利な機能なんじゃないでしょうか。

このサンプルを動作させてみるとわかりますが、実はエラーチェックの実行順序等に癖(といっていいのかな?)があり、広く一般に使ってもらうサイトには向かないかもしれません。
ただ、イントラネット内で動作させるプログラムを作るといった限定的なところでは使えるんじゃないでしょうか。

特に検証ルールを後から追加したり変更したりするのが楽なので、とにかく動くものを提供してだんだん作りこんでいくといった方法がとりやすい気がします。

カテゴリー:.NET, ASP.NET 備忘録

Microsoft Web 開発ガイドライン(373ページ)が公開されてます

「Microsoft Web 開発ガイドライン」公開です♪

まぁ、詳しい内容はネタ元の井上さんのBlogを見てもらうこととして(w
基本はMSDNライブラリにあるドキュメントだそうですが、このようにきちんとまとまった形で読めるのはうれしいですね。
といってもさすがにボリュームあるのでまだダウンロードしてページ数確認した程度だったりしますが。

ひととおり読み込んでみたいと思います。

カテゴリー:.NET