例如,项目中的许多页面具有相似的部分,这需要从控制器中获取数据。
我们可以为其创建Partial View:
查看模型类:
public class DriverProfilerSidebarVM
{
public DriverProfilerSidebarVM()
{
Trucks = new List<SelectListItem>();
Trailers = new List<SelectListItem>();
}
public int Id { get; set; }
[Display(Name = "Truck")]
public int? TruckId { get; set; }
public List<SelectListItem> Trucks { get; set; }
....
_ProfilerSidebar.cshtml:
@model Web.ViewModels.DriverProfilerSidebarVM
<div class="profile-sidebar">
<div class="portlet light profile-sidebar-portlet ">
<div class="profile-userpic">
<img src=@(!string.IsNullOrWhiteSpace(Model.AvatarUrl) ? Model.AvatarUrl : "/Images/coloricons/Driver-100.png") class="img-responsive" alt="Avatar Photo">
</div>
<div class="profile-usertitle">
<div class="profile-usertitle-name"> @Model.FirstName @Model.LastName </div><br />
<div class="profile-usertitle-name">@Model.Nickname</div>
</div>
<div class="profile-usermenu">
<ul class="nav-item nav page-sidebar-menu" data-keep-expanded="false" data-auto-scroll="true" data-slide-speed="200">
<li id="liProfile" class="active">
<a class="" href="@Url.Action("Edit", "Drivers",new { Model.Id })">
<i class="icon-user"></i> Driver Profile
</a>
</li>
然后使用它,我们可以选择2种方式:
创建控制器方法并从页面调用它:
@ Html.Action(“ _ ProfilerSidebar”,“驱动程序”,新的{id = Model.Id}
和方法:
public ActionResult _ProfilerSidebar(int id, bool isEditTruckTrailer = false)
{
DriverProfilerSidebarVM model = ProfilerSidebar(id, isEditTruckTrailer);
return PartialView(model);
}
添加类型为DriverProfilerSidebarVM的属性以对每个页面建模,该页面将使用此部分并进行渲染:
@ Html.Partial(“ _ ProfilerSidebar”,Model.ProfilerSidebar)
两种方法都有效。两者都有哪些利弊?
答案 0 :(得分:0)
另一个选择是在_layout
中渲染局部。如果要呈现与用户相关的数据,则可以通过声明扩展来实现,如下例所示。我投票支持这种方法,因为所有代码都包含在一个地方,您不需要在视图模型中添加其他属性,也不需要记住要在视图中添加html辅助函数以呈现局部视图。它比前面多了一些代码,但更具可维护性。这是一个示例,可在导航栏中显示部分视图,其中包含用户登录时的用户名和角色,但是可以对其进行修改以执行或执行任何操作:
_layout.cshtml(调用_LoginPartial
,这是与您的示例/问题相关的部分):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@Styles.Render("~/content/layout")
<title>Title</title>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
@Html.ActionLink("Controller", "SomeAction", "My Link To Something")
</ul>
@Html.Partial("_LoginPartial")
</div>
</div>
</div>
<div>
@RenderBody()
</div>
@Scripts.Render("~/bundles/layout")
@RenderSection("scripts", required: false)
</body>
</html>
然后在_LoginPartial.cshtml
中输入
using Microsoft.AspNet.Identity
@using MyProject.Extensions
@using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm" }))
{
@Html.AntiForgeryToken()
var userName = User.Identity.GetUserName();
}
@if (Request.IsAuthenticated)
{
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">@Html.Raw("Hello " + User.GetFullNameAndRole() + "!") <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li>@Html.ActionLink("Manage Account", "Manage", "Account", new { userName = User.Identity.GetUserName() }, null)</li>
<li><a href="javascript:document.getElementById('logoutForm').submit()">Log Off</a></li>
</ul>
</li>
</ul>
}
else
{
<ul class="nav navbar-nav navbar-right">
<li>@Html.ActionLink("Log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" })</li>
</ul>
}
和User.GetFullNameAndRole()
之所以起作用,是因为以下原因:
ClaimsExtensions.cs
:
/// <summary>
/// Extension class to handle adding claims to a user
/// </summary>
public static class ClaimsExtensions
{
/// <summary>
/// Gets the full name and role of a user.
/// </summary>
/// <param name="user">The user.</param>
/// <returns></returns>
public static string GetFullNameAndRole(this IPrincipal user)
{
var fullNameAndRoleClaim = ((ClaimsIdentity)user.Identity).FindFirst("FullNameAndRole");
if (fullNameAndRoleClaim != null)
{
return fullNameAndRoleClaim.Value;
}
// If we don't find the claim for the user's full name and email for some reason, use the email address as a fall back
return user.Identity.Name;
}
}
在ApplicationUser.cs
中,我们向用户添加声明,如下所示:
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
// Ability to retrieve first/last name and role via the Identity class. This is so _LoginPartial.cshtml can display first name + last name
// and role instead of e-mail address. The other option is to create an instance of usermanager in razor in _LoginPartial.cshtml. Ew.
// We retrieve this custom user claim via the extension method 'GetUserNameAndRole' in ClaimsExtensions.cs
var userRole = manager.GetRoles(userIdentity.GetUserId()).FirstOrDefault();
var nameAndRole = string.Empty;
if (userRole != null)
{
if(!string.IsNullOrEmpty(this.FirstName) && !string.IsNullOrEmpty(this.LastName))
{
nameAndRole = string.Format("{0} {1} ({2})", this.FirstName, this.LastName, userRole);
}
else
{
nameAndRole = string.Format("{0} ({1})", this.Email, userRole);
}
}
else
{
if (!string.IsNullOrEmpty(this.FirstName) && !string.IsNullOrEmpty(this.LastName))
{
nameAndRole = string.Format("{0} {1}", this.FirstName, this.LastName);
}
else
{
nameAndRole = string.Format("{0}", this.Email);
}
}
userIdentity.AddClaim(new Claim("FullNameAndRole", nameAndRole));
return userIdentity;
}