ASP.NET MVC: как преобразовать модель представления в объект Json

Из Руководство по плавающей запятой :

Почему мои цифры, например, 0,1 + 0,2, не совпадают с хорошим раундом 0,3, и вместо этого я получаю странный результат, например, 0,30000000000000004?

. Поскольку внутренне компьютеры используют формат (двоичный с плавающей запятой), который не может точно представлять число, например 0,1, 0,2 или 0,3.

Когда код скомпилирован или интерпретирован, ваш «0,1» уже округлен до ближайшего номера в этом формате, что приводит к небольшой ошибке округления даже до того, как произойдет расчет.

Что можно сделать, чтобы избежать этой проблемы?

Это зависит от того, какие расчеты вы делаете.

  • Если вам действительно нужны ваши результаты, чтобы точно скомпоновать, особенно когда вы работаете с деньгами: используйте специальный decimal datatype .
  • Если вы просто не хотите видеть все эти дополнительные десятичные знаки: просто отформатируйте результат, округленный до фиксированного числа десятичных знаков при его отображении.
  • Если у вас нет десятичных данных ype, альтернативой является работа с целыми числами, например. делать денежные расчеты целиком в центах. Но это больше работает и имеет некоторые недостатки.
blockquote>

Youz также может использовать «нечеткое сравнение» , чтобы определить, достаточно ли близки два числа предположим, что они будут одинаковыми с использованием точной математики.

148
задан Rajmond Burgaj 24 October 2017 в 19:25
поделиться

3 ответа

Отлично, вы только начали использовать MVC и обнаружили его первый серьезный недостаток.

Вы действительно не хотите конвертировать его в JSON в представлении, и вы действительно не хотите конвертировать его в контроллере, поскольку ни одно из этих мест не имеет смысла. К сожалению, вы застряли в этой ситуации.

Лучшее, что я нашел, - это отправить JSON в представление в ViewModel, например:

var data = somedata;
var viewModel = new ViewModel();
var serializer = new JavaScriptSerializer();
viewModel.JsonData = serializer.Serialize(data);

return View("viewname", viewModel);

затем использовать

<%= Model.JsonData %>

в вашем представлении. Имейте в виду, что стандартный .NET JavaScriptSerializer - это довольно дерьмо.

выполнение этого в контроллере, по крайней мере, делает его тестируемым (хотя и не совсем так, как указано выше - вы, вероятно, захотите использовать ISerializer в качестве зависимости, чтобы вы могли имитировать его)

Обновите также, что касается вашего JavaScript, Было бы неплохо обернуть ВСЕ JS виджета, который у вас есть выше, следующим образом:

(
    // all js here
)();

таким образом, если вы поместите несколько виджетов на страницу, у вас не будет конфликтов (если вам не нужен доступ к методам из другого места на странице , но в этом случае вы все равно должны зарегистрировать виджет в какой-либо структуре виджетов). Возможно, сейчас это не проблема, но было бы неплохо добавить скобки сейчас, чтобы сэкономить много усилий в будущем, когда это станет требованием, также хорошей практикой OO является инкапсуляция функциональности.

31
ответ дан 23 November 2019 в 22:03
поделиться

Вы можете использовать Json непосредственно из действия,

Ваше действие будет примерно таким:

virtual public JsonResult DisplaySomeWidget(int id)
{
    SomeModelView returnData = someDataMapper.getbyid(1);
    return Json(returnData);
}

Редактировать

Вы только что видели, что вы предполагаете, что это модель представления, поэтому приведенное выше не является строго правильным, вам нужно будет сделать вызов Ajax метода контроллера, чтобы получить это, ascx тогда не будет иметь модель для Итак, я оставлю свой код на всякий случай, если он будет вам полезен, и вы можете изменить звонок

6
ответ дан 23 November 2019 в 22:03
поделиться

У Эндрю был отличный ответ, но я хотел бы его немного подправить. Отличие в том, что я хочу, чтобы в моих ModelView не было накладных данных. Только данные для объекта. Кажется, что ViewData подходит для этих данных, но, конечно, я новичок в этом деле. Я предлагаю сделать что-то вроде этого.

Controller

virtual public ActionResult DisplaySomeWidget(int id)
{
    SomeModelView returnData = someDataMapper.getbyid(1);
    var serializer = new JavaScriptSerializer();
    ViewData["JSON"] = serializer.Serialize(returnData);
    return View(myview, returnData);
}

View

//create base js object;
var myWidget= new Widget(); //Widget is a class with a public member variable called data.
myWidget.data= <%= ViewData["JSON"] %>;

Что это делает для вас, это дает вам те же данные в JSON, что и в ModelView, так что вы можете потенциально вернуть JSON обратно в ваш контроллер, и у него будут все части. Это похоже на простой запрос через JSONRequest, но требует на один вызов меньше, что экономит ваши накладные расходы. BTW это интересно для Dates, но это, кажется, другая тема.

0
ответ дан 23 November 2019 в 22:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: