一步一步建立ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](九)

前言

童鞋們,你們好css

我是專一.NET開發者社區建設的實踐者Rector。html

首先,爲本身間隔了兩個星期五再更新本系列文章找個不充分的理由:Rector最近工做,家庭的各類事務所致,但願你們諒解。前端

本文知識要點

回到本文的主題,仍是關於系列文章:《一步一步建立ASP.NET MVC5程序Repository+Autofac+Automapper+SqlSugar》,本文將爲你們分享的主要內容有:mysql

  • 響應式網站首頁的佈局與製做
  • 文章列表的展現
  • 文章詳情頁面

前端佈局與製做

響應式網站首頁的佈局與製做jquery

在以本文以前的系列文章的頁面中,咱們的網站首頁以及文章列表頁面都沒有應用樣式,本文將給你們分享首頁的製做,其中包含的內容有:git

  • 頭部導航
  • 文章列表
  • Bootstrap響應式佈局

最終的首頁效果圖以下:github

create-aspnet-mvc-5-web-application-repository-autofac-automapper-sqlsugar-step-by-step-09-01.png

CSS樣式

首先,在項目[TsBlog.Frontend]中建立資源文件夾命名爲:resources,在其中建立一個css樣式文件夾,並新建一個樣式文件,命名爲:site.css,此時的目錄結構以下:web

create-aspnet-mvc-5-web-application-repository-autofac-automapper-sqlsugar-step-by-step-09-02.png

樣式代碼以下:sql

site.css數據庫

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td { border: 0; margin: 0; padding: 0; }

