我有一个用VS.2017开发的ASP.NET Core 1.1 Web应用程序,我决定将一些视图功能放在一个视图组件中(以前做过其他的)。
此视图组件获取与用户ID关联的字典集合,并将其显示在一个漂亮的表中。当我把它作为页面的一部分(而不是VC)时,它可以工作。但是,当我将它用作视图组件时,组件的HTML永远不会被渲染。
我在视图组件中放置了一个断点并触发,我看到View(已授予)返回语句返回一个填充列表,直到按预期执行为止。
然后我在ViewComponent的default.cshtml代码部分的@ {some code here}顶部放置了一个断点,并且该断点也会触发,因此视图组件的Default.cshtml文件是找到。这个Default.cshtml有一些标记来呈现一个表,在表格中我有一个@foreach()语句,当做一个" Run to cursor"到那个精确的位置 - 迭代的循环 - 它也会触发,因此它会遍历集合。
但毕竟主视图看起来好像视图组件不在那里,即使找到并执行了Default.cshtml中的HTML也没有呈现。我在这里错过了什么?到目前为止,我的印象是VS.2017(及其所有更新)不是很稳定。
Default.cshtml
@using ACME.AspNetCore.Permissions.Infrastructure.Authorization
@model Dictionary<Permission, string>
@{
ViewBag.UserName = "xxx";
Model.Add(Permission.Permission1, "test");
}
<h1>Component Output</h1>
<div class="well well-lg">
<table class="table table-hover">
<thead>
<tr>
<th>Permission</th>
<th>Description</th>
<th class="text-center">Status</th>
<th class="text-center">Revoke it!</th>
</tr>
</thead>
<tbody>
@foreach (var dictentry in Model)
{
<tr>
<td>@dictentry.Key.ToString()</td>
<td>@dictentry.Value</td>
<td class="text-center"><span class="glyphicon glyphicon-ok" style="color:green;"></span></td>
<td class="text-center"><a asp-action="RevokePermission" asp-route-id="@ViewBag.UserName" asp-route-pid="@dictentry.Key.ToString()"><span class="glyphicon glyphicon-thumbs-down" style="color:red;"></span></a></td>
</tr>
}
</tbody>
<tfoot><p class="alert alert-success"><span class="glyphicon glyphicon-eye-open"></span> Granted permissions</p></tfoot>
</table>
</div>
GrantedPermissionsViewComponent.cs
[ViewComponent(Name = "GrantedPermissions")]
public class GrantedPermissionsViewComponent : ViewComponent {
private readonly ApplicationDbContext _context;
public GrantedPermissionsViewComponent(ApplicationDbContext context) : base()
{
_context = context;
}
public async Task<IViewComponentResult> InvokeAsync(string emailOrUserId)
{
string id;
Guid UID;
if (Guid.TryParse(emailOrUserId, out UID))
{ // THE PARAMETER WAS A GUID, THUS A USER ID FROM IDENTITY DATABASE
id = emailOrUserId;
}
else
{ // THE PARAMETER IS ASSUMED TO BE AN EMAIL/USERNAME FROM WHICH WE CAN DERIVE THE USER ID
id = _context.Users.Where(u => u.Email == emailOrUserId.Trim()).Select(s => s.Id).FirstOrDefault();
}
Dictionary<Permission, string> granted = GetOwnerPermissions(id);
return View(granted);
}
private Dictionary<Permission, string> GetOwnerPermissions(string userId)
{
Dictionary<Permission, string> granted;
granted = _context.UserPermissions.Where(u => u.ApplicationUserId == userId)
.Select(t => new { t.Permission })
.AsEnumerable() // to clients memory
.Select(o => new KeyValuePair<Permission, string>(o.Permission, o.Permission.Description()))
.ToList()
.ToDictionary(x => x.Key, x => x.Value);
return granted;
}
}
那么为什么它本身会触发组件的代码以及组件的视图(default.cshtml),但它不会呈现其中的HTML代码?
主视图中的组件调用:
@{await Component.InvokeAsync<GrantedPermissionsViewComponent>(
new { emailOrUserId = ViewBag.UserName });
}
请注意
答案 0 :(得分:12)
问题在于如何调用ViewComponent。
如果使用@{ ... }
,则意味着您要执行代码而不是渲染输出。
如果使用括号而不是括号,则结果将呈现为输出。 @( ... )
在您的情况下,您甚至不需要括号。 尝试调用它具有以下内容:
@await Component.InvokeAsync("GrantedPermissions", new { emailOrUserId = ViewBag.UserName })
更多信息here
答案 1 :(得分:1)
@if (User.Identity.IsAuthenticated)
{
<div>User: @User.Identity.Name</div>
@(await Component.InvokeAsync("DefaultNavbar"));
@RenderBody()
}
else
{
<div> show public pages</div>
@RenderBody()
}