ASP .NET Core MVC: как правильно использовать Partial View?

107
05 февраля 2022, 21:40

Помогите, пожалуйста, разобраться с проблемой вызова 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>

Но модель не принимается :(

Answer 1

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>.

READ ALSO
Ввод данных в поле EO.WebBrowser C#

Ввод данных в поле EO.WebBrowser C#

Всех приветствуюМне нужно вводить определенные данные в текстовые поля сайта после загрузки страницы

73
C# вызвать переменную из другого метода

C# вызвать переменную из другого метода

подскажите пожалуйста, мне нужно вызвать public class CallSKP из другого метода, чтоб использовать там значение переменной "text"как это сделать?

89
Искажение данных в JS функции (razorpage, asp.net core 3.0)

Искажение данных в JS функции (razorpage, asp.net core 3.0)

Существует метод контроллера:

104