Помогите, пожалуйста, разобраться с проблемой вызова Partial View.
Имеем модель:
public class File
{
public int Id { get; set; }
public string Name { get; set; }
public string Path { get; set; }
public int? PhoneId { get; set; }
}
Контроллер для отображения Partial View:
[HttpGet]
public ActionResult GetAdditionalPhotos(int phoneId)
{
using (db)
{
var model = db.Files.Where(f => f.PhoneId == phoneId).ToList();
return PartialView("_GetAdditionalPhotos", model);
}
}
Так выглядит PartialView (_GetAdditionalPhotos.cshtml):
@model IEnumerable<Models.File>
<table id="table" data-toggle="table" data-search="false" data-virtual-scroll="true">
<thead>
<tr>
<th data-width="100">Фото</th>
<th data-width="120"></th>
</tr>
</thead>
<tbody>
@foreach (var photo in Model)
{
<tr>
<td><img src="@Url.Content(@photo.Path)" width="80" height="80" /></td>
</tr>
}
</tbody>
</table>
В основном View пробую вызвать Partial View:
<div class="col col-sm-12" id="additionalPhotos">
@if (Model.Files != null)
{
@await Html.PartialAsync("_GetAdditionalPhonePhotos", Model.Id)
}
else
{
<p>Нет дополнительных фотографий</p>
}
</div>
Но получаю ошибку:
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'System.Int32', but this ViewDataDictionary instance requires a model item of type 'System.Collections.Generic.IEnumerable`1[Models.File]'.
С указанной проблемой разобрался - необходимо передавать в PartialView модель.
Но теперь появился дополнительный вопрос - в основном View я обрабатываю событие нажатия на кнопку и выполняю js-скрипт для обновления Partial View. Но как мне теперь передавать модель?
Вот код обработки скриптом события:
<script type="text/javascript">
var url = '@Url.Action("GetAdditionalPhotos", "Home", new { Model })';
$("#btnReloadAdditionalPhotos").click(function () {
$('#additionalPhotos').load(url);
});
</script>
Но модель не принимается :(
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'System.Int32', but this ViewDataDictionary instance requires a model item of type 'System.Collections.Generic.IEnumerable`1[Models.File]'.
Эта ошибка выводится из-за того, что при вызове метода Html.PartialAsync происходит "рендер" только razor страницы (в вашем случае _GetAdditionalPhotos.cshtml), а действие public ActionResult GetAdditionalPhotos(int phoneId) никогда не выполняется. Поэтому и получается, что вы передаете int id, сразу в вашу вьюху, которая ожидает список File.
Раньше в ASP.NET MVC для этих целей существовал метод Action/RenderAction, и в отличии от Html.PartialAsync, он делал вызов вашего экшена, который принимает id и выполняет нужный код. Сейчас этого нет, но добавили View Component.
Например:
Views/Shared/Components/PhotoViewComponent.cs:
public class PhotoViewComponent : ViewComponent
{
public PhotoViewComponent(DbContext db) { /* ... */ }
public async Task<IViewComponentResult> InvokeAsync()
{
using (db)
{
var model = db.Files.Where(f => f.PhoneId == phoneId).ToList();
return View(model);
}
}
}
Вашу _GetAdditionalPhotos.cshtml нужно поместить и переименовать в Views/Shared/Components/Photo/Default.cshtml (это не обязательно делать, но тогда в компоненте нужно будет явно передавать название вьюхи).
И рендерить теперь это можно так: @await Component.InvokeAsync("Photo").
А если добавить Tag Helper в _ViewImports.cshtml: @addTagHelper *, <название вашей сборки>, то рендерить его можно будет при помощи тега: <vc:photo></vc:photo>.
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости