Hank
Hank

Reputation: 2646

How to send json object to razor model then angularjs

This is the way I was sending my model to an angular controller scope.

c# Controller:

public class AreaMenuController : RootController
{
    // GET: Menu
    public PartialViewResult Index()
    {
        var mod = Modules.Instance.ModuleList.FirstOrDefault(m => m.Prefix.Equals(base.GetArea(), StringComparison.CurrentCultureIgnoreCase));
        return PartialView("_AreaMenu", mod.ModuleMenus);
    }
}

View cshtml:

@using Nuclei.Models
@model IEnumerable<Nuclei.Models.Menu>
<script type="text/javascript">
    @{ var serializer = new System.Web.Script.Serialization.JavaScriptSerializer(); }
    window.areaMenus = @Html.Raw(serializer.Serialize(Model));
</script>
<script type="text/javascript" src="@Url.Content("~/Scripts/AngularControllers/_AreaMenuController.js")"></script>
<div ng-controller="AreaMenuController as vm" ng-init="vm.initializeController()">
    <div id="accordion" ng-class="accordian-menu" style="visibility: visible;">
        <ul>
            <li ng-repeat="menu in vm.areaMenus">
                ...
            </li>
        </ul>
    </div>
</div>

Angular Js file:

var NucleiApp = angular.module('NucleiApp');
NucleiApp.controller('AreaMenuController', ['$scope', '$http', '$location', function ($scope, $http, $location) {

    "use strict";

    var vm = this;

    vm.initializeController = function () {
        vm.areaMenus = window.areaMenus;
    }
}]);

Question 1: Is there a smoother way to send your c# model through to angular other than through global window object?

You can use an $http get from angular, however because this is processed client-side there is always a bit of lag before it gets displayed, because it needs to call the c# controller and get the data. So I'm reserving $http get for updates only.

The other other way I was thinking was to send the view a Json object straight off:

c# controller:

public class AreaMenusController : RootController
{
    // GET: Menu
    public PartialViewResult Index()
    {
        return PartialView("_AreaMenu", GetAreaMenus());
    }

    public JsonResult GetAreaMenus()
    {
        var mod = Modules.Instance.ModuleList.FirstOrDefault(m => m.Prefix.Equals(base.GetArea(), StringComparison.CurrentCultureIgnoreCase));

        return Json(new { areaMenus = mod.ModuleMenus }, JsonRequestBehavior.AllowGet);
    }
}

View cshtml:

@using System.Web.Mvc
@model JsonResult
<script type="text/javascript">
    window.areaMenus = @Model;
</script>

Question 2: I'm not really sure how to initialize the @model at this point and send it through to the angular file and again, if there is a better option than javascripts global window object... open to suggestions!

Upvotes: 0

Views: 459

Answers (1)

Brendan Green
Brendan Green

Reputation: 11954

We currently do this to bootstrap a set of data that is later updated by a call into a WebAPI.

The reason we do this is we have found cases where the data, when bootstrapped via an API call, was coming back too slowly, which gave a bad experience to our users.

In our razor view:

<html>
    <head>
        <script>
            window.areaMenus = '@Html.Raw(Model.SerializedJsonString)';
        </script>
    </head>
</html>

Then when our angular app is Run(), we deserialize the data, and use it from there:

var app = angular.module('myApp', ["stuff"])
    .run(["menuService", (menuService) => {
        // deserialize the json string into my object
        var areaMenus = angular.fromJson(window.areaMenus);
        // do something with it
        menuService.Load(areaMenus);
    }]);

This'll get the data available to angular immediately without having to wait for a $http request to complete, which should address your issue.

Upvotes: 1

Related Questions