ASP.NET Core Razor Pages 2.2 - Как реализовать общий ViewComponent
Я работаю над сайтом ASP.NET Core, используя Razor Pages вместо MVC.
Я столкнулся с ситуацией, когда мне нужно реализовать общий компонент, который можно использовать на разных страницах. Компонент - Простая ветка комментариев. На разных страницах подписанные пользователи могут присылать свои комментарии.
Компонент должен состоять из 2 частей:
- Список комментариев - это список комментариев, который может быть легко реализован с помощью ViewComponent или Partial Page;
- Добавить комментарий управления - это текстовые области и кнопка отправки, которые позволяют пользователю отправлять свой собственный комментарий.
Чего я хочу добиться, так это использовать ViewComponent или Partial page или другой метод, чтобы поместить некоторую разметку с начальными параметрами на любую страницу, чтобы включить эту функцию комментариев без копирования / вставки одного и того же кода со страницы на страницу.
И у меня есть несколько проблем с этим.
Как я уже упоминал, ViewComponent можно использовать для отображения списка комментариев на любой странице, просто добавив следующую разметку:
@await Component.InvokeAsync("Comments", new { type="NewsItem", id="@Model.Item.ID" })
Поэтому CommentsViewComponent будет вызывать ef.core DBContext для загрузки комментариев для определенного типа и идентификатора. Это работает отлично. Но проблема начинает возникать, когда мне нужно отправлять сообщения из разметки ViewComponent и обрабатывать эти сообщения.
Планируется провести 3 возможных почтовых звонка:
- Добавить новый комментарий
- Удалить существующий комментарий
- Изменить существующий комментарий
Первый возможный подход - определить 3 обработчика на странице NewsItem и вызвать их, используя tag-helper из ViewComponent. Но тогда мне нужно будет определить 3 одинаковых обработчика на любой другой странице, где мне понадобятся те же функции.
Другой подход, о котором я думал, - определить какой-то фальшивый PageModel, который будет содержать эти 3 обработчика, и ViewComponent будет публиковать на этой странице, используя Ajax. Единственная сложность здесь заключается в том, что после выполнения этих сообщений мне нужно заставить ViewComponent перерисовывать себя, так как комментарии были изменены (удалены, добавлены или отредактированы).
Таким образом, в результате компонент будет содержать следующие части:
- ViewComponent для отображения необходимой разметки
- JavaScript-код для отправки сообщений по кликам клиентов
- Поддельные PageModel для обработки сообщений.
Мне не очень нравится этот подход, и я думаю, что он слишком сложен для такой простой задачи. Это мой первый проект Razor Pages для ядра APS.NET, поэтому у меня нет большого опыта по реализации таких изолированных компонентов, и я надеюсь, что вы, ребята, поможете мне понять, как это можно реализовать, чтобы лучше следовать принципам SOLID и DRY.
Благодарю.
1 ответ
Вы можете иметь два ViewComponents: один CommentsViewComponent
который показывает список предыдущих комментариев, и вы можете редактировать / удалять комментарии. PostCommentViewComponent
который вы могли бы добавить новый комментарий. Например:
@await Component.InvokeAsync("Comments")
@await Component.InvokeAsync("PostComment")
Прежде всего, вы можете добавить создание / редактирование / удаление бритвенных страниц в папке Pages / Comments с соответствующим обработчиком.
Затем в PostCommentViewComponent вы можете использовать отправку формы в обработчик OnPostCreateAsync и перенаправить обратно.
public async Task<IViewComponentResult> InvokeAsync()
{
var comment = new Comment();
return View(comment);
}
//Default.cshtml
@model Razor.Models.Comment
<div class="row">
<div class="col-md-4">
<form asp-page="./Comments/Create" asp-page-handler="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Content" class="control-label"></label>
<input asp-for="Content" class="form-control" />
<span asp-validation-for="Content" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
</div>
//handler
public async Task<IActionResult> OnPostCreateAsync()
{
//create code
await _context.SaveChangesAsync();
return Redirect(Request.Headers["Referer"].ToString());
}
В CommentsViewComponent покажите все комментарии и дайте пользователю возможность перенаправлять на бритвенные страницы, чтобы редактировать / удалять и перенаправлять обратно.
@model IEnumerable<Razor.Models.Comment>
<h4> Comment List</h4>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Content)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Content)
</td>
<td>
<a asp-page="./Comments/Edit" asp-route-id="@item.CommentId">Edit</a> |
<a asp-page="./Comments/Delete" asp-route-
id="@item.CommentId">Delete</a>
</td>
</tr>
}
</tbody>