I have an MVC application that I'm using various JsonResult
endpoints to populate the javascript ViewModel.
I have been using several jQuery Ajax requests to populate the model, but I'd like as much of the inital model to be passed to the view on the server.
The ViewModel has 3-5 pieces (depending on where the user is in the application):
I'm currently using this code to load the first three pieces:
$(document).ready(function () {
ko.applyBindings(viewModel);
@Html.Raw(ViewBag.Script)
// Piece 1. Almost always the same thing
postJSON('@Url.Action("HomeViewModelJson", "Home")', function (data) {
if (data == null)
return;
for (var i in data.Tabs) {
viewModel.tabs.push({ name: data.Tabs[i] });
}
for (var i in data.Buttons) {
viewModel.metroButtons.push({ name: data.MetroButtons[i] });
}
for (var i in data.Ribbons) {
viewModel.ribbons.push(data.Ribbons[i]);
}
ApplyButtonThemes();
});
});
// Piece 2. Changes constantly. OK as is
postJSON('@Url.Action("GetNotifications", "NotificationAsync")', function (nots) {
viewModel.notifications.removeAll();
ko.utils.arrayForEach(nots, function (item) {
item.readNotification = function () {
hub.markNotificationAsRead(this.Id);
return true;
};
viewModel.notifications.push(item);
});
});
// Piece 3. Changes but should also be loaded at startup
postJSON('@Url.Action("GetUser", "UserAsync")', function (user) {
viewModel.user(koifyObject(user));
});
postJSON = function(url, data, callback) {
if($.isFunction(data)) {
callback = data;
data = {};
}
$.ajax({
'type': 'POST',
'url': url,
'contentType': 'application/json',
'data': ko.toJSON(data),
'dataType': 'json',
'success': callback
});
};
I tried doing something like this, but I'm finding that by using the @Html.Action("HomeViewModelJson", "Home")
is causing the HTTP headers to get changed and the whole page is sent as if it were JSON
(function (data) {
if (data == null)
return;
for (var i in data.Tabs) {
viewModel.tabs.push({ name: data.Tabs[i] });
}
for (var i in data.MetroButtons) {
viewModel.metroButtons.push({ name: data.MetroButtons[i] });
}
for (var i in data.Ribbons) {
viewModel.ribbons.push(data.Ribbons[i]);
}
ApplyMetroButtonThemes();
})('@Html.Action("HomeViewModelJson", "Home")');
What I'd like to do is use the existing JsonResult
endpoints to get Json data into my ViewModel on the server side, before the page is sent to the user.
Are there any options that will allow me to do that w/o rewriting my controllers?
When rendering the main view you are using a view model, right? In this view model simply populate the properties that you don't want to be fetched with AJAX before returning the view:
public ActionResult Index()
{
MyViewModel model = ...
model.Prop1 = ...
model.Prop2 = ...
return View(model);
}
for example if you have the following action that is used for the AJAX requests:
public JsonResult GetProp1()
{
Property1ViewModel model = ...
return Json(model, JsonRequestBehavior.AllowGet);
}
you could use it from the main action to populate individual properties:
model.Prop1 = (Property1ViewModel)GetProp1().Data;
model.Prop2 = (Property2ViewModel)GetProp2().Data;
and then inside the corresponding view you could use the Json.Encode
method to serialize the entire model into a JSON string:
@model MyViewModel
<script type="text/javascript">
var model = @Html.Raw(Json.Encode(Model));
// You could use model.Prop1 and model.Prop2 here
</script>
or you could also serialize individual properties if you don't need all of them:
@model MyViewModel
<script type="text/javascript">
var prop1 = @Html.Raw(Json.Encode(Model.Prop1));
</script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With