ASP.NET MVC页面的常见部分,如何做得更好

时间:2018-07-17 14:21:44

标签: asp.net-mvc partial-views asp.net-mvc-partialview

例如,项目中的许多页面具有相似的部分,这需要从控制器中获取数据。

我们可以为其创建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种方式:

  1. 创建控制器方法并从页面调用它:

    @ Html.Action(“ _ ProfilerSidebar”,“驱动程序”,新的{id = Model.Id}

和方法:

    public ActionResult _ProfilerSidebar(int id, bool isEditTruckTrailer = false)
    {
        DriverProfilerSidebarVM model = ProfilerSidebar(id, isEditTruckTrailer);
        return PartialView(model);
    }
  1. 添加类型为DriverProfilerSidebarVM的属性以对每个页面建模,该页面将使用此部分并进行渲染:

    @ Html.Partial(“ _ ProfilerSidebar”,Model.ProfilerSidebar)

两种方法都有效。两者都有哪些利弊?

1 个答案:

答案 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;
    }