Как обновить данные без перезагрузки страницы в Asp.net ядро MVC с использованием Ajax?

#c# #ajax #asp.net-mvc #asp.net-core

#c# #ajax #asp.net-mvc #asp.net-ядро

Вопрос:

У меня есть фильтрация данных с помощью флажка. Я хочу, чтобы при нажатии на кнопку «Отправить» обновлялись только продукты без перезагрузки страницы

Вот фильтрация:

 <form id="my_form" asp-action="Face" method="get">
    <label>Color:</label>
    <input type="checkbox" name="color" value="black" /><span>Black</span>
    <input type="checkbox" name="color" value="white" /><span>White</span>
    <br />
    <p></p>
    <label>Manufacturer:</label>
    <input type="checkbox" name="brand" value="A" /><span>A</span>
    <input type="checkbox" name="brand" value="B" /><span>B</span>
    <input class="btn btn-info float-right" type="submit" value="Search" />
    //Etc
</form>
 

Мне нужно, чтобы эти данные отображались в первую очередь. И в случае прохождения фильтров они обновлялись в зависимости от того, что я передавал контроллеру

  <div class="row pr-3 pl-3">
            @foreach (var c in Model)
            {
                <div class="filter col-md-3 p-0 hover-bc-card" data-category="@c.PurposeFor">
                    <div class="p-3">
                        <a class="text-decoration-none text-dark" asp-action="Product" asp-controller="Cosmetic" asp-route-id="@c.Id">
                            <div>
                                <img class="card-img-top p-4 bg-white" src=@c.Img alt="@c.Name">
                            </div>
                        </a>
                        <div class="card-body">
                            <h5 class="card-title text-center">@c.Name</h5>
                            <p class="card-text text-center f-sz-12 ">@c.PurposeFor</p>
                            <p class="card-text rounded text-center price-for-list">@c.Price ₴</p>
                        </div>
                    </div>
                </div>
            }
        </div>
 

На всякий случай мой контроллер:

 public IActionResult Face(string[] color, string[] brand, string[] PurposeFor, string sortOrder)
    {

        ViewBag.color = color;
        ViewBag.PurposeFor = PurposeFor;
        ViewBag.brand = brand;
        ViewBag.NameSortParm = string.IsNullOrEmpty(sortOrder) ? "Name_desc" : "";
        ViewBag.PriceSortParm = sortOrder == "Price" ? "Price_desc" : "Price";

        var cosmetics = db.Cosmetics.Where(c => c.PurposeFor.Contains("Face")).ToList();
        var co_cars = new List<Cosmetic>();
        var ma_cars = new List<Cosmetic>();
        var purposeFor = new List<Cosmetic>();


        if (color.Length != 0)
        {
            foreach (string co in color)
            {
                var colorfiltercars = db.Cosmetics.Where(c => c.Color.Contains(co)).ToList();
                co_cars.AddRange(colorfiltercars);
            }
        }
        else
        {
            co_cars = cosmetics;
        }

        if (PurposeFor.Length != 0)
        {
            foreach (string pf in PurposeFor)
            {
                var purposefiltercars = db.Cosmetics.Where(c => c.PurposeFor.Contains(pf)).ToList();
                purposeFor.AddRange(purposefiltercars);
            }
        }
        else
        {
            purposeFor = cosmetics;
        }

        if (brand.Length != 0)
        {
            foreach (string ma in brand)
            {
                var manufacturerfiltercars = db.Cosmetics.Where(c => c.Brand.Contains(ma)).ToList();
                ma_cars.AddRange(manufacturerfiltercars);
            }
        }
        else
        {
            ma_cars = cosmetics;
        }

        var filtercars = co_cars.Intersect(ma_cars);
        filtercars = filtercars.Intersect(purposeFor);

        switch (sortOrder)
        {
            case "Name_desc":
                filtercars = filtercars.OrderByDescending(s => s.Name);
                break;
            case "Price":
                filtercars = filtercars.OrderBy(s => s.Price);
                break;
            case "Price_desc":
                filtercars = filtercars.OrderByDescending(s => s.Price);
                break;
            default:
                filtercars = filtercars.OrderBy(s => s.Name);
                break;
        }
        return View(filtercars.ToList());
    }
 

Комментарии:

1. С какой конкретной проблемой вы сталкиваетесь при выполнении вызова ajax?

2. Я знаю, как вызвать ajax, но не знаю, как использовать его с mvc. Я могу создать кнопку вызова, которая будет работать с ajax и html, но я не смог найти, как объединить все это с mvc.

3. Точнее, я нашел, как использовать его в mvc. Но это не помогло бы моей проблеме

Ответ №1:

Я хочу, чтобы при нажатии на кнопку «Отправить» обновлялись только продукты без перезагрузки страницы

Вы можете обратиться к следующему фрагменту кода, чтобы выполнить отправку AJAX с помощью ненавязчивого AJAX jQuery и динамически обновлять целевой контейнер возвращаемым результатом частичного просмотра.

 <form id="my_form" asp-action="Face" method="get" data-ajax="true" data-ajax-method="get" data-ajax-update="#panel" data-ajax-mode='replace' data-ajax-url="@Url.Action("GetPartial","Home")">
    <label>Color:</label>
    <input type="checkbox" name="color" value="black" /><span>Black</span>
    <input type="checkbox" name="color" value="white" /><span>White</span>
    <br />
    <p></p>
    <label>Manufacturer:</label>
    <input type="checkbox" name="brand" value="A" /><span>A</span>
    <input type="checkbox" name="brand" value="B" /><span>B</span>
    <input class="btn btn-info float-right" type="submit" value="Search" />
