[AngularJS][ASP.Net MVC] 將ViewModel從後端注入AngularJS Controller中

如何將ViewModel從後端傳遞至AngularJS Controller中進行繫結

前言

 

在使用ASP.Net MVC開發時,通常會依據View中所需資訊定義一個View Model作為頁面資料繫結之用,因此就可以在後端Controller中賦予View Model特定內容,接著將View Model傳入View後,利用檢視頁面Model強型別的特性,搭配HtmlHelper來呈現View Model中各屬性之資料內容。

 

當前端套用AngularJS框架後,在View設計上就很少會使用HtmlHelper擴充方法來產生匹配物件屬性的Html了,而是自行建立Html元素並利用AngularJS所提供的ng-model Directive作資料繫結設定。如此是否表示View中所宣告@model(View Model)已無用武之地? 其實不然,我們還是可以利用後端Controller將View Model資料傳入View中的機制,讓AngularJS繫結機制幫忙呈現View Model資料做為畫面初始值;有興趣的朋友可以參考以下做法來實現。

 

 

實作說明

 

以用戶資訊編輯功能為例,首先定義用戶資訊類別(User)作為編輯畫面View Model使用


{
    public class User
    {
        public string UserId { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }

    }
}

 

接著Controller中模擬取得該User資料作為View Model,並傳送至View中顯示資料內容


{
    public class HomeController : Controller
    {
        public ActionResult Edit(string userId)
        {
            // 模擬取得該userId之用戶資料
            var viewModel = new User()
            {
               UserId = "Chris",
               Name = "Chris Chen",
               Address = "Taiwan Taipei..."
            };

            // 傳出ViewModel至頁面
            return View(viewModel);
        }
    }
}

 

若使用ASP.Net MVC進行資料繫結的View如下。主要先宣告此頁面使用的View Model為User類別,接著就可以透過HtmlHelper幫忙產出對應View Model中各屬性所需之Html代碼,並且將值賦予至各元素中,而產出的Html元素名稱(Name)將做為資料回傳伺服端資料綁定之依據。



@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    
    <div class="form-horizontal">
        <h4>User</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @Html.HiddenFor(model => model.UserId)

        <div class="form-group">
            @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Address, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Address, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Address, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
}

 

產出前端畫面如下(ViewModel屬性值皆繫結[via ASP.Net MVC]至頁面上)

 

image

 

 

當前端要套用AngularJS框架時,首先會在JS檔中建立module及controller如下。

 

image

 

由於我們可以在View中獲得從後端Controller傳入之View Model資料,因此直接將此頁面繫結的View Model(User)資料內容轉換成JSON格式,並以此資料建立viewModel Value Provider供後續注入前端AngularJS controller中使用。

 

image

 

接著就可以在前端controller中注入viewModel了。先將viewModel資料存入controller的editUser屬性中。

 

image


	.module('app', [ ]);

angular
    .module('app')
    .controller("UserController", function (viewModel) {
        var vm = this;

    	// set viewModel as editUser
        vm.editUser = viewModel;

    	// edit user via web api
        vm.Edit = function () {
			//...
        }
    });

 

經過前面的努力後,前端controller的editUser屬性就是後端Controller傳入View中的View Model(User)資料,因此我們就可以依照View Model(User)資料結構來設定各Input元素的ng-model資訊如下。

 

image



<div class="form-horizontal" ng-controller="UserController as ctrl">
    <h4>User</h4>
    <hr />
    
    <div class="form-group">
        <label class="control-label col-md-2" for="Name">Name</label>
        <div class="col-md-10">
            <input type="text" ng-model="ctrl.editUser.Name" class="form-control" />
        </div>
    </div>

    <div class="form-group">
        <label class="control-label col-md-2" for="Address">Address</label>
        <div class="col-md-10">
            <input type="text" ng-model="ctrl.editUser.Address" class="form-control" />
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="button" value="Save" ng-click="ctrl.Edit()" class="btn btn-default" />
        </div>
    </div>
</div>

@section Scripts {
    <script>    
        // 將Model轉換成JSON
        var model = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(this.Model));
        // 建立 viewModel Value Provider 供後續注入controller使用
        angular.module('app').value("viewModel", model);
    </script>
}

 

執行後前端畫面如下(ViewModel屬性值皆繫結[via AngularJS]至頁面上),實現了我們的需求。

 

image

 

 

 

參考資料

 

http://davideguida.altervista.org/angularjs-mvc-how-to-pass-model-from-server-to-angular-controller/


希望此篇文章可以幫助到需要的人

若內容有誤或有其他建議請不吝留言給筆者喔 !