knockout asp.net mvc viewmodel json in page source - asp.net-mvc

Before I start, I want to make it clear that my code is working properly, and this is more of a "general best practice" question. I'm using knockout.js to load in my ASP.NET MVC2 model into knockout's viewModel.
In my aspx page I have:
<script>
var model = <%= new JavaScriptSerializer().serialize(Model) %>;
// the above line will display in my page's "View Source". Is this bad? slow?
</script>
Then in my JavaScript include file at the top I have:
$(document).ready(function() {
var viewModel = new MyViewModel();
ko.applyBindings(viewModel);
viewModel.modelProp(model);
});
The code totally works fine, but the concern I have with this is that the JSON output is viewable in the "View Source" option from the browser in the HTML output. I'm curious about two things:
Does this also happen in ASP.NET MVC3? I'm using ASP.NET MVC2, hence I can't use #Html.Raw(Json.Encode(Model)); -- But does the MVC3 method result in the same issue?
Is this something I should be concerned about? Is it a security issue? Is it a performance issue? The page's source will be larger because I'm outputting the JSON into a JavaScript variable, no? Again, maybe it's not an issue in MVC3?

If I hear you correctly, you want to now if you should be concerned that people can see your json. I would not be concerned about that. In fact, not only can they see the json by viewing source, but they can also see it via a network sniffer like fiddler, httpwatch, or browser developer tools (F12). I'm not sure why you care if the json is visible because once it gets data bound to the UI, it will be there too.
As a side note, by loading your KO viewmodel from MVC, that means your viewmodel will only refresh its model data when you post. If you load it via an ajax call (to perhaps an MVC action since you use asp.net mvc) you could avoid that page refresh. Just another option.

Related

Difference between knockout and .NET View Models?