body { color: #333; font-size: 14px; font-family: -apple-system,'helvetica neue', helvetica,"Helvetica Neue",Helvetica,Arial,"PingFang SC","Hiragino Sans GB","WenQuanYi Micro Hei","Microsoft Yahei",sans-serif; line-height: 22px; width: 100%; height: 100%; }
h1, h2, h3, h4, h5, h6 { clear: both; font-weight: normal; }
ol, ul { list-style: none; }
blockquote { quotes: none; border-left: 5px solid #eee; font-size: 14px; margin: 10px 0; padding: 10px 20px; }
    blockquote:before, blockquote:after { content: ''; content: none; }

a { color: #4484ce; }

/*bootstrap override*/
.btn { border-radius: 2px !important; }
.btn-primary { background-color: #4484CE !important; }
    .btn-primary:hover { background-color: #3A77BE !important; }

.navbar-nav a { color: #333 !important; }
    .navbar-nav > .active > a, .navbar-nav > .active > a:focus, .navbar-nav > .active > a:hover, .navbar-nav a:hover { border-radius: 2px; background-color: #e7e7e7 !important; }
/*site begin*/
.ts-navbar .navbar-nav { height: 50px; vertical-align: middle; line-height: 50px; }
    .ts-navbar .navbar-nav li { vertical-align: middle; line-height: 50px; float: none; display: inline-block; }
.ts-navbar .dropdown li { display: block; }
.ts-navbar .navbar-nav li a { padding: 8px 15px; }
.navbar-brand { height: auto; }
a.nav-btn-login { color: #fff !important; }
    a.nav-btn-login:hover { background-color: #3A77BE !important; color: #fff !important; }
.navbar-profile { margin-right: 0; }
/*home begin*/
.jumbotron h1 { margin-bottom: 15px; }
.jumbotron p { line-height: 28px; }
.post-title { display: block; font-size: 16px; font-weight: 600; border-bottom: 2px solid #e7e7e7; padding-bottom: 8px; }
.post-item-box { margin-bottom: 15px; }
    .post-item-box li { margin-top: 15px; margin-bottom: 15px; padding-top: 10px; padding-bottom: 10px; }
        .post-item-box li h2 { font-size: 16px; font-weight: 500; margin-bottom: 10px; }
.post-item-summary { color: #555; }
.footer-box { padding: 15px; margin-top: 15px; border-top: 1px solid #e7e7e7; }


/*post details*/

.article-content { padding-top: 15px; padding-bottom: 15px; }
    .article-content p { margin-top: 20px; margin-bottom: 20px; }
.article-fixed p { margin-top: 0; margin-bottom: 5px; }
.article-content h1, .article-content h2, .article-content h3, .article-content h4, .article-content h5, .article-content h6 { margin: 15px 0 10px; }
.article-content h1, .article-content h2 { border-bottom: 1px solid #eee; padding-bottom: 10px; }
.article-content h2 { font-size: 1.75em; line-height: 1.2 }
.article-content h3 { font-size: 1.5em; line-height: 1.2 }
.article-content blockquote { background: #f6f6f6 none repeat scroll 0 0; border-left: 2px solid #009a61; color: #555; font-size: 1em; }
.cloud-tags .cloud-tag-item { border: 1px solid #efefef; background-color: #f7f7f7; padding: 5px 10px; }
.cloud-tags .cloud-tag-item, .side-bar-article-list, .article-content { word-break: break-all; word-wrap: break-word; white-space: normal; }
    .article-content pre { background-attachment: scroll; background-clip: border-box; background-color: #f6f6f6; border: medium none; line-height: 1.45; max-height: 35em; overflow: auto; padding: 1em; position: relative; margin-bottom: 15px; margin-top: 15px; }
    .article-content ul li { padding-left: 15px; list-style: inside; }
    .article-content ul li { padding-left: 15px; list-style: inside; }
    .article-content ul, .article-content ol { margin-left: 3em; padding-left: 0; }
        .article-content ul li, .article-content ol li { margin: .3em 0; }

以上的樣式表是本文中所用到的,你只須要複製便可。

頭部導航

打開視圖文件[...TsBlogsrcPresentationTsBlog.FrontendViewsHomeIndex.cshtml],首先製做頭部導航條,其中導航條的HTML代碼以下:

<nav class="navbar navbar-default navbar-static-top ts-navbar">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="~/">TSBLOG</a>
            </div>
            <div id="navbar" class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li class="active"><a href="~/">網站首頁</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">分類導航 <span class="caret"></span></a>
                        <ul class="dropdown-menu">
                            <li class="dropdown-header">後端開發</li>
                            <li><a href="http://2sharings.com/category/csharp-development">C#程序設計</a></li>
                            <li><a href="http://2sharings.com/category/dot-net">.NET程序設計</a></li>
                            <li><a href="http://2sharings.com/category/asp-dot-net">ASP.NET</a></li>
                            <li><a href="http://2sharings.com/category/asp-net-mvc">ASP.NET MVC</a></li>
                            <li><a href="http://2sharings.com/category/asp-dotnet-core">ASP.NET Core</a></li>
                            <li><a href="http://2sharings.com/category/winform">Winform</a></li>
                            <li role="separator" class="divider"></li>
                            <li class="dropdown-header">數據庫</li>
                            <li><a href="http://2sharings.com/category/mysql">MySQL</a></li>
                            <li><a href="http://2sharings.com/category/sql-server">SQL Server</a></li>
                            <li><a href="http://2sharings.com/category/sqlite">SqLite</a></li>
                        </ul>
                    </li>
                    <li><a href="~/home/about">關於咱們</a></li>
                    <li><a href="~/home/contact">聯繫咱們</a></li>
                </ul>
                <ul class="nav navbar-nav navbar-right navbar-profile">
                    <li><a href="~/account/register">免費註冊</a></li>
                    <li><a class="btn btn-primary nav-btn-login" href="~/account/login">當即登陸</a></li>
                </ul>
            </div><!--/.nav-collapse -->
        </div>
    </nav>

正文HTML

其中正文的第一部分爲一個BANNER,在這個區域中,能夠放置一些重要的關於站點的描述信息,也能夠放滾動播放的廣告圖片等,按本身的須要處理就能夠了。

第二部分則是一個文章列表區域,其中列出了網站最近發佈的20條文章列表,正文的HTML代碼以下:

<div class="container">
        <div class="jumbotron">
            <h1>小夥伴,你好</h1>
            <p>歡迎來到 Rector 的ASP.NET MVC 5 系列文章教程。在這裏,Rector將和你一塊兒一步一步建立一個集成Repository+Autofac+Automapper+SqlSugar的WEB應用程序。</p>
            <p>你準備好了嗎?</p>
            <p>......</p>
            <p>讓咱們開始ASP.NET MVC 5 應用程序的探索之旅吧!!!</p>
        </div>
        <strong class="post-title">文章列表(@(Model.Count())篇)</strong>
        <ul class="list-unstyled post-item-box">
            @foreach (var p in Model)
            {
                <li>
                    <h2><a href="~/post/details/@p.Id">@p.Title</a></h2>
                    <p class="post-item-summary">@p.Summary ... <a href="~/post/details/@p.Id">閱讀全文</a></p>
                </li>
            }
        </ul>
    </div>

頁腳

頁面最後爲頁腳部分,包含比較簡單的版權等信息,HTML代碼以下:

<footer class="footer-box">
        <div class="container">
            版權全部 &copy; @(DateTime.Now.Year)
        </div>
    </footer>

首頁完整的HTML代碼以下:

Index.cshtml

@model IEnumerable<TsBlog.ViewModel.Post.PostViewModel>
@{
    Layout = null;
}
<!doctype html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>ASP.NET MVC 5 系列文章教程--首頁 | TSBLOG</title>
    <link href="~/Content/bootstrap.min.css" rel="stylesheet" />
    <link href="~/resources/css/site.css" rel="stylesheet" />

</head>
<body>
    <nav class="navbar navbar-default navbar-static-top ts-navbar">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="~/">TSBLOG</a>
            </div>
            <div id="navbar" class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li class="active"><a href="~/">網站首頁</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">分類導航 <span class="caret"></span></a>
                        <ul class="dropdown-menu">
                            <li class="dropdown-header">後端開發</li>
                            <li><a href="http://2sharings.com/category/csharp-development">C#程序設計</a></li>
                            <li><a href="http://2sharings.com/category/dot-net">.NET程序設計</a></li>
                            <li><a href="http://2sharings.com/category/asp-dot-net">ASP.NET</a></li>
                            <li><a href="http://2sharings.com/category/asp-net-mvc">ASP.NET MVC</a></li>
                            <li><a href="http://2sharings.com/category/asp-dotnet-core">ASP.NET Core</a></li>
                            <li><a href="http://2sharings.com/category/winform">Winform</a></li>
                            <li role="separator" class="divider"></li>
                            <li class="dropdown-header">數據庫</li>
                            <li><a href="http://2sharings.com/category/mysql">MySQL</a></li>
                            <li><a href="http://2sharings.com/category/sql-server">SQL Server</a></li>
                            <li><a href="http://2sharings.com/category/sqlite">SqLite</a></li>
                        </ul>
                    </li>
                    <li><a href="~/home/about">關於咱們</a></li>
                    <li><a href="~/home/contact">聯繫咱們</a></li>
                </ul>
                <ul class="nav navbar-nav navbar-right navbar-profile">
                    <li><a href="~/account/register">免費註冊</a></li>
                    <li><a class="btn btn-primary nav-btn-login" href="~/account/login">當即登陸</a></li>
                </ul>
            </div><!--/.nav-collapse -->
        </div>
    </nav>
    <div class="container">
        <div class="jumbotron">
            <h1>小夥伴,你好</h1>
            <p>歡迎來到 Rector 的ASP.NET MVC 5 系列文章教程。在這裏,Rector將和你一塊兒一步一步建立一個集成Repository+Autofac+Automapper+SqlSugar的WEB應用程序。</p>
            <p>你準備好了嗎?</p>
            <p>......</p>
            <p>讓咱們開始ASP.NET MVC 5 應用程序的探索之旅吧!!!</p>
        </div>
        <strong class="post-title">文章列表(@(Model.Count())篇)</strong>
        <ul class="list-unstyled post-item-box">
            @foreach (var p in Model)
            {
                <li>
                    <h2><a href="~/post/details/@p.Id">@p.Title</a></h2>
                    <p class="post-item-summary">@p.Summary ... <a href="~/post/details/@p.Id">閱讀全文</a></p>
                </li>
            }
        </ul>
    </div>
    <footer class="footer-box">
        <div class="container">
            版權全部 &copy; @(DateTime.Now.Year)
        </div>
    </footer>
    <script src="~/Scripts/jquery-3.2.1.min.js"></script>
    <script src="~/Scripts/bootstrap.min.js"></script>
</body>
</html>

後端接口與實現

在完成了前端頁面的佈局與製做以後,咱們須要後端程序提供接口和服務,來供前端頁面調用,如首頁視圖中的視圖模型:

@model IEnumerable<TsBlog.ViewModel.Post.PostViewModel>

文章倉儲接口和實現

打開文件[IPostRepository.cs],在其中新增接口方法: FindHomePagePosts ,代碼以下:

using System.Collections.Generic;
using TsBlog.Domain.Entities;

namespace TsBlog.Repositories
{
    public interface IPostRepository : IRepository<Post>
    {
        /// <summary>
        /// 查詢首頁文章列表
        /// </summary>
        /// <param name="limit">要查詢的記錄數</param>
        /// <returns></returns>
        IEnumerable<Post> FindHomePagePosts(int limit = 20);
    }
}

打開文件[PostRepository.cs],實現對應的接口方法:FindHomePagePosts,代碼以下:

using SqlSugar;
using System.Collections.Generic;
using TsBlog.Domain.Entities;

namespace TsBlog.Repositories
{
    /// <summary>
    /// POST表的數據庫操做類
    /// </summary>
    public class PostRepository : GenericRepository<Post>, IPostRepository
    {
        #region Implementation of IPostRepository

        /// <summary>
        /// 查詢首頁文章列表
        /// </summary>
        /// <param name="limit">要查詢的記錄數</param>
        /// <returns></returns>
        public IEnumerable<Post> FindHomePagePosts(int limit = 20)
        {
            using (var db = DbFactory.GetSqlSugarClient())
            {
                var list = db.Queryable<Post>().OrderBy(x => x.Id, OrderByType.Desc).Take(limit).ToList();
                return list;
            }
        }
    }
    #endregion
}

文章服務接口和實現

打開文件[IPostService.cs],在其中新增接口方法: FindHomePagePosts ,代碼以下:

using System.Collections.Generic;
using TsBlog.Domain.Entities;

namespace TsBlog.Services
{
    public interface IPostService : IService<Post>
    {
        /// <summary>
        /// 查詢首頁文章列表
        /// </summary>
        /// <param name="limit">要查詢的記錄數</param>
        /// <returns></returns>
        IEnumerable<Post> FindHomePagePosts(int limit = 20);
    }
}

打開文件[PostService.cs],實現對應的接口方法:FindHomePagePosts,代碼以下:

using System.Collections.Generic;
using TsBlog.Domain.Entities;
using TsBlog.Repositories;

namespace TsBlog.Services
{
    public class PostService : GenericService<Post>, IPostService
    {
        private readonly IPostRepository _repository;
        public PostService(IPostRepository repository) : base(repository)
        {
            _repository = repository;
        }


        #region Implementation of IPostService

        /// <summary>
        /// 查詢首頁文章列表
        /// </summary>
        /// <param name="limit">要查詢的記錄數</param>
        /// <returns></returns>
        public IEnumerable<Post> FindHomePagePosts(int limit = 20)
        {
            return _repository.FindHomePagePosts(limit);
        }

        #endregion
    }
}

附加修改:重構了一下倉儲接口中的 FindListByClause 方法,將orderBy參數設置爲可空參數,具體實現以下:

/// <summary>
/// 根據條件查詢數據
/// </summary>
/// <param name="predicate">條件表達式樹</param>
/// <param name="orderBy">排序</param>
/// <returns>泛型實體集合</returns>
IEnumerable<T> FindListByClause(Expression<Func<T, bool>> predicate, string orderBy = "");

對應的修改泛型倉儲中的對應實現:

/// <summary>
/// 根據條件查詢數據
/// </summary>
/// <param name="predicate">條件表達式樹</param>
/// <param name="orderBy">排序</param>
/// <returns>泛型實體集合</returns>
public IEnumerable<T> FindListByClause(Expression<Func<T, bool>> predicate, string orderBy = "")
{
    using (var db = DbFactory.GetSqlSugarClient())
    {
        var query = db.Queryable<T>().Where(predicate);
        if (!string.IsNullOrEmpty(orderBy))
        {
            query = query.OrderBy(orderBy);
        }
        var entities = query.ToList();
        return entities;
    }
}

一樣的,服務層中也做相應的修改:

IService.cs 文件中的 FindListByClause接口方法:

/// <summary>
/// 根據條件查詢數據
/// </summary>
/// <param name="predicate">條件表達式樹</param>
/// <param name="orderBy">排序</param>
/// <returns>泛型實體集合</returns>
IEnumerable<T> FindListByClause(Expression<Func<T, bool>> predicate, string orderBy = "");

泛型服務類:GenericService.cs 中的 FindListByClause 方法實現:

/// <summary>
/// 根據條件查詢數據
/// </summary>
/// <param name="predicate">條件表達式樹</param>
/// <param name="orderBy">排序</param>
/// <returns>泛型實體集合</returns>
public IEnumerable<T> FindListByClause(Expression<Func<T, bool>> predicate, string orderBy = "")
{
    return _repository.FindListByClause(predicate, orderBy);
}

在開始處理HomeController控制器以前 ,咱們先在項目[TsBlog.Core]中新建兩個幫助類,分別爲:HtmlHelper.csStringHelper.cs。其中代碼分別爲:

HtmlHelper.cs:

using System.Text.RegularExpressions;

namespace TsBlog.Core
{
    public static class HtmlHelper
    {
        #region 去掉HTML中的全部標籤,只留下純文本
        /// <summary>
        /// 去掉HTML中的全部標籤,只留下純文本
        /// </summary>
        /// <param name="strHtml"></param>
        /// <returns></returns>
        public static string CleanHtml(this string strHtml)
        {
            if (string.IsNullOrEmpty(strHtml)) return strHtml;
            //刪除腳本
            strHtml = Regex.Replace(strHtml, "(\\<script(.+?)\\</script\\>)|(\\<style(.+?)\\</style\\>)", "", RegexOptions.IgnoreCase | RegexOptions.Singleline);
            //刪除標籤
            var r = new Regex(@"<\/?[^>]*>", RegexOptions.IgnoreCase);
            Match m;
            for (m = r.Match(strHtml); m.Success; m = m.NextMatch())
            {
                strHtml = strHtml.Replace(m.Groups[0].ToString(), "");
            }
            return strHtml.Trim();
        }

        #endregion
    }
}

StringHelper.cs

using System;

namespace TsBlog.Core
{
    public static class StringHelper
    {
        #region
        /// <summary>
        /// 截取指定長度的字符串
        /// </summary>
        /// <param name="str">原始字符串</param>
        /// <param name="strLength">要保留的字符串長度</param>
        /// <returns></returns>
        public static string CutStrLength(this string str, int strLength)
        {
            var strNew = str;
            if (string.IsNullOrEmpty(strNew)) return strNew;
            var strOriginalLength = strNew.Length;
            if (strOriginalLength > strLength)
            {
                strNew = strNew.Substring(0, strLength) + "...";
            }
            return strNew;
        }

        #endregion

        #region
        /// <summary>
        /// 截取指定長度的字符串
        /// </summary>
        /// <param name="str">原始字符串</param>
        /// <param name="strLength">要保留的字符串長度</param>
        /// <param name="endWithEllipsis">是或以省略號(...)結束</param>
        /// <returns></returns>
        public static string CutStrLength(string str, int strLength, bool endWithEllipsis)
        {
            string strNew = str;
            if (!strNew.Equals(""))
            {
                int strOriginalLength = strNew.Length;
                if (strOriginalLength > strLength)
                {
                    strNew = strNew.Substring(0, strLength);
                    if (endWithEllipsis)
                    {
                        strNew += "...";
                    }
                }
            }
            return strNew;
        }

        #endregion

        #region 截斷字符串(可保留完整單詞)
        /// <summary>
        /// 截斷字符串(可保留完整單詞)
        /// </summary>
        /// <param name="valueToTruncate">需處理的字符串</param>
        /// <param name="maxLength">字符數</param>
        /// <param name="options">截斷選項</param>
        /// <returns></returns>
        public static string TruncateString(this string valueToTruncate, int maxLength, TruncateOptions options)
        {
            if (valueToTruncate == null)
            {
                return "";
            }

            if (valueToTruncate.Length <= maxLength)
            {
                return valueToTruncate;
            }

            var includeEllipsis = (options & TruncateOptions.IncludeEllipsis) ==
                    TruncateOptions.IncludeEllipsis;
            var finishWord = (options & TruncateOptions.FinishWord) ==
                    TruncateOptions.FinishWord;
            var allowLastWordOverflow =
              (options & TruncateOptions.AllowLastWordToGoOverMaxLength) ==
              TruncateOptions.AllowLastWordToGoOverMaxLength;

            var retValue = valueToTruncate;

            if (includeEllipsis)
            {
                maxLength -= 1;
            }

            var lastSpaceIndex = retValue.LastIndexOf(" ",
              maxLength, StringComparison.CurrentCultureIgnoreCase);

            if (!finishWord)
            {
                retValue = retValue.Remove(maxLength);
            }
            else if (allowLastWordOverflow)
            {
                var spaceIndex = retValue.IndexOf(" ",
                  maxLength, StringComparison.CurrentCultureIgnoreCase);
                if (spaceIndex != -1)
                {
                    retValue = retValue.Remove(spaceIndex);
                }
            }
            else if (lastSpaceIndex > -1)
            {
                retValue = retValue.Remove(lastSpaceIndex);
            }

            if (includeEllipsis && retValue.Length < valueToTruncate.Length)
            {
                retValue += "...";
            }
            return retValue;
        }

        #endregion
    }

    #region 截斷字符串用的枚舉
    /// <summary>
    /// 截斷字符串用的枚舉
    /// </summary>
    [Flags]
    public enum TruncateOptions
    {
        /// <summary>
        /// 不做任何處理
        /// </summary>
        None = 0x0,
        /// <summary>
        /// 保留完整單詞
        /// </summary>
        FinishWord = 0x1,
        /// <summary>
        /// 容許最後一個單詞超過最大長度限制
        /// </summary>
        AllowLastWordToGoOverMaxLength = 0x2,
        /// <summary>
        /// 字符串最後跟省略號
        /// </summary>
        IncludeEllipsis = 0x4
    }
    #endregion
}

在項[TsBlog.ViewModel]中的文章視圖文件[...TsBlogsrcLibrariesTsBlog.ViewModelPostPostViewModel.cs]中添加一個新的屬性:Summary,此時的PostViewModel是這樣的:

namespace TsBlog.ViewModel.Post
{
    /// <summary>
    /// 博文視圖實體類
    /// </summary>
    public class PostViewModel
    {
        /// <summary>
        /// ID
        /// </summary>
        public int Id { get; set; }
        /// <summary>
        /// 標題
        /// </summary>
        public string Title { get; set; }
        /// <summary>
        /// 內容
        /// </summary>
        public string Content { get; set; }
        /// <summary>
        /// 做者ID
        /// </summary>
        public string AuthorId { get; set; }
        /// <summary>
        /// 做者姓名
        /// </summary>
        public string AuthorName { get; set; }
        /// <summary>
        /// 建立時間
        /// </summary>
        public string CreatedAt { get; set; }
        /// <summary>
        /// 發佈時間
        /// </summary>
        public string PublishedAt { get; set; }
        /// <summary>
        /// 是否標識已刪除
        /// </summary>
        public string IsDeleted { get; set; }
        /// <summary>
        /// 是否容許展現
        /// </summary>
        public bool AllowShow { get; set; }
        /// <summary>
        /// 瀏覽量
        /// </summary>
        public int ViewCount { get; set; }

        /// <summary>
        /// 摘要
        /// </summary>
        public string Summary { get; set; }
    }
}

在項目[TsBlog.Frontend]中建立一個名爲:Extensions 文件夾,並在其中建立一個文章的靜態擴展類[...TsBlog.FrontendExtensionsPostExtension.cs],同時實現如下靜態擴展方法:

using TsBlog.Core;
using TsBlog.ViewModel.Post;

namespace TsBlog.Frontend.Extensions
{
    public static class PostExtension
    {
        /// <summary>
        /// 格式化文章的視圖實體
        /// </summary>
        /// <param name="model">文章視圖實體類</param>
        /// <returns></returns>
        public static PostViewModel FormatPostViewModel(this PostViewModel model)
        {
            if (model == null)
            {
                return null;
            }

            model.Summary = model.Content
                .CleanHtml()            //去掉全部HTML標籤
                .TruncateString(200, TruncateOptions.FinishWord | TruncateOptions.AllowLastWordToGoOverMaxLength);     //截斷指定長度做爲文章摘要
            return model;
        }
    }
}

網站首頁[HomeController]

在首頁的控制器[...TsBlog.FrontendControllersHomeController.cs]中,利用文章服務接口的方法實現首頁文章列表的查詢,代碼以下:

using System.Linq;
using System.Web.Mvc;
using TsBlog.AutoMapperConfig;
using TsBlog.Frontend.Extensions;
using TsBlog.Services;

namespace TsBlog.Frontend.Controllers
{
    public class HomeController : Controller
    {
        /// <summary>
        /// 文章服務接口
        /// </summary>
        private readonly IPostService _postService;
        public HomeController(IPostService postService)
        {
            _postService = postService;
        }
        /// <summary>
        /// 首頁
        /// </summary>
        /// <returns></returns>
        public ActionResult Index()
        {
            var list = _postService.FindHomePagePosts();
            var model = list.Select(x => x.ToModel().FormatPostViewModel());
            return View(model);
        }
    }
}

好了,到此咱們的首頁製做與數據綁定等到完成了,按F5運行,咱們便可看到本文開篇所示的首頁效果。

文章詳情頁[PostController]

新建一個名爲:PostController的控制器,並添加以下代碼:

using System.Web.Mvc;
using TsBlog.AutoMapperConfig;
using TsBlog.Services;

namespace TsBlog.Frontend.Controllers
{
    public class PostController : Controller
    {
        /// <summary>
        /// 文章服務接口
        /// </summary>
        private readonly IPostService _postService;

        public PostController(IPostService postService)
        {
            _postService = postService;
        }

        /// <summary>
        /// 文章詳情
        /// </summary>
        /// <param name="id">文章ID</param>
        /// <returns></returns>
        public ActionResult Details(int id)
        {
            var post = _postService.FindById(id);
            var model = post.ToModel();
            return View(model);
        }
    }
}

再添加文章詳情頁的視圖[...TsBlog.FrontendViewsPostDetails.cshtml],添加以下視圖HTML代碼:

@model TsBlog.ViewModel.Post.PostViewModel
@{
    Layout = null;
}
<!doctype html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>@(Model.Title) | TSBLOG</title>
    <link href="~/Content/bootstrap.min.css" rel="stylesheet" />
    <link href="~/resources/css/site.css" rel="stylesheet" />
</head>
<body>
    <nav class="navbar navbar-default navbar-static-top ts-navbar">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="~/">網站名稱</a>
            </div>
            <div id="navbar" class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a href="~/">網站首頁</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">分類導航 <span class="caret"></span></a>
                        <ul class="dropdown-menu">
                            <li class="dropdown-header">後端開發</li>
                            <li><a href="http://2sharings.com/category/csharp-development">C#程序設計</a></li>
                            <li><a href="http://2sharings.com/category/dot-net">.NET程序設計</a></li>
                            <li><a href="http://2sharings.com/category/asp-dot-net">ASP.NET</a></li>
                            <li><a href="http://2sharings.com/category/asp-net-mvc">ASP.NET MVC</a></li>
                            <li><a href="http://2sharings.com/category/asp-dotnet-core">ASP.NET Core</a></li>
                            <li><a href="http://2sharings.com/category/winform">Winform</a></li>
                            <li role="separator" class="divider"></li>
                            <li class="dropdown-header">數據庫</li>
                            <li><a href="http://2sharings.com/category/mysql">MySQL</a></li>
                            <li><a href="http://2sharings.com/category/sql-server">SQL Server</a></li>
                            <li><a href="http://2sharings.com/category/sqlite">SqLite</a></li>
                        </ul>
                    </li>
                    <li><a href="~/home/about">關於咱們</a></li>
                    <li><a href="~/home/contact">聯繫咱們</a></li>
                </ul>
                <ul class="nav navbar-nav navbar-right navbar-profile">
                    <li><a href="~/account/register">免費註冊</a></li>
                    <li><a class="btn btn-primary nav-btn-login" href="~/account/login">當即登陸</a></li>
                </ul>
            </div>
        </div>
    </nav>
    <div class="container">
        <h1 class="post-title">@Model.Title</h1>
        <article class="article-content">
            @Html.Raw(Model.Content)
        </article>
    </div>
    <footer class="footer-box">
        <div class="container">
            版權全部 &copy; @(DateTime.Now.Year)
        </div>
    </footer>
    <script src="~/Scripts/jquery-3.2.1.min.js"></script>
    <script src="~/Scripts/bootstrap.min.js"></script>
</body>
</html>

OK,今天這期的關於網站首頁及文章詳情頁面的佈局與製做就分享到這裏,但願對你瞭解ASP.NET MVC WEB應用程序開發有所幫助。

本期源碼託管地址:https://github.com/lampo1024/...
數據庫腳本文件請到目錄下查看:TsBlog\document\scripts\mysql\v1.9\

若是你喜歡Rector的本系列文章,請爲我點個大大的贊。

看完教程若是以爲還不過癮的,想「勾對」的,歡迎加入圖享網官方QQ羣:483350228,若是你按照教程還原出來的程序運行有問題,請參照本期源碼對應調整與修改遇到問題的,也歡迎加入QQ羣。有什麼,你懂的。。。^_^

謝謝你的耐心閱讀,本系列未完待續,咱們下期再見……

本文來源自 碼友網一步一步建立ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](九)

相關文章
相關標籤/搜索