Ответ 1
Вы можете использовать ServiceStack JsonSerializer, который довольно быстро в результатах теста вот документация http://mono.servicestack.net/docs/text-serializers/json-serializer и вот этапы http://mono.servicestack.net/benchmarks/
В текущем проекте клиент попросил возможность ответить на вопросник двумя способами: используя Wizard
(по одному вопросу одновременно) и Listing
(все вопросы сразу) в одной форме. Оба способа уже реализованы.
Вопросы загружаются из базы данных в главе руководства с помощью AJAX (это очень быстро). Самая большая глава на данный момент имеет 230
вопросы (каждая с 4 полями ввода HTML - ввод/текст, выбор и т.д.). Если пользователь выбирает такую главу для ответа в формате Listing
, <form>
будет содержать примерно 920
поля, которые будут отправляться на сервер.
Я выполняю запрос AJAX POST, передавая данные с помощью метода jQuery serialize
:
data: $("#questions :input").serialize()
Эта сериализация занимает 207.143ms
для завершения. Я получил это значение для отладки с Firebug в Firefox:
console.profile();
$("#questions :input").serialize();
console.profileEnd();
Снова это супер быстро...
Проблема возникает при увлажнении данных, полученных по следующему методу действий:
public async Task<ActionResult> ListSaveAsync(IEnumerable<AnswerViewModel> questions)
Как вы видите, опубликованные данные привязаны к IEnumerable<AnswerViewModel> questions
. AnswerViewModel
имеет только 4 поля для хранения каждого ответа.
Дело в том, что после нажатия кнопки "Сохранить" требуется значительное количество времени (ровно 10 секунд), чтобы попасть в точку останова по этому методу действия, то есть те 10 секунд будут потрачены в связующем устройстве модели предположительно.
Важно отметить, что я использую Steve Sanderson @Html.BeginCollectionItem helper, чтобы помочь при материализации свойств коллекции ViewModel из HTTP POST. Посмотрите, как данные попадают в ViewModel (Ключи):
Знаете ли вы, что я могу сделать, чтобы оптимизировать это?
Я думал об 4 обходных решениях:
Сохраните только измененные вопросы. Для этого мне нужно сохранить каждое значение ответа в атрибуте data при загрузке листинга и сравнить его с фактическим значением при отправке <form>
, поскольку этот парень предлагает здесь.
Создайте объекты AnswerViewModel
JavaScript на стороне клиента и передайте их методу действий. Будет ли это облегчать модель Binder?
Сверните мою собственную привязку к модели... но я действительно не знаю, будет ли она быстрее, чем стандартная версия ASP.NET MVC. Из того, что я прочитал, связующее устройство по умолчанию делает много отражения для установки значений/гидратации параметра модели действия, и это может быть узким местом.
Используйте FormCollection
и перечислите через опубликованные данные, получив каждое значение по ключу и выполнив проверку вручную, как показано здесь.
Что еще вы предлагаете?
Обновление 1
Я пошел с опцией 3 и реализовал пользовательскую привязку модели: AnswerModelBinder : IModelBinder
и использовал ее в этом конкретном методе действий:
public async Task<ActionResult> ListSaveAsync(
[ModelBinder(typeof(AnswerModelBinder))]List<AnswerViewModel> questions)
Теперь то, что приняло 10 seconds
для завершения, принимает только 2 seconds
.
ModelState
] оказывает большое влияние на производительность.Обновление 2
Я только что испытал это: наличие List<Guid>
в качестве параметра действия и передача только 59 strings
через вызов $.getJson
занимали ~ 3 секунды, чтобы попасть в точку останова в первой строке метода действия. Изменение типа параметра на List<string>
заставил все это работать в мгновение ока.
Интересным фактом является то, что внутри метода действия я сделал это:
List<Guid> userIds = resources.Select(Guid.Parse).ToList();
и он мгновенно преобразует ресурсы List<string>
в List<Guid>
.
Конечно, есть что-то неподходящее с привязкой модели ASP.NET. Я просто хотел бы знать, что это такое...:)
Вы можете использовать ServiceStack JsonSerializer, который довольно быстро в результатах теста вот документация http://mono.servicestack.net/docs/text-serializers/json-serializer и вот этапы http://mono.servicestack.net/benchmarks/
Это может быть не тот ответ, который вы ищете, но он может помочь. Вместо использования FormCollection попробуйте использовать метод контроллера в модели подписи и использовать Ajax.BeginForm(). Это устранит необходимость в сериализации и позволит MVC работать. Кроме того, наличие модели со списком типа Вопрос может стоить изучить. Этот подход также, по-видимому, устранит необходимость перебора значений на почте, поскольку они уже будут в модели.
Я не пробовал это, но когда я использую целочисленные индексы, связующее не имело проблем с привязкой к IEnumerable. Поскольку вы фактически не используете эти Гиды, я бы заменил их целыми числами. (0,1,2...)
Я думаю, вы могли бы сделать это легко на странице, которая отображает форму или использует JS.