Forms 将ViewComponent与表单一起使用
我正在尝试学习如何在ASP.NET Core Mvc中正确使用ViewComponent,因此我有以下示例:想法是使用电影详细信息渲染视图,其中包含“ReviewViewComponent”,其中包含一个10星电影评级小部件 在ViewComponent的视图中,实际上是一个带有单选按钮的窗体。表单操作名称将传递给ViewComponent(根据用户是否已给出评级,“创建”或“编辑”)。根据收到的操作名称,ViewComponent中的表单将调用ReviewController中的Create或Edit方法 在我到达ReviewController内部的返回调用之前,所有这些都有效。我希望能够在那里返回ViewComponent,并使用ajax在div中以id=“now showing details rating div”详细呈现返回结果。这适用于PartialView(代码在ReviewController编辑方法中注释掉),但似乎不适用于ViewComponents(它只是将ViewComponent视图呈现为一个全新的视图,尽管我在表单上调用ajax的方式与在PartialView中调用ajax的方式相同) 我是否真的误用了ViewComponent的概念?在表单提交后呈现视图的一部分的意义上,仅仅使用PartialViews实际上更好吗 Ajax片段 视图模型: 视图组件Forms 将ViewComponent与表单一起使用,forms,asp.net-core,view,razor-pages,view-components,Forms,Asp.net Core,View,Razor Pages,View Components,我正在尝试学习如何在ASP.NET Core Mvc中正确使用ViewComponent,因此我有以下示例:想法是使用电影详细信息渲染视图,其中包含“ReviewViewComponent”,其中包含一个10星电影评级小部件 在ViewComponent的视图中,实际上是一个带有单选按钮的窗体。表单操作名称将传递给ViewComponent(根据用户是否已给出评级,“创建”或“编辑”)。根据收到的操作名称,ViewComponent中的表单将调用ReviewController中的Create或
公共类ReviewViewComponent:ViewComponent
{
公共异步任务InvokeAsync(string方法名,ReviewIndexVM review)
{
方法=方法名;
返回视图(审查);
}
}
视图组件默认视图
@model Cinema.DTO.ViewModels.Reviews.ReviewIndexVM
@{
ViewData[“标题”]=“默认值”;
}
@对于(int i=10;i>0;i--)
{
}
视图:
@model Cinema.DTO.ViewModels.Movies.MovieDetailsVM
@使用Microsoft.AspNetCore.Identity
@使用Cinema.Domain.Entities.Identity
@注入SignInManager SignInManager
@注入用户管理器用户管理器
@{
ViewData[“标题”]=“详细信息”;
Layout=“~/Views/Shared/_Layout.cshtml”;
bool first=true;
DateTime currentDate=DateTime.Now;
}
@DisplayFor(model=>model.Title)
-
@DisplayNameFor(model=>model.Title)
@DisplayFor(model=>model.Title)
-
@Html.DisplayNameFor(model=>model.Year)
@DisplayFor(model=>model.Year)
-
@DisplayNameFor(model=>model.Actors)
@DisplayFor(model=>model.Actors)
-
@Html.DisplayNameFor(model=>model.Country)
@DisplayFor(model=>model.Country)
-
@DisplayNameFor(model=>model.Directors)
@DisplayFor(model=>model.Directors)
-
@DisplayNameFor(model=>model.Duration)
@DisplayFor(model=>model.Duration)
@*-
@DisplayNameFor(model=>model.GenreMovies)
@DisplayFor(model=>model.GenreMovies)
*@
-
@DisplayNameFor(model=>model.VideoLink)
@DisplayFor(model=>model.VideoLink)
平均评级@Model.AverageRating
您的评级:
@如果(@Model.CurrentUserReview.ReviewId==0)
{
@wait Component.InvokeAsync(“Review”,new{methodName=“Create”,Review=@Model.CurrentUserReview})
}
其他的
{
@wait Component.InvokeAsync(“Review”,new{methodName=“Edit”,Review=@Model.CurrentUserReview})
}
@节脚本{
$(文档).ready(函数(){
$('.rating star label')。鼠标悬停(函数(){
$('.rating star').prop('checked',false);
});
});
}
查看控制器
[HttpGet]
[授权(角色=角色.用户)]
公共异步任务编辑(int-reviewId)
{
Review Review=wait_unit.Reviews.GetAsync(reviewId);
var authorizationResult=Wait_authorizationService.AuthorizationAsync(用户、审核、操作要求.Update);
if(authorizationResult.successed)
{
ReviewUpdateVM model=review.ToUpdateVM();
返回局部视图(模型);
}
else if(User.Identity.IsAuthenticated)
{
返回新结果();
}
其他的
{
返回新的ChallengeResult();
}
}
[授权(角色=角色.用户)]
$.ajax({
type: "POST",
url: requestUrl,
data: form.serialize(),
success: function (data) {
$("#" + divZaRezultat).html(data);
}
});
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; }
}
public class ReviewViewComponent : ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync(string methodName, ReviewIndexVM review)
{
ViewBag.Method = methodName;
return View(review);
}
}
@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();
}
}
@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>
@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>
}
@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>
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();
}
public class ReviewViewComponent : ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync(string methodName, ReviewIndexVM review)
{
ViewBag.Method = methodName;
return View(review);
}
}