Я пытаюсь научиться правильно использовать ViewComponent в ASP. NET Core Mvc, поэтому у меня есть следующий пример: Идея состоит в том, чтобы визуализировать представление с деталями Mov ie и внутри это, ReviewViewComponent, содержащий 10-звездочный виджет оценки mov ie.
Внутри ViewComponent View фактически есть форма с переключателями. Имя действия формы передается ViewComponent (либо «Создать», либо «Редактировать», в зависимости от того, дал ли пользователь оценку). В зависимости от полученного имени действия, форма внутри ViewComponent будет вызывать метод Create или Edit внутри ReviewsController.
Это все работает, пока я не достигну обратного вызова внутри ReviewsController. Я хотел бы иметь возможность вернуть ViewComponent там и просто отобразить возвращаемый результат внутри div с id = "now-показывая-details-rating-div" в Details, используя ajax. Это работает с PartialViews (код закомментирован в методе редактирования ReviewsController), но кажется, что он не работает с ViewComponents (он просто отображает ViewComponent View как совершенно новый View, хотя я вызываю ajax в той же форме как если бы это было в PartialView).
Действительно ли я здесь неправильно использую концепцию ViewComponent? В смысле визуализации части представления после отправки формы, лучше ли на самом деле просто использовать PartialViews?
Ajax фрагмент
$.ajax({
type: "POST",
url: requestUrl,
data: form.serialize(),
success: function (data) {
$("#" + divZaRezultat).html(data);
}
});
ViewModels:
public class MovieDetailsVM
{
public string Title { get; set; }
public int Id { get; set; }
public int Year { get; set; }
public string Actors { get; set; }
public string Country { get; set; }
public string Directors { get; set; }
public int Duration { get; set; }
public string VideoLink { get; set; }
public string AverageRating { get; set; }
public string NumberOfReviews { get; set; }
public ReviewIndexVM CurrentUserReview { get; set; }
}
public class ReviewIndexVM
{
public int ReviewId { get; set; }
public int Rating { get; set; }
public MasterModel User { get; set; }
public MasterModel Movie { get; set; }
}
ViewComponent
public class ReviewViewComponent : ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync(string methodName, ReviewIndexVM review)
{
ViewBag.Method = methodName;
return View(review);
}
}
ViewComponent Представление по умолчанию
@model Cinema.DTO.ViewModels.Reviews.ReviewIndexVM
@{
ViewData["Title"] = "Default";
}
<form asp-controller="Reviews" asp-action="@ViewBag.Method">
<input asp-for="ReviewId" hidden />
<input asp-for="Movie.Id" hidden />
<input asp-for="User.Id" hidden />
<div class="rating form-group">
@for (int i = 10; i > 0; i--)
{
<input asp-for="Rating" type="radio" value="@i" id="@($"rating-star-{i}")" onclick="this.form.submit();" class="form-control rating-star"><label class="rating-star-label" for="@($"rating-star-{i}")"></label>
}
</div>
</form>
Просмотров:
@model Cinema.DTO.ViewModels.Movies.MovieDetailsVM
@using Microsoft.AspNetCore.Identity
@using Cinema.Domain.Entities.Identity
@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager
@{
ViewData["Title"] = "Details";
Layout = "~/Views/Shared/_Layout.cshtml";
bool first = true;
DateTime currentDate = DateTime.Now;
}
<section>
<div class="container">
<div class="content-wrap">
<div class="row">
<h1 class="h2">@Html.DisplayFor(model => model.Title)</h1>
</div>
<div class="row">
<div class="col-md-4">
<img id="movie-poster" class="pull-left" src="~/img/movie-poster.png" />
</div>
<div class="col-md-8">
<ul class="list-unstyled movie-info">
<li>
<span>@Html.DisplayNameFor(model => model.Title)</span>
@Html.DisplayFor(model => model.Title)
</li>
<li>
<span>@Html.DisplayNameFor(model => model.Year)</span>
@Html.DisplayFor(model => model.Year)
</li>
<li>
<span>@Html.DisplayNameFor(model => model.Actors)</span>
@Html.DisplayFor(model => model.Actors)
</li>
<li>
<span>@Html.DisplayNameFor(model => model.Country)</span>
@Html.DisplayFor(model => model.Country)
</li>
<li>
<span>@Html.DisplayNameFor(model => model.Directors)</span>
@Html.DisplayFor(model => model.Directors)
</li>
<li>
<span>@Html.DisplayNameFor(model => model.Duration)</span>
@Html.DisplayFor(model => model.Duration)
</li>
@*<li>
<span>@Html.DisplayNameFor(model => model.GenreMovies)</span>
@Html.DisplayFor(model => model.GenreMovies)
</li>*@
<li>
<span>@Html.DisplayNameFor(model => model.VideoLink)</span>
@Html.DisplayFor(model => model.VideoLink)
</li>
</ul>
Average rating <span class="badge">@Model.AverageRating</span>
<hr />
<div asp-authorize asp-roles="@Roles.User">
Your rating:
<div id="now-showing-details-rating-div">
@if (@Model.CurrentUserReview.ReviewId == 0)
{
@await Component.InvokeAsync("Review", new { methodName = "Create", review = @Model.CurrentUserReview })
}
else
{
@await Component.InvokeAsync("Review", new { methodName = "Edit", review = @Model.CurrentUserReview })
}
</div>
</div>
</div>
</div>
</div>
</section>
@section Scripts {
$(document).ready(function () {
$('.rating-star-label').mouseover(function () {
$('.rating-star').prop('checked', false);
});
});
</script>
}
ОтзывыКонтроллер
[HttpGet]
[Authorize(Roles = Roles.User)]
public async Task<IActionResult> Edit(int reviewId)
{
Review review = await _unit.Reviews.GetAsync(reviewId);
var authorizationResult = await _authorizationService.AuthorizeAsync(User, review, OperationRequirements.Update);
if (authorizationResult.Succeeded)
{
ReviewUpdateVM model = review.ToUpdateVM();
return PartialView(model);
}
else if (User.Identity.IsAuthenticated)
{
return new ForbidResult();
}
else
{
return new ChallengeResult();
}
}
[Authorize(Roles = Roles.User)]
public async Task<IActionResult> Edit(ReviewIndexVM model)
{
Review review = model.Create();
var authorizationResult = await _authorizationService.AuthorizeAsync(User, review, OperationRequirements.Update);
if (authorizationResult.Succeeded)
{
await _unit.Reviews.UpdateAsync(review, model.ReviewId);
await _unit.SaveAsync();
return ViewComponent("Review");
//return Redirect("/Reviews/Details?reviewId=" + review.Id);
}
else if (User.Identity.IsAuthenticated)
{
return new ForbidResult();
}
else
{
return new ChallengeResult();
}
}
}
else if (User.Identity.IsAuthenticated)
{
return new ForbidResult();
}
else
{
return new ChallengeResult();
}
}