I'm starting MVC and I understand the difference between models and ViewModels, thanks to this post:
http://rachelappel.com/use-viewmodels-to-manage-data-amp-organize-code-in-asp.net-mvc-applications
However I showed this to my colleague and am now under the impression that this is an alternative to using knockout to bind views to models. Can someone explain this? Does knockout binding do the same thing as defining a ViewModel class with properties?
Thank you!
In convention you can use Knockout view-model is as client-side and MVC view-model is as server-side.
Your question : How do you decide which to use ?
Answer : You can use both as parallel.That means for your single cshtml page can have a knockout view-model is as below.It contains both properties and functions as a unit.This view-model for the behavior what you need for the client side functionality.
//This is a simple Viewmodel
//JavaScript that defines the data and behavior of your UI
function AppViewModel() {
var self = this;
self.firstName = ko.observable();
self.lastName = ko.observable();
self.fullName = ko.computed(function () {
return self.firstName() + " " + self.lastName();
});
self.capitalizeLastName = function () {
var currentVal = self.lastName();//Read the current value
self.lastName(currentVal.toUpperCase());//Write back a modified value
};
}
But for show server side behaviors you can use more complex (or more properties) with the MVC view-model.That is for bring data from database and show those data in your view.
Conclusion: So you can use both view-models simultaneously when working with MVC.
Important Note : But if you need to use single view-model for both scenarios then you can do that thing also.For that you have to use KnockoutJS Mapping plugin.
It can be used like below.
<script src="~/Scripts/knockout.mapping-latest.js"></script>
<script type="text/javascript">
$(function() {
var viewModel = ko.mapping.fromJS(#Html.Raw(Model.ToJson()));
ko.applyBindings(viewModel);
});
</script>
You can get more details about this from Loading KnockoutJS View Models from ASP.Net MVC, for faster page loads
If you need to know more about Knockout check learn.knockoutjs
I hope this will help to you.
Knockout view models are client side and MVC is server side, that is the big difference.
Knockout allows you to create single page applications, and encapsulates logic on the client side.
ViewModels in MVC only works server side for rendering the page and handle postbacks.
Xharze answer is valid, but...
If you need to add view related logic to your Business entities that can not be done Client side then you need to have server side View models. If not they become redundant.
There is still a difference to classic MVC, these server side models will not be used to render server side content, they will be exposed to the client side KO engine using REST

ASP.Net Web Api + KnockoutJs + MVC4 - Tying it together

I am starting a new project, and keen to make use of the KnockoutJS + Web Api which are new to me, I have a good understanding of the Web Api, but Knockout is tough to get my head around at the moment.
This is my initial thoughts of how I want my app to work:
I have a standard MVC controller such as LeadsController
LeadsController has an Action called ListLeads, this doesn't actually return any data though, but just returns a view with a template to display data from Knockout.
The ListLeads view calls my api controller LeadsApiController via ajax to get a list of leads to display
The leads data is then mapped to a KnockoutJs ViewModel (I don't want to replicate my view models from server side into JavaScript view models)
I want to use external JavaScript files as much as possible rather than bloating my HTML page full of JavaScript.
I have seen lots of examples but most of them return some initial data on the first page load, rather than via an ajax call.
So my question is, how would create my JavaScript viewModel for Knockout when retrieved from ajax, where the ajax url is created using Url.Content().
Also, what if I need additional computed values on this ViewModel, how would I extend the mapped view model from server side.
If I haven't explained myself well, please let me know what your not sure of and I'll try and update my question to be more explicit.
I think your design is a good idea. In fact, I am developing an application using exactly this design right now!
You don't have to embed the initial data in your page. Instead, when your page loads, create an empty view model, call ko.applyBindings, then start an AJAX call which will populate the view model when it completes:
$(function () {
var viewModel = {
leads: ko.observableArray([]) // empty array for now
};
ko.applyBindings(viewModel);
$.getJSON("/api/Leads", function (data) {
var newLeads = ko.mapping.fromJS(data)(); // convert to view model objects
viewModel.leads(newLeads); // replace the empty array with a populated one
});
});
You'll want to put a "Loading" message somewhere on your page until the AJAX call completes.
To generate the "/api/Leads" URL, use Url.RouteUrl:
<script>
var apiUrl = '#Url.RouteUrl("DefaultApi", new { httproute = "", controller = "Leads" })';
</script>
(That's assuming your API route configured in Global.asax or App_Start\RouteConfig.cs is named "DefaultApi".)
The knockout mapping plugin is used above to convert the AJAX JSON result into a knockout view model. By default, the generated view model will have one observable property for each property in the JSON. To customise this, such as to add additional computed properties, use the knockout mapping plugin's "create" callback.
After getting this far in my application, I found I wanted more meta-data from the server-side view models available to the client-side code, such as which properties are required, and what validations are on each property. In the knockout mapping "create" callbacks, I wanted this information in order to automatically generate additional properties and computed observables in the view models. So, on the server side, I used some MVC framework classes and reflection to inspect the view models and generate some meta-data as JavaScript which gets embeded into the relevant views. On the client side, I have external JavaScript files which hook up the knockout mapping callbacks and generate view models according the meta-data provided in the page. My advice is to start out by writing the knockout view model customisations and other JavaScript by hand in each view, then as you refactor, move generic JavaScript functions out into external files. Each view should end up with only the minimal JavaScript that is specific to that view, at which point you can consider writing some C# to generate that JavaScript from your server-side view model annotations.
For the url issue add this in your _Layout.cshtml in a place where it is before the files that will use it:
<script>
window._appRootUrl = '#Url.Content("~/")';
</script>
Then you can use the window._appRootUrl to compose urls with string concatenation or with the help of a javascript library like URI.js.
As for the additional computed values, you may want to use a knockout computed observable. If that is not possible or you prefer to do it in .Net you should be able to create a property with a getter only, but this won't update when you update other properties on the client if it depends on them.

ASP.NET MVC 2 ExtJs and Ajax post array of objects to controller?

I'm developing an ASP.NET MVC2 web application.
I want to send an array of JSON objects from my view code using AJAX to the controller.
I have seen many examples of hot to do this using jquery.
However I would like to know how to do this using an Ajax request without using jquery?
I have read that updating to MVC3 may help, if this is the best solution can you point me in the right direction on how to update from MVC2 to MVC3?
Below is some sample code:
VIEW
var modRecords = store.getModifiedRecords();
Ext.Ajax.request({
url: AppRootPath +'EmployeeDetails/SetSAASUser',
params: {
users: modRecords
}
});
CONTROLLER
public JsonResult SetUser(IEnumerable<User> users)
{
GetData data = delegate
{
return Repo.SetUser(users);
};
JsonResultBase jsonResult = GetJsonResult(data);
JsonResult json = PortalJsonResult(jsonResult, JsonRequestBehavior.AllowGet);
return json;
}
To MVC3 or not to MVC3
No particular need to convert to MVC3 though because you can consume JSON in MVC2 as well. There are two actually many ways of doing it:
using JsonValueProviderFactory which Phil Haack described in his blog post that would give you exactly equivalent functionality as if you've used MVC3.
Pre-convert your client data so ExtJS will correctly send it to the server. This is somehow similar to what I've done with a jQuery plugin. A very similar thing could be done with ExtJS as well. These two steps are necessary to accomplish it:
First you'd need to analyse how your JSON object is converted on the wire (use Fiddler)
Write code that transforms your JSON into a form that will be correctly sent to the server. What form would that be? You can read about that in my previously mentioned blog post.
I don't know if you're aware of this but there's also something called Ext.Direct for ASP.NET MVC that may help you in this scenario. As it says it support simple, complex and array parameters which covers it actually.
The only advantage of using MVC3 is that JsonValueProviderFactory is enabled for you by default without any additional code.
I've used ExtJS few years ago when it was in version 2. No Ext.Direct and MVC back then yet. But we were very successful in pairing it to an Asp.net WebForms application with async calls to WCF using the same business+data layers as Asp.net WebForms application used.

Is Razor view with ASPX .Master page possible?

Is it possible to keep my existing .master page and have it used with a new ASP.NET MVC 3 Razor view? I tried this:
#{
LayoutPage = "~/Views/Shared/Site.master";
}
And it gives me this error message:
The file '~/Views/Shared/Site.master' could not be rendered, because it does not exist or is not a valid page.
Unfortunately no. Master pages are a part of the ASPX WebForms view engine, not the MVC framework so Razor cannot interoperate with it.
One option would be to duplicate the masters, as you mentioned, but rather than copying all the code, you could factor the Master page into a bunch of ASPX partials that the Razor and ASPX masters could embed. Then you can start converting each page and partial, one-by-one, to Razor and eventually get rid of the ASPX master.
There is actually a way to do this. Scott Hansleman has a blog post on the topic: http://www.hanselman.com/blog/MixingRazorViewsAndWebFormsMasterPagesWithASPNETMVC3.aspx
It's a bit hackish, but doable. I think the approach described could be encapsulated and cleaned up even further so that you could build your views and controllers without worrying about how things are being wired together.
I think you need to look for _Layout.cshtml in the shared folder...
Here is the comparison between aspx and razor view engine....
http://weblogs.asp.net/shijuvarghese/archive/2010/07/29/aspx-and-razor-view-engines-in-asp-net-mvc-3-preview-1.aspx
this is also an interessting post about nested masterpages with razor...
http://weblogs.asp.net/fredriknormen/archive/2010/08/01/asp-net-mvc-3-0-preview-1-razor-and-nested-master-pages.aspx
HTH
Support for .NET User Controls in MVC
MVC does not officially support .Net User Controls but you can retrieve the html produced by them.
The following code retrieves the HTML produced from a page made up of dozens of ASCX files.
Create an ASP page that contains your .Net User Controls within your MVC site.
Get the HTML string produced by your user controls.
Use the HTML string in your MVC Layout page.
Code example:
try{
using (WebClient client = new WebClient())
{
client.Headers[HttpRequestHeader.UserAgent] = "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13";
myHTML = client.DownloadString("http//www.mysite.com/header.aspx");
}
} catch ( WebException exception )
{
using(var reader = new StreamReader(exception.Response.GetResponseStream())){
Response.Write(reader.ReadToEnd());
}
}
#Html.Raw(myHTML ); //OR Response.Write(myHTML);
#RenderBody();
Having just been through this process myself, I found that this method by Matt Hawley worked a treat.
This approach works by creating a standard aspx page that uses your required master page. You can then add content placeholders as required. You then call RenderPartial with the name of the view to use. The response from your controller then gets passed on down to the actual view you want to render.
There is a bit more plumbing required to make this work and you have to call an extensions method to render your view in the controller but once you are setup it works very well.
In Razor you can achieve the same functionality using Layout pages.
Layout/Master pages using Razor

How to create a dashboard user interface using ASP.NET MVC?

I am currently building an application using ASP.NET MVC. The data entry pages are fairly easy to code, I just make the Model for the page of the type of my business object:
namespace MyNameSpace.Web.Views.ProjectEdit
{
public partial class MyView : ViewPage<Project>
{
}
}
Where I am struggling is figuring out the best way to implement a dashboard like interface, with stand-alone parts, using ASP.NET MVC, where the Model for each part would be different? I'm assuming that each part would be an MVC user control.
Also, how could I make it so each part is testable?
I think that user controls is probably the way to go. I'm not sure what the concern is about testability. You should be able to test that your controller is providing the right view data -- since you'll have several models each of these will probably be stored in a separate view data item, rather than aggregating them in a single model. Aggregating in a single model is also possible, although probably more brittle. Each control would just need to check for a particular view data item, rather than being specific to a particular model. You could approximate the model variable on each view page by doing:
<% MyUserControlModel model = ViewData["MyUserControlModel"]
as MyUserControlModel; %>
<div id="myUserControl_dashboard" class="dashboard">
Name: <%= model.Name %><br />
Count: <%$ model.Count %>
</div>
If you need to test your view, then you're probably already using Selenium or some other web testing framework. I don't think that these would care how the page was constructed and you should be able to construct your tests pretty much like you always do.
Check out the notion is sub-controllers in MVC-Contrib http://www.codeplex.com/MVCContrib. Basically you run a full request to a partial then display that partial where you want in your existing code.
Alternatively you can check out this post: http://blog.codeville.net/2008/10/14/partial-requests-in-aspnet-mvc/
Codeplex.com has an open source project "DotNet.Highcharts". This project provides an ASP.NET control that wraps around the excellent (free for personal use) Highcharts charting library. that includes a sample MVC3 project in the downloads section.
URL: http://dotnethighcharts.codeplex.com/
I have posted an article on CodeProject.com that includes a downloadable VS2012 solution and some sample C# code. However I use a webform template in my example, not MVC. The bulk of the dashboard is done using JavaScript libraries, HTML & CSS. I have included some sample C# code to demo data retrieval in C# which in then merged with JavaScript code to render one of the many dashboard charts.

Resources