这是一个正在运行的演示:
Details.cshtml:
我正在尝试学习在ASP.NET Core Mvc中正确使用ViewComponent的方法,因此,我有以下示例:这个想法是渲染带有Movie细节的视图,并且在其中包含“ ReviewViewComponent”的10-明星电影评分小部件。
在ViewComponent的View内部实际上是带有单选按钮的表单。表单操作名称将传递到ViewComponent(“创建”或“编辑”,具体取决于用户是否已给出评分)。根据收到的操作名称,ViewComponent中的表单将在ReviewsController中调用Create或Edit方法。
这一切都有效,直到我在ReviewsController中到达返回调用为止。我希望能够在那里返回ViewComponent并使用ajax在Details中的id =“ now-showing-details-rating-div”内简单地将返回结果呈现在div中。这适用于PartialViews(在ReviewsController编辑方法中注释掉的代码),但似乎不适用于ViewComponents(即使我以相同的方式在窗体上调用ajax,它也只是将ViewComponent View呈现为全新的View)。如果它位于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> }
ReviewsController
] >>[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(); } }
[我正在尝试学习在ASP.NET Core Mvc中正确使用ViewComponent,因此,我有以下示例:这个想法是渲染带有Movie细节的视图,并在其中包含“ ReviewViewComponent” ...] >
这是一个正在运行的演示:
Details.cshtml:
@model MovieDetailsVM @{ 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-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> Your rating: <div id="now-showing-details-rating-div"> @if (@Model.CurrentUserReview == null) { @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> </div> </section>
Details.cshtml中的Ajax:
@section Scripts { <script> $(document).ready(function () { $('.rating-star-label').mouseover(function () { $('.rating-star').prop('checked', false); }); }); function Update() { $.ajax({ type: "POST", url: "/Reviews/Edit/@Model.CurrentUserReview.ReviewId", data: $("form").serialize(), success: function (data) { $("#now-showing-details-rating-div").html(data); } }); } </script> }
Components / Review / Default.cshtml:
@model 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="Update();" class="form-control rating-star"><label class="rating-star-label" for="@($"rating-star-{i}")"></label> } </div> </form>
Controller:
public class ReviewsController : Controller { private readonly Component2_2Context _context; public ReviewsController(Component2_2Context context) { _context = context; } // GET: Reviews/Details/5 public async Task<IActionResult> Details(int? id) { var reviewIndexVM = await _context.MovieDetailsVM .Include(m => m.CurrentUserReview) .FirstOrDefaultAsync(m => m.Id == id); return View(reviewIndexVM); } // GET: Reviews/Edit/5 public async Task<IActionResult> Edit(int? id) { if (id == null) { return NotFound(); } var reviewIndexVM = await _context.ReviewIndexVM.FindAsync(id); if (reviewIndexVM == null) { return NotFound(); } return View(reviewIndexVM); } // POST: Reviews/Edit/5 [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Edit(int id, [Bind("ReviewId,Rating")] ReviewIndexVM reviewIndexVM) { if (id != reviewIndexVM.ReviewId) { return NotFound(); } if (ModelState.IsValid) { _context.Update(reviewIndexVM); await _context.SaveChangesAsync(); return ViewComponent("Review"); } return new ChallengeResult(); }
ViewComponent:
public class ReviewViewComponent : ViewComponent { public async Task<IViewComponentResult> InvokeAsync(string methodName, ReviewIndexVM review) { ViewBag.Method = methodName; return View(review); } }
结果:
这是一个正在运行的演示:
Details.cshtml: