0

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!

7
  • 1
    Really angular is designed to work with a SPA model where you get everything you need from the server via api calls which return JSON, rather than by the kind of templating you are doing here using razor. Commented Feb 22, 2019 at 1:34
  • I ask this in a friendly manner. If that is the case do you find the lag that I'm talking about when rendering content via angular when loading a page all the time. I'm actually finding angular a heck of a lot better for templating versus the razor and jquery combination? And it's great for updating your client-side model, not so much for the initial load, that's why I'm mixing it up a little. Commented Feb 22, 2019 at 2:00
  • However this still doesn't answer the question of initializing the razor model that's what I'm looking for right now. Commented Feb 22, 2019 at 2:01
  • 1
    Well that's why Angular is better for SPA - precisely because you don't reload the page all the time. Initial load time for angular is not insignificant. So you load all that once only and everything after that is just JSON API calls. Commented Feb 22, 2019 at 2:02
  • 1
    And yes @Hank, I understand I'm not answering the direct question. That's why I'm offering this as a comment. Often the real answer to a question is to think about the problem differently or change tack. You can of course inject razor content anywhere into a javascript file, and when I first started playing with Angular I did just that. Never went via the window object. I'm not sure why you're finding that necessary. However, everything will make sense and run more smoothly if you switch to API calls instead of page loads. I understand the transition is a big time investment however. Commented Feb 22, 2019 at 2:08

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

5 Comments

This is exactly my thinking, you're kind-of getting the best of both worlds. The first set of examples were working fine, I just wanted to refine it. In the second example instead of sending the actual ModuleMenu objects I doing the serialization at the server and sending the json object to the view. So what worked in the end was trimming your answer a little: window.areaMenus = @Html.Raw(Model);
I can't have had that right, it stopped working. If I'm sending json data straight to the model I shouldn't have to do any serialization before adding it to window.areaMenus and angular should I?
Also were you using any @using declarations to initialize the model? And if window.areaMenus is in json format, shouldn't angular be able to read it as is?
Well, what is the content of your @Model? Is this a serialized json string? You are not assigning an object to window.areaMenus, you need to pass along a string containing serialized json, and then deserialize it on the angular side.
Ah, I was serializing a JsonResult, which worked but got strange results in angular, as you would expect. I didn't have to do: angular.fromJson() it worked without it. Not sure where SerializedJsonString is coming from, is this your own extension?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.