- ВКонтакте
- РћРТвЂВВВВВВВВнокласснРСвЂВВВВВВВВРєРСвЂВВВВВВВВ
- РњРѕР№ Р В Р’В Р РЋРЎв„ўР В Р’В Р РЋРІР‚ВВВВВВВВРЎР‚
- Viber
- Skype
- Telegram
Почему не приходят данные на сервер?
Делаю веб-приложение на ASP.NET. В разрабатываемом модуле необходимо сделать возможность добавлять заказ на имя клиента. Скину весь код. Вот код представления с формой
@model OrderFlow.Models.OrdersFlowDB.ViewModels.OrderCreateViewModel
@{
ViewData["Title"] = "Create";
}
<h1>Создать</h1>
<h4>Заказ</h4>
<hr />
<form class="col-md-4" asp-action="Create" method="post">
<div class="form-group">
<label>Клиент</label>
<input type="text" id="clientSearch" class="form-control" placeholder="Введите имя клиента..." />
<input type="hidden" id="clientId" name="ClientId" />
</div>
<div class="form-group">
<label>Юридическое лицо</label>
<select id="legalEntitySelect" class="form-control">
<option value="">Выберите юрлицо</option>
</select>
<input type="hidden" id="legalEntityId" name="LegalEntityId">
</div>
<div class="form-group">
<label>Адрес</label>
<input type="text" name="Address" class="form-control" required />
</div>
<div class="form-group">
<label>Дата начала</label>
<input type="date" name="DateOfStart" class="form-control" required />
</div>
<div class="form-group">
<label>Дата окончания</label>
<input type="date" name="DateOfEnd" class="form-control" required />
</div>
<div class="form-group">
<label for="price">Стоимость</label>
<input type="text" id="price" class="form-control" readonly>
<input type="hidden" id="priceHidden" name="Price">
</div>
<div class="form-group">
<label for="priceWithNDS">Стоимость с НДС</label>
<input type="text" id="priceWithNDS" class="form-control" readonly>
<input type="hidden" id="priceWithNDSHidden" name="PriceWithNDS">
</div>
<div class="form-group">
<label for="productSelect">Товар:</label>
<select id="productSelect" class="form-control"></select>
<label for="productQuantity">Количество:</label>
<input type="number" id="productQuantity" class="form-control" min="1" value="1">
<button type="button" id="addProduct" class="btn btn-success">Добавить товар</button>
<ul id="productList"></ul>
</div>
<button type="submit" class="btn btn-primary">Сохранить</button>
</form>
<div>
<a class="text-white" asp-action="Index">К списку заказов</a>
</div>
Вот модель представления для формы
public class OrderCreateViewModel
{
public string ClientId { get; set; }
public int? LegalEntityId { get; set; }
public string Address { get; set; }
public string? Comment { get; set; }
public DateOnly DateOfStart { get; set; }
public DateOnly DateOfEnd { get; set; }
public decimal Price { get; set; }
public decimal PriceWithNDS { get; set; }
public List<OrderProductViewModel> Products { get; set; } = new List<OrderProductViewModel>();
}
Код контроллера
[HttpGet]
public async Task<IActionResult> Create()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Create(OrderViewModel model, string products)
{
Debug.WriteLine($"Received Price: {model.Price}");
Debug.WriteLine($"Received PriceWithNDS: {model.PriceWithNDS}");
if (!string.IsNullOrEmpty(products))
{
var productList = JsonConvert.DeserializeObject<List<OrderProductViewModel>>(products);
var order = new Order
{
ClientId = model.ClientId,
LegalEntityId = model.LegalEntityId,
Address = model.Address,
Comment = model.Comment,
DateOfStart = model.DateOfStart,
DateOfEnd = model.DateOfEnd,
Price = model.Price,
PriceWithNDS = model.PriceWithNDS,
IsComplete = false,
OrdersProducts = productList.Select(p => new OrdersProduct
{
ProductId = p.ProductId,
Count = p.Quantity
}).ToList()
};
_ordersContext.Orders.Add(order);
await _ordersContext.SaveChangesAsync();
return RedirectToAction("List");
}
return View(model);
}
[HttpGet]
public async Task<IActionResult> SearchUsers(string term)
{
if (string.IsNullOrEmpty(term))
{
return Json(new { });
}
var users = await _userManager.Users
.Where(u => u.UserName.Contains(term) || u.Email.Contains(term) || u.PhoneNumber.Contains(term))
.Select(u => new { id = u.Id, userName = u.UserName, email = u.Email, phone = u.PhoneNumber })
.Take(10) // Ограничиваем кол-во результатов
.ToListAsync();
return Json(users);
}
[HttpGet]
public async Task<IActionResult> GetLegalEntities(string userId)
{
if (string.IsNullOrEmpty(userId))
{
return Json(new { });
}
var legalEntities = await _identityContext.LegalEntities
.Where(le => le.UserId == userId)
.Select(le => new { id = le.Id, companyName = le.CompanyName, inn = le.INN })
.ToListAsync();
return Json(legalEntities);
}
[HttpGet]
public async Task<IActionResult> GetProducts()
{
var products = await _ordersContext.Products
.Select(p => new { id = p.Id, name = p.Name, price = p.Price, nds = p.NDS })
.ToListAsync();
return Json(products);
}
В контроллере есть методы для получения списка пользователей, юридических лиц и товаров, т.к. они получаются через AJAX запросы. Вот, собственно, код js
$(document).ready(function () {
// Поиск клиентов
$("#clientSearch").autocomplete({
source: function (request, response) {
$.ajax({
url: "/Orders/SearchUsers",
type: "GET",
dataType: "json",
data: { term: request.term }, // Текст из инпута
success: function (data) {
response($.map(data, function (item) {
return {
label: item.userName + " (" + item.email + ")" + " (" + item.phone + ")",
value: item.userName,
id: item.id
};
}));
}
});
},
minLength: 2,
select: function (event, ui) {
$("#clientSearch").val(ui.item.value); // Имя пользователя в инпуте
$("#clientId").val(ui.item.id).trigger("change");; // ID пользователя в скрытое поле
return false;
}
});
// Загрузка юрлиц при выборе клиента
$("#clientId").change(function () {
var userId = $("#clientId").val();
var client = $("#clientSearch").val();
console.log("Выбран клиент ID:", userId)
if (userId && client) {
$.getJSON("/Orders/GetLegalEntities", { userId: userId }, function (data) {
console.log("Полученные юрлица:", data);
var options = '<option value="">Выберите юрлицо</option>';
$.each(data, function (index, item) {
options += `<option value="${item.id}">${item.companyName} (ИНН: ${item.inn})</option>`;
});
$("#legalEntitySelect").html(options);
});
} else {
$("#legalEntitySelect").html('<option value="">Выберите клиента</option>');
}
});
$("#legalEntitySelect").change(function () {
let selectedValue = $(this).val();
$("#legalEntityId").val(selectedValue);
});
// Добавление товара
$.ajax({
url: "/Orders/GetProducts",
type: "GET",
success: function (data) {
let productSelect = $("#productSelect");
productSelect.empty();
productSelect.append('<option value="">Выберите товар</option>');
data.forEach(function (product) {
productSelect.append(
`<option value="${product.id}" data-price="${product.price}" data-nds="${product.nds}">
${product.name} (Цена: ${product.price}, НДС: ${product.nds}%)
</option>`
);
});
},
error: function () {
console.error("Ошибка загрузки товаров");
}
});
$("#addProduct").click(function (event) {
event.preventDefault();
let selectedProduct = $("#productSelect option:selected");
let productId = selectedProduct.val();
let productName = selectedProduct.text();
let productQuantity = $("#productQuantity").val();
let productPrice = parseFloat(selectedProduct.attr("data-price")) || 0;
let productNDS = parseFloat(selectedProduct.attr("data-nds")) || 0;
if (!productId) {
alert("Выберите товар!");
return;
}
if (productQuantity <= 0) {
alert("Введите корректное количество!");
return;
}
let totalPrice = productPrice * productQuantity;
let totalNDS = (totalPrice * productNDS) / 100;
let totalPriceWithNDS = totalPrice + totalNDS;
// Проверяем, есть ли уже этот товар в списке
let existingItem = $(`#productList li[data-id='${productId}']`);
if (existingItem.length > 0) {
let currentQuantity = parseInt(existingItem.attr("data-quantity"));
let newQuantity = currentQuantity + parseInt(productQuantity);
existingItem.attr("data-quantity", newQuantity);
existingItem.attr("data-total-price", totalPrice);
existingItem.attr("data-total-price-nds", totalPriceWithNDS);
existingItem.find(".product-info").text(`${productName} - ${newQuantity} шт.`);
} else {
$("#productList").append(
`<li data-id="${productId}" data-quantity="${productQuantity}" data-total-price="${totalPrice}" data-total-price-nds="${totalPriceWithNDS}">
<span class="product-info">${productName} - ${productQuantity} шт.</span>
<button type="button" class="removeProduct btn btn-danger btn-sm">Удалить</button>
</li>`
);
}
updateTotalPrice();
});
// Удаление товара
$(document).on("click", ".removeProduct", function () {
$(this).parent().remove();
updateTotalPrice();
});
// Отправка формы
$("form").submit(function () {
let products = [];
let price = $("#priceHidden").val();
let priceWithNDS = $("#priceWithNDSHidden").val();
let legalEntity = $("#legalEntityId").val();
$("#productList li").each(function () {
let productId = $(this).attr("data-id");
let quantity = $(this).attr("data-quantity");
products.push({ productId, quantity });
});
// Записываем товары в скрытое поле формы
$("<input>").attr({
type: "hidden",
name: "products",
value: JSON.stringify(products)
}).appendTo("form");
if (!price || price <= 0) {
alert("Ошибка: Итоговая стоимость равна 0. Добавьте товары!");
return false;
}
console.log("Цена:", price);
console.log("Цена с НДС:", priceWithNDS);
console.log("Юрлицо:", legalEntity);
});
});
function updateTotalPrice() {
let totalPrice = 0;
let totalPriceWithNDS = 0;
$("#productList li").each(function () {
totalPrice += parseFloat($(this).attr("data-total-price"));
totalPriceWithNDS += parseFloat($(this).attr("data-total-price-nds"));
});
$("#price").val(totalPrice.toFixed(2));
$("#priceHidden").val(totalPrice.toFixed(2));
$("#priceWithNDS").val(totalPriceWithNDS.toFixed(2));
$("#priceWithNDSHidden").val(totalPriceWithNDS.toFixed(2));
console.log("Обновлено в форме: Цена =", totalPrice, "Цена с НДС =", totalPriceWithNDS);
}
И тут проблема в том, что все данные после отправки записываются в БД, кроме стоимости и стоимости с НДС(Price, PriceWithNDS). Точнее, всегда записываются нули вместо реальных чисел. Как видно, в коде js я создал функцию автозаполнения этих полей. Я также сделал проверку на то, что они обновляются в этой же функции
console.log("Обновлено в форме: Цена =", totalPrice, "Цена с НДС =", totalPriceWithNDS);
В консоль выводятся правильные значения.
Далее, в методе отправки формы создал проверку на то, чтобы стоимость не была равна нулю и вывел в консоль отправляемые значения.
if (!price || price <= 0) {
alert("Ошибка: Итоговая стоимость равна 0. Добавьте товары!");
return false;
}
console.log("Цена:", price);
console.log("Цена с НДС:", priceWithNDS);
console.log("Юрлицо:", legalEntity);
Тут тоже всё выводит правильно. Кроме того я запрещаю отправку формы, если цена меньше или равна нулю. Но форма отправляется. Захожу в СУБД и вижу, что всё записалось правильно, кроме этих двух значений (Price и PriceWithNDS) Тогда подумал, что проблема в серверной части, но не совсем так. В начале метода Create в контроллере проверил какие значения приходят на сервер при отправке формы
[HttpPost]
public async Task<IActionResult> Create(OrderViewModel model, string products)
{
Debug.WriteLine($"Received Price: {model.Price}");
Debug.WriteLine($"Received PriceWithNDS: {model.PriceWithNDS}");
И тут выводит нули.
Но почему, ведь при отправке формы выводились правильные числа?
Заметил то, что когда поле заполняется автоматически, то на сервер приходит 0. Но в случае, когда в input нет атрибута readonly и пользователь сам вписывает данные, то они отправляются на сервер.
Ответы (1 шт):
Насколько я помню, чтобы данные получить в контроллер из формы нужно в контроллере указать атрибут [FromForm], правда на счет string products не уверен, что будет приходить, но надо попробовать
Create([FromForm]OrderViewModel model, string products)
- лучше в HTML (в input откуда необходимо будет брать данные для БД) использовать не просто атрибут name, а хелпер asp-for. Так и читаемости больше на мой взгляд и ASP.NET Core точно должен правильно разобрать пришедшие ему данные и десериализовать в объект C#
еще в коде отправки формы
// Отправка формы
$("form").submit(function () {
let products = [];
let price = $("#priceHidden").val();
let priceWithNDS = $("#priceWithNDSHidden").val();
let legalEntity = $("#legalEntityId").val();
$("#productList li").each(function () {
let productId = $(this).attr("data-id");
let quantity = $(this).attr("data-quantity");
products.push({ productId, quantity });
});
// Записываем товары в скрытое поле формы
$("<input>").attr({
type: "hidden",
name: "products",
value: JSON.stringify(products)
}).appendTo("form");
if (!price || price <= 0) {
alert("Ошибка: Итоговая стоимость равна 0. Добавьте товары!");
return false;
}
console.log("Цена:", price);
console.log("Цена с НДС:", priceWithNDS);
console.log("Юрлицо:", legalEntity);
});
ты отправляешь форму до своих махинаций. в submit ты передаешь функцию которая выполнится вместе с отправкой, а не до нее. Попробуй сделать так:
// Отправка формы
let products = [];
let price = $("#priceHidden").val();
let priceWithNDS = $("#priceWithNDSHidden").val();
let legalEntity = $("#legalEntityId").val();
$("#productList li").each(function () {
let productId = $(this).attr("data-id");
let quantity = $(this).attr("data-quantity");
products.push({ productId, quantity });
});
// Записываем товары в скрытое поле формы
$("<input>").attr({
type: "hidden",
name: "products",
value: JSON.stringify(products)
}).appendTo("form");
if (!price || price <= 0) {
alert("Ошибка: Итоговая стоимость равна 0. Добавьте товары!");
return false;
}
console.log("Цена:", price);
console.log("Цена с НДС:", priceWithNDS);
console.log("Юрлицо:", legalEntity);
$("form").submit();