satymale’s diary

日々の忘備録

ASP.NET4.6+W2UIでデータを保存する

サーバー側で変更分が分からない問題

W2UIで入力されたデータを保存すると、変更があった差分のみがサーバーに渡されます。 例えば次のようなGridのlnameとsdateを編集して保存すると

$('#grid').w2grid({
    name : 'grid',
    url  : {
        get    : 'server/side/path/to/records',
        remove : 'server/side/path/to/remove',
        save   : 'server/side/path/to/save'
    },
    columns: [                
        { field: 'recid', caption: 'ID', size: '50px' },
        { field: 'lname', caption: 'Last Name', size: '30%' },
        { field: 'fname', caption: 'First Name', size: '30%' },
        { field: 'email', caption: 'Email', size: '40%' },
        { field: 'sdate', caption: 'Start Date', size: '120px' },
        { field: 'edate', caption: 'End Date', size: '120px' }
    ]
});

次のように変更分のみサーバーに送信されます。

cmd:save-records
selected[]:1
limit:100
offset:0
changes[0][recid]:1
changes[0][lname]:hoge
changes[0][sdate]:2016/01/23

サーバー側のコントローラーでは次のように、パラメータの型に動的にマッピングされるため変更されたプロパティにしか値が設定されません。

public class GridSaveParameter<T> {
    public string Cmd { get; set; }
    public int[] Selected { get; set; }
    public int Limit { get; set; }
    public int Offset { get; set; }
    public List<T> Changes { get; set; }
}

public class Hoge {
    public string Recid { get; set; }
    public string Lname { get; set; }
    public string Fmame { get; set; }
    public string Email { get; set; }
    public DateTime Sdate { get; set; }
    public DateTime Edate { get; set; }
}

public ActionResult Save(GridSaveParameter<Hoge> param) {
    // 保存処理
}

そうなると、保存する際に値なしに変更されたのか、変更されていないのかを判断することが出来なくなります。

すべての値を送る

上記のように、変更分のみをサーバー側に送信すると、値を空にした場合が判断できなくなるため、 クライアント側で、変更があった行のすべての値をサーバー側に送るように少し手を加えます。 urlの指定からsaveを消して、保存ボタン押下時のイベントで自前で値をサーバー側に送信します。

$('#grid').w2grid({
    name : 'grid',
    url  : {
        get    : 'server/side/path/to/records',
        remove : 'server/side/path/to/remove',
    },
    columns: [                
        { field: 'recid', caption: 'ID', size: '50px' },
        { field: 'lname', caption: 'Last Name', size: '30%' },
        { field: 'fname', caption: 'First Name', size: '30%' },
        { field: 'email', caption: 'Email', size: '40%' },
        { field: 'sdate', caption: 'Start Date', size: '120px' },
        { field: 'sdate', caption: 'End Date', size: '120px' }
    ],
    onSubmit: function (event) {
        // 2016.08.07 追記
        // url.saveを消すことで、保存した際に、サーバからのstatusがerrorか否かに関わらず
        // 編集箇所がクリアされる分岐に入ります。
        // そのため、既定の保存処理を中断しておきます。
        event.isCancelled = true;

        var chgRows = w2ui['grid'].getChanges();
        
        // 変更があった行の変更前のすべての値を持った行に変更された値を上書き
        var rows = $.map(chgRows, function (n, i) {
            return $.extend(w2ui['grid'].get(n.recid), n);
        });
        
        w2ui['grid'].request('save-records', { changes: rows }, 'server/side/path/to/save');
    }
});

上記のようにすると値が空の場合は素直に空になって送信されるので、サーバー側では特に考慮することなく保存すれば良くなります。