</form>
 

Добавить ссылку на jquery-ajax-ненавязчивый

 @section scripts{
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-ajax-unobtrusive/3.2.6/jquery.unobtrusive-ajax.min.js"></script>
}
 

Укажите id атрибут panel для контейнера div

 <div class="row pr-3 pl-3" id="panel">
 

Метод действия, который возвращает частичное представление

 public IActionResult GetPartial(string[] color, string[] brand, string[] PurposeFor, string sortOrder)
{
    //move your query code logic in custom method GetFilterData
    var filtercars = GetFilterData(color, brand, PurposeFor, sortOrder);

    return PartialView("_CarListPartial", filtercars);
}
 

Частичный просмотр _CarListPartial.cshtml

 @model IEnumerable<WebNaApp.Models.Cosmetic>

@foreach (var c in Model)
{
    <div class="filter col-md-3 p-0 hover-bc-card" data-category="@c.PurposeFor">
        <div class="p-3">
            <a class="text-decoration-none text-dark" asp-action="Product" asp-controller="Cosmetic" asp-route-id="@c.Id">
                <div>
                    <img class="card-img-top p-4 bg-white" src=@c.Img alt="@c.Name">
                </div>
            </a>
            <div class="card-body">
                <h5 class="card-title text-center">@c.Name</h5>
                <p class="card-text text-center f-sz-12 ">@c.PurposeFor</p>
                <p class="card-text rounded text-center price-for-list">@c.Price ₴</p>
            </div>
        </div>
    </div>
}
 

Результат теста

введите описание изображения здесь

Комментарии:

1. Вы также можете добиться того же, используя jQuery Ajax, загрузив возвращенный результат частичного просмотра в целевой контейнер div в функции обратного вызова Ajax success.

2. Похоже, это то, что мне нужно. Но мне определенно нужно, чтобы запрос был передан в строку запроса. Чтобы я мог скопировать ссылку и отправить другим с примененными фильтрами

3. I definitely need the request to be passed to the query string. So that I can copy the link and send to others with filters applied Привет @Betsq9, для достижения этого требования, как я упоминал в комментарии, вы можете добиться того же, переведя jQuery Ajax в GetPartial действие, а затем загрузить / добавить возвращенный результат частичного просмотра в целевой контейнер div.

4. Кроме того, если вы проверите фактический запрос на вкладке F12 developer tool Network, вы обнаружите, что приведенный выше код, использующий ненавязчивый AJAX jQuery, также передает данные через строку запроса.

5. @FeiHan Но что, если нам не нужно использовать jQuery?

Ответ №2:

Я предлагаю вам следующий шаг, если вы хотите избежать перезагрузки страницы :

1- jQuery и Ajax Post для отправки данных на контроллер

2- Функция в вашем контроллере для управления данными и отправки ответа с необходимыми данными

3- В части успеха вашего Ajax .clear или .добавьте соответствующую часть HTML, например, div или выберите опцию

вот небольшой пример, который поможет вам, но вы должны адаптировать его в соответствии с вашими потребностями:

В CSHTML: не забудьте добавить идентификатор в свой флажок :

 <button type="button" onclick="checkMe()">Search</button>
<input type="checkbox" id="Checkbox1" />
<input type="checkbox" id="Checkbox2" />
<script>
  function checkMe() {
  // here get value of your checkbox1 
  var Checkbox1state = $('#Checkbox1').prop('checked');
  var Checkbox2state = $('#Checkbox2').prop('checked');
  // and some logic how you want to filter if there is many parameter
  var id =0
  if (Checkbox2state) { id=1 } else {  id=2 };
  
    $.ajax({
      type: "POST",
      url: "/Home/AjaxMethodeCheckMe",
      data: '{id: "'   id   '" }',
      contentType: "application/json; charset=utf-8",
      dataType: "json",
      success: function (ListOfItems) {
        $("#yourDropDown").empty();
        $.each(ListOfItems, function (i, item) {
        $("#yourDropDown").append('<option value="'   item.Value   '">'   item.Text   '</option>');
        });
      },
      failure: function (response) {
        alert("failure");
      },
      error: function (response) {
        alert("error");
      },
    });
  }
  
</script>
 

в вашем контроллере:

 public JsonResult AjaxMethodeCheckMe(int id)
{
    List<SelectListItem> ListOfPort = new List<SelectListItem>();

    ListOfPort.Add(new SelectListItem() { Text = "Text 1", Value = "Value1" });
    ListOfPort.Add(new SelectListItem() { Text = "Text 2", Value = "Value2" });
    ListOfPort.Add(new SelectListItem() { Text = "Text 3", Value = "Value3" });

    return Json(new SelectList(ListOfPort, "Value", "Text"));
}
 

Здесь я показываю, как это сделать с помощью выпадающего списка, но вы можете изменить…