#c# #asp.net-mvc-3 #http-compression
#c# #asp.net-mvc-3 #http-сжатие
Вопрос:
У меня есть представление MVC3, предназначенное для запуска отчетов для наших клиентов. В представлении, которое позволяет вам выбирать параметры отчета, я передаю большой список наших клиентов (~ 3K). Я визуализирую это следующим образом:
@{Html.RenderPartial("_ClientSelector", ViewBag.Clients as IEnumerable<Client>);}
Часть _ClientSelector выглядит следующим образом:
<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>
Я использую библиотеку jQuery multiselect, чтобы превратить это в приятное визуальное отображение.
Мой вопрос в том, возможно ли сжать этот список на стороне сервера? Безусловно, самой медленной частью этого представления является загрузка этого списка клиентов. Используя PageSpeed в Chrome, предлагается сжать html, чтобы ускорить его загрузку, возможно ли это? Если это должно быть в собственном действии контроллера вместо того, чтобы помещать его в ViewBag, я не возражаю против этого. Я просто хочу посмотреть, есть ли способ ускорить эту страницу.
Редактировать:
Я начал играть с шаблонами, представленными ниже. Когда я создаю json вручную, это работает. Однако, когда я пытаюсь получить ее с сервера, используя $.getJSON, она никогда не срабатывает по результатам. Используя инструменты отладки в Chrome, я вижу, что возвращается ответ, и он выглядит как действительный json. Можете ли вы заметить, что с этим что-то не так?
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);
}
И в представлении:
<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>
—Это была еще одна попытка с использованием метода $.ajax, но она тоже не срабатывает в результатах
$.ajax({
url: "/Report/ClientList",
dataType: "json",
success: function (data) {
$("#templateOptionItem").tmpl(data).appendTo("#clients");
}
});
Это пример, который работает:
var Clients = [{ value: 1, text: "test123" },
{ value: 2, text: "123test" }]
$("#templateOptionItem").tmpl(Clients).appendTo("#clients");
После долгих настроек у меня наконец-то получилось что-то сделать:
$.ajax({
url: "/Report/ClientList",
dataType: "json",
complete: function (data) {
$("#templateOptionItem").tmpl(JSON.parse(data.responseText)).appendTo("#clients");
}
});
Я все еще не уверен, почему это не сработало бы при событии успеха, но использование события complete и выполнение JSON.parse в responseText, похоже, сделали свое дело.
Комментарии:
1. Под сжатием html, вероятно, подразумевается динамическое сжатие html, выполняемое веб-сервером, а не вашим приложением.
Ответ №1:
Вы думали о том, чтобы отправить ее в представление в виде данных JSON и привязать к шаблону на стороне клиента или использовать библиотеку, подобную knockout.
Размер отправляемых вами данных увеличивается в основном потому, что вы повторяете один и тот же HTML-код, который вы генерируете для каждого из 3k клиентов. Если вы отправите это без разметки, размер будет намного меньше, и тогда код для вашего элемента списка может быть отправлен только один раз с заполнителями для данных json.
РЕДАКТИРОВАТЬ: Этот пример основан на идее, что вы используете knockout.
JSON: Имейте в виду, что если вы используете knockout, этот объект будет помечен функциями ko.observable или использованием knockout.mapping.js может использоваться для автоматического применения значений ко всему 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>
Остальную информацию о реализации knockout вы можете получить из руководств на их сайте.
Комментарии:
1. как шаблон будет выглядеть для такого списка выбора? Пример на этой странице выглядит как шаблон для одного элемента, поэтому шаблон используется для каждого элемента.
2. хотя knockout выглядит как довольно отличная библиотека, я уже использую jquery, jquery-ui и несколько других плагинов jquery. Я бы не хотел добавлять в проект еще одну большую библиотеку только ради этой части функциональности. Спасибо за идею, однако я продолжу играть с передачей json и посмотрю, есть ли способ сделать это с помощью jquery.
3. В jQuery 1.5 добавлена функциональность создания шаблонов — см. api.jquery.com/category/plugins/templates для получения подробной информации.
4. Да, чувак, использующий движок шаблонов jquery, как я указал в моей первой ссылке. Нокаутирующие данные-bind=»template: {}» функциональность — это просто абстракция. вы могли бы загрузить все данные, просто применив шаблон jQuery, как объясняет Скотт Гу в первой ссылке, которую я добавил к этому случаю.
5. Спасибо за помощь здесь, я думаю, что у меня почти получилось, но мне трудно заставить его принимать json, поступающий с сервера. Я обновил свой первоначальный пост с использованием подхода, который я использую, однако он не работает с результатами из $.getJSON