Будет ли метод работать асинхронно
Объясните, пожалуйста, про асинхронность!
В проекте у меня есть ajax.beginform во View Index.cshtml, в которой выпадающий список и по имени это все отсылается в метод возвращающий частичное представление.
View Index.cshtml
@model IEnumerable<Checkitlink.Models.ViewModels.UserVM>
@{
ViewBag.Title = "Список пользователей";
AjaxOptions ajaxSort = new AjaxOptions()
{
UpdateTargetId = "list",
Url = Url.Action("UsersQueryPartial")
};
}
@using (Ajax.BeginForm(ajaxSort))
{
<ul class="navbar-nav userDropdown btn-group btn btn-info" style="margin-right: 15px; border-radius: 15px;">
<li class="nav-item dropdown">
<a class="dropdown-toggle userDropdown" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Сортировать
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<li class="dropdown-submenu">
<a class="dropdown-item dropdown-toggle" data-toggle="dropdown" href="#">Статус</a>
<ul class="dropdown-menu">
<li>
<button name="sort" value="user_active">Активные</button>
</li>
<li>
<button name="sort" value="user_block">Заблокированные</button>
</li>
</ul>
</li>
<li class="dropdown-submenu">
<a class="dropdown-item dropdown-toggle" data-toggle="dropdown" href="#">Кол-ву ссылок</a>
<ul class="dropdown-menu">
<li>
<button class="dropdown-item" name="sort" value="linksCount_asc">Возрастанию</button>
</li>
<li>
<button class="dropdown-item" name="sort" value="linksCount_desc">Убыванию</button>
</li>
</ul>
</li>
</ul>
</li>
</ul>
}
<div id="list">
@Html.Action("UsersQueryPartial")
</div>
Родительский и дочерний метод из контроллера
public ActionResult Index()
{
return View();
}
public ActionResult UsersQueryPartial(string sort, string filter, int? page)
{
List<UserVM> usersList = new List<UserVM>();
var pageNumber = page ?? 1;
using(ChekitDB chekitDB = new ChekitDB())
{
string SortQuery = string.IsNullOrEmpty(sort) ? "login_asc" : sort;
switch (SortQuery)
{
case "login_asc":
usersList = chekitDB.Users.ToArray().Where(x => x.BanStatus == false).OrderBy(x => x.Login).Select(x => new UserVM(x)).ToList();
break;
case "user_active":
usersList = chekitDB.Users.ToArray().Where(x => x.BanStatus == false).OrderBy(x => x.Login).Select(x => new UserVM(x)).ToList();
break;
case "user_block":
usersList = chekitDB.Users.ToArray().Where(x => x.BanStatus == true).OrderBy(x => x.Login).Select(x => new UserVM(x)).ToList();
break;
case "linksCount_asc":
usersList = chekitDB.Users.ToArray().Where(x => x.BanStatus == false).OrderBy(x => x.LinksCount).Select(x => new UserVM(x)).ToList();
break;
case "linksCount_desc":
usersList = chekitDB.Users.ToArray().Where(x => x.BanStatus == false).OrderByDescending(x => x.LinksCount).Select(x => new UserVM(x)).ToList();
break;
default:
usersList = chekitDB.Users.ToArray().Where(x => x.BanStatus == false).OrderBy(x => x.Login).Select(x => new UserVM(x)).ToList();
break;
}
if(filter != null)
{
usersList = usersList.Where(x => x.SearchInfo().ToLower().Contains(filter.ToLower())).ToList();
}
}
var usersOnPage = usersList.ToPagedList(pageNumber, 20);
ViewBag.usersOnPage = usersOnPage;
return PartialView("_UsersQueryPartial", usersOnPage);
}
Частичное представление _UsersQueryPartial.cshtml
@model IEnumerable<Checkitlink.Models.ViewModels.UserVM>
@using PagedList.Mvc;
@using PagedList;
@if (!Model.Any())
{
<h2>Пользователей не обнаружено</h2>
}
else
{
<div class="d-table">
<div class="d-tr">
<div class="d-td">
@Html.DisplayNameFor(model => model.Login)
</div>
<div class="d-td">
@Html.DisplayNameFor(model => model.Email)
</div>
<div class="d-td">
@Html.DisplayNameFor(model => model.LinksCount)
</div>
<div class="d-td">
@Html.DisplayNameFor(model => model.BanStatus)
</div>
<div class="d-td">
Действия
</div>
</div>
@foreach (var item in Model)
{
<div class="d-tr">
<div class="d-td">
@Html.DisplayFor(modelItem => item.Login)
</div>
<div class="d-td">
@Html.DisplayFor(modelItem => item.Email)
</div>
<div class="d-td">
@Html.DisplayFor(modelItem => item.LinksCount)
</div>
@if (item.BanStatus == false)
{
<div class="d-td text-success">
Активный
</div>
}
else
{
<div class="d-td">
<a class="text-danger" href="~/admin/user/BlackList" style="text-decoration:none" title="Посмотреть причину">Заблокирован</a>
</div>
}
<div class="d-td">
@Html.ActionLink("Инфо", "InfoUser", new { id = item.UserId }, new { @class = "btn btn-info" }) |
@Html.ActionLink("Редактировать", "EditUser", new { id = item.UserId }, new { @class = "btn btn-primary" }) |
@if (item.Role == "Админ")
{
@Html.ActionLink("Заблокировать", "BanUser", new { id = item.UserId }, new { @class = "btn btn-warning disabled" })
string slash = " | ";
@slash
@Html.ActionLink("Удалить", "DeleteUser", new { id = item.UserId }, new { @class = "btn btn-danger disabled" })
}
else
{
@Html.ActionLink("Заблокировать", "BanUser", new { id = item.UserId }, new { @class = "btn btn-warning blockLink" })
string slash = " | ";
@slash
@Html.ActionLink("Удалить", "DeleteUser", new { id = item.UserId }, new { @class = "btn btn-danger delete" })
}
</div>
<div id="blockUser">
<form method="post" action="~/admin/user/BanUser">
<p class="text-danger">Блокировка пользователя</p>
<p>Укажите причину</p>
<input type="hidden" name="id" value="@item.UserId" />
<input type="text" name="reason" class="form-control" />
<input type="submit" value="Заблокировать" class="btn btn-success" style="margin-top:20px" />
</form>
</div>
<div id="myOverlay"></div>
</div>
}
</div>
}
@Html.PagedListPager((IPagedList)ViewBag.usersOnPage, page => Url.Action("Index", new { page }))
Так вот, скажите, пожалуйста, будет ли этот метод вести себя как асинхронный? Насколько я знаю, то метод возвращающий частичное представление нельзя сделать асинхронным, а костыли нарытые на просторах интернета у меня применить не получилось.
Резюмируя, нужно понимание:
- Будет ли мой код работать, как асинхронный?
- Если нет, то возможно у Вас есть идеи, как нужно его переписать, чтобы добиться асинхронной работы
Заранее спасибо
Ответы (1 шт):
Для того, чтоб частичное представление вызывалось из асинхронного метода нужно:
- Наполнить модель родительской страницы данными:
public async Task<ActionResult> Index(int? page)
{
List<UserVM> usersList = new List<UserVM>();
List<UsersDTO> usersDTO;
var pageNumber = page ?? 1;
using (ChekitDB chekitDB = new ChekitDB())
{
usersDTO = await chekitDB.Users.ToListAsync();
usersList = usersDTO.ToArray().Where(x => x.BanStatus == false).OrderBy(x => x.Login).Select(x => new UserVM(x)).ToList();
}
var usersOnPage = usersList.ToPagedList(pageNumber, 20);
ViewBag.usersOnPage = usersOnPage;
return View(usersOnPage);
}
В родительском представлении добавить рендер дочернего представления с именем cshtml дочернего представления и заполненной моделью:
<div id="list">
@{
Html.RenderPartial("_UsersQueryPartial", Model);
}
</div>
- Создать ajax.beginform. Сама форма, например, для поиска:
@{
AjaxOptions ajaxUserSearch = new AjaxOptions()
{
UpdateTargetId = "list",
Url = Url.Action("AsyncQuery", "User")
};
}
@using (Ajax.BeginForm(ajaxUserSearch))
{
<input type="text" name="filter" class="form-control form-search-input" placeholder="Search...">
<button class="btn btn-default form-control" type="submit">
<span class="fa fa-search" aria-hidden="true"></span>
</button>
}
Создать "прокладку" которая будет обрабатывать запрос из формы:
public async Task<ActionResult> AsyncQuery(string filter, int? page) { var model = await this.UsersQueryPartial(filter, page); return PartialView("_UsersQueryPartial", model); }И метод, который будет возвращать результат в прокладку:
public async Task<IPagedList<UserVM>> UsersQueryPartial(string filter, int? page) { List<UserVM> usersList = new List<UserVM>(); List<UsersDTO> usersDTO; var pageNumber = page ?? 1; using(ChekitDB chekitDB = new ChekitDB()) { usersDTO = await chekitDB.Users.ToListAsync(); usersList = usersDTO.ToArray().Where(x => x.BanStatus == false).OrderBy(x => x.Login).Select(x => new UserVM(x)).ToList(); if(filter != null) { usersList = usersList.Where(x => x.SearchInfo().ToLower().Contains(filter.ToLower())).ToList(); } } var usersOnPage = usersList.ToPagedList(pageNumber, 20); ViewBag.usersOnPage = usersOnPage; return usersOnPage; }
Надеюсь, что в будущем кому-то пригодится!