MVC3 - Compress model in viewbag
I have an MVC3 view that's design to run reports for our clients. In the View that lets you select the report options, I pass a large list of our clients (~3K). I'm rendering it like this:
@{Html.RenderPartial("_ClientSelector", ViewBag.Clients as IEnumerable<Client>);}
The _ClientSelector partial looks like this:
<select id="clients" class="clientList" multiple="multiple">
@foreach (Client client in Model) {
var prefix = client.Parent == null ? "" : String.Format("{0}-({1}) / ", client.Parent.Name, client.Parent.Id);
<option value="@client.Id">@prefix@client.Name-(@client.Id)</option>
}
</select>
I'm using the jQuery multiselect library to turn this into a nice visual display.
My question is, is it possible to compress this list server side? By far, the slowest part of this view is loading this list of clients. Using PageSpeed in chrome, it suggests compressing the html to make it load faster, is that possible? If this needs to be in it's own controller action instead of putting it in the ViewBag, I don't mind doing that. I just want to see if there is a way I can speed this page up.
Edit:
I started playing around with the templates you have below. When I build json manually, it works. However when I try to get it from the server using $.getJSON, it never fires on the results. Using debug tools in Chrome, I see the response coming back, and it looks like valid json. Can you spot something wrong with this?
public ActionResult ClientList() {
var clients = reportRepository.GetClientList();
IList<object> model = new List<object>();
foreach (Phoenix.Models.Client c in clients) {
var prefix = c.Parent == null ? "" : String.Format("{0}-({1}) / ", c.Parent.Name, c.Parent.Id);
model.Add(new { value = c.Id.ToString(), text = String.Format("{0}{1}-({2})",prefix,c.Name,c.Id) });
}
return Json(model, JsonRequestBehavior.AllowGet);
}
And in the view:
<script type="text/javascript">
$(function () {
$.getJSON("/Report/ClientList", null, function (data) {
$("#templateOptionItem").tmpl(data).appendTo("#clients");
});
});
</script>
<script id="templateOptionItem" type="test/html">
<option value=\'{{= value}}\'>{{= text}}</option>
</script>
<select id="clients" class="clientList" multiple="multiple">
</select>
--This was another attempt using the $.ajax method, but it too does not fire on the results
$.ajax({
url: "/Report/ClientList",
dataType: "json",
success: function (data) {
$("#templateOptionItem").tmpl(data).appendTo("#clients");
}
});
This is the example that works:
var Clients = [{ value: 1, text: "test123" },
{ value: 2, text: "123test" }]
$("#templateOptionItem").tmpl(Clients).appendTo("#clients");
After much开发者_开发百科 tweaking, I finally got something to work:
$.ajax({
url: "/Report/ClientList",
dataType: "json",
complete: function (data) {
$("#templateOptionItem").tmpl(JSON.parse(data.responseText)).appendTo("#clients");
}
});
I'm still not sure why it would not fire on the on the success event, but using the complete event and doing a JSON.parse on the responseText seems to have done the trick.
Have you thought of sending it down to the view as JSON data and binding it to a template in the client side or using a library like knockout.
The size of the data you are sending is increased largely because you are repeating the same html which you are generating for each of the 3k clients. If you send that down with out mark up the size will be much smaller, and then the code for your list item can be sent down only once with place holders for json data.
EDIT: This example is based on the idea that you are using knockout.
JSON: Mind you if you are using knockout, this object would be annotated with ko.observable functions, or the use of the knockout.mapping.js could be used to auto apply the values across the entire onject
var JsonData = [
{ clientID : 'IDValye', Prefix : 'Some value for the prefix', Name = 'name value' } ,
{ ... }
];
HTML:
<select id="clients" class="clientList" multiple="multiple" data-bind="template :{ name : 'optionTemplate', foreach : JsonData }">
</select>
<script type="text/html" id="optionTemplate">
<option value="${ clientID }">${ Prefix }${ Name }-(${ clientID })</option>
</script>
You can get the rest of the detail on implementation of knockout from the tutorials on their site.
精彩评论