2

サーバー側で作成したビューモデルをクライアント側で利用するために、knockoutjs マッピングプラグインを使用しています。しかし、私は自分の見解で js コードを書きたくありませんでした。このため、私はにアクセスできないため、Model次のコードのプロパティに値を指定せずに ajax 呼び出しを介してモデルを取得しています。このコードは、外部の js ファイルに記述されています。

var Person = function () {
    var self = this;


    self.SetupKOBindings = function (flagkey) {
        var source = null;
        if (flagkey.val() === "True") {
            this.GetViewModelFromServer = function () {
                $.ajax(
                    {
                        url: "/Person/LoadData",
                        type: "GET",
                        async: false
                    }).
                success(function (data) {
                    if (data !== null && data !== undefined) {
                        source = data;
                        flagkey.val("false");
                    }
                });
            }();
            return ko.mapping.fromJS(source);
        }
        return null;
    };

    self.ViewModel = function (flagkey) {
        this.model = self.SetupKOBindings(flagkey);

        this.model.FullName = ko.computed(function () {
            return this.model.FirstName() + " " + this.model.LastName();
        });

        this.model.ShouldShowFullName = ko.computed(function () {
            return (this.model.FirstName() === null || this.model.LastName() === null) ? false : true;
        });

        this.model.Save = function () {
            if ($(form).valid()) {
                $.ajax(
               {
                   url: "/Person/Index",
                   type: "POST",
                   contentType: "application/json",
                   data: ko.mapping.toJSON(model),
                   async: true
               }).
           success(function (data) {
               ko.mapping.fromJS(model, data);
           });
            }
        }

        return this.model;
    };

    self.ApplyKOBindings = function (vm) {
        ko.applyBindings(vm);
    };

    return this;
};

$(function () {
    var PersonPage = Person();
    var viewModel = PersonPage.ViewModel($('#GetViewModelFromServer'));
    if (viewModel !== null) PersonPage.ApplyKOBindings(viewModel);
});

このアプローチで直面した問題は、投稿アクションを実行するたびに、ページが読み込まれるときに、サーバーからビューモデルを取得するために同じ ajax リクエストが発行され、同じコードが実行されて、フォームが空の vm のプロパティにバインドされることでした。

これを避けるために、隠しコントロールの値を、サーバー側のビューモデルを js オブジェクトに変換するかどうかのフラグとして使用しています。そのため、最初の呼び出しでフラグの値を false に設定しました。

データ注釈を使用して言及された検証メッセージを取得するために、フォームを部分ビューとして作成し、ajax 呼び出しを使用してコンテンツを div のサンプルとして id に置き換えます。unobtrusive-validation とサーバー側の検証を使用したクライアント側の検証は非常にうまく機能し、ノックアウト バインディングも機能します。

コントローラーコード:

 [HttpPost]
        public ActionResult Index(PersonViewModel viewModel)
        {
            if (viewModel.Age < 10)
            {
                ModelState.AddModelError("Age", "bal bla bla");
            }
            if (ModelState.IsValid)
            {
                return PartialView("_Form", viewModel);
            }
            else
            {
                viewModel.GetViewModelFromServer = false;
                return PartialView("_Form", viewModel);
            }

        }

インデックス ビュー:

<div id="sample">
    @Html.Partial("_Form")
</div>

部分図:

@model MVCKOPractise.Models.PersonViewModel
<fieldset>
    <legend>PeopleViewModel</legend>

        @using (Ajax.BeginForm("Index", "Person", new AjaxOptions() { InsertionMode = InsertionMode.Replace, HttpMethod = "POST", UpdateTargetId = "sample" }))
        {
            <div>
                First Name:
            @Html.TextBoxFor(model => model.FirstName, new { data_bind = "value: FirstName,valueUpdate:['afterkeydown','propertychange','input']" })<br />
                @Html.ValidationMessageFor(model => model.FirstName)
            </div>
            <div>
                Last Name:
                    @Html.TextBoxFor(model => model.LastName, new { data_bind = "value: LastName,valueUpdate:['afterkeydown','propertychange','input']" })<br />
                @Html.ValidationMessageFor(model => model.LastName)
            </div>
            <div data-bind="visible: ShouldShowFullName">
                Full Name:
                   <div data-bind="text: FullName"></div>
            </div>
            <div>
                Address:
                    @Html.TextBoxFor(model => model.Address, new { data_bind = "value: Address" })<br />
                @Html.ValidationMessageFor(model => model.Address)
            </div>
            <div>
                Age:
                    @Html.TextBoxFor(model => model.Age, new { data_bind = "value: Age" })<br />
                @Html.ValidationMessage("Age")
            </div>
            @Html.HiddenFor(model => model.GetViewModelFromServer)
            <input type="submit" value="Save" />
        }
</fieldset>

上記の小さなサンプルは私にとってはうまくいきますが、これが先に進むための良い方法であることを知りたいです

  • ビューでjsコードを記述せず、ajax呼び出しを使用してクライアントでビューモデルのコピーを作成し、data-属性を使用してjavascriptのサーバー側のものにアクセスします。
  • ビューのサーバー側でデータ注釈を使用して記述された同じ検証を使用します。ノックアウト検証プラグインと jquery-validation プラグインが利用可能であることは知っています。しかし、mvc data-annotations は検証を data- 属性に変換し、それが jquery によって読み取られます。
4

1 に答える 1