從零開始,搭建博客系統MVC5+EF6搭建框架(3),添加Nlog日誌、緩存機制(MemoryCache、RedisCache)、創建控制器父類BaseController

来源:http://www.cnblogs.com/M-LittleBird/archive/2016/09/26/5907742.html
-Advertisement-
Play Games

一、回顧系統進度以及本章概要 目前博客系統已經資料庫創建、以及依賴註入Autofac集成,接下來就是日誌和緩存集成,這裡日誌用的是Nlog,其實還有其他的日誌框架如log4,這些博客園都有很多介紹,這裡就不說了,緩存機制用的是微軟自帶的MemoryCache和比較流行Redis,這裡我也只是瞭解使用 ...


一、回顧系統進度以及本章概要

     目前博客系統已經資料庫創建、以及依賴註入Autofac集成,接下來就是日誌和緩存集成,這裡日誌用的是Nlog,其實還有其他的日誌框架如log4,這些博客園都有很多介紹,這裡就不說了,緩存機制用的是微軟自帶的MemoryCache和比較流行Redis,這裡我也只是瞭解使用,沒有做更升入的研究,以後好好學一下Redis,然後就是實現一個BaseController父類用來重寫JsonResult方法為的是返回時間格式問題,預設json返回的時間格式是Date(84923838332223)轉為常見的yyyy-MM-dd HH:mm:ss格式。

二、緩存機制實現

1、在公共程式集中創建連個文件加一個Cache用來存放緩存類,一個是Log是用來創建Nlog類,這裡都使用介面來實現,以便可以以後可以多個實現。

image

2、首先創建一個ICacheManager介面類。

  1 namespace Wchl.WMBlog.Common.Cache
  2 {
  3     public interface ICacheManager
  4     {
  5        /// <summary>
  6        /// 獲取
  7        /// </summary>
  8        /// <typeparam name="TEntity"></typeparam>
  9        /// <param name="key"></param>
 10        /// <returns></returns>
 11         TEntity Get<TEntity>(string key);
 12         //設置
 13         void Set(string key, object value, TimeSpan cacheTime);
 14         //判斷是否存在
 15         bool Contains(string key);
 16         //移除
 17         void Remove(string key);
 18         //清除
 19         void Clear();
 20 
 21     }
 22 }
View Code

3、在實現微軟緩存機制的時候需要引用System.Runtime.Caching.dll,創建一個MemoryCacheManager 類

  1 namespace Wchl.WMBlog.Common.Cache
  2 {
  3      public  class MemoryCacheManager : ICacheManager
  4     {
  5         public void Clear()
  6         {
  7 
  8             foreach (var item in MemoryCache.Default)
  9             {
 10                 this.Remove(item.Key);
 11             }
 12         }
 13 
 14         public bool Contains(string key)
 15         {
 16             return MemoryCache.Default.Contains(key);
 17         }
 18 
 19         public TEntity Get<TEntity>(string key)
 20         {
 21             return (TEntity)MemoryCache.Default.Get(key);
 22         }
 23 
 24         public void Remove(string key)
 25         {
 26             MemoryCache.Default.Remove(key);
 27         }
 28 
 29         public void Set(string key, object value, TimeSpan cacheTime)
 30         {
 31             MemoryCache.Default.Add(key, value, new CacheItemPolicy { SlidingExpiration = cacheTime });
 32         }
 33     }
 34 }
View Code

4、實現RedisCacheManager類,這裡我們使用的免費的Redis客服端是StackExchange.Redis.可以在nuget中下載到。

image

RedisCacheManager類

  1 namespace Wchl.WMBlog.Common.Cache
  2 {
  3     public class RedisCacheManager : ICacheManager
  4     {
  5         private readonly string redisConnenctionString;
  6 
  7         public volatile ConnectionMultiplexer redisConnection;
  8 
  9         private readonly object redisConnectionLock = new object();
 10 
 11         public RedisCacheManager()
 12         {
 13             //鏈接redis服務語句
 14             string redisConfiguration = ConfigurationManager.ConnectionStrings["redisCache"].ToString();
 15 
 16             if (string.IsNullOrWhiteSpace(redisConfiguration))
 17             {
 18                 throw new ArgumentException("redis config is empty", nameof(redisConfiguration));
 19             }
 20             this.redisConnenctionString = redisConfiguration;
 21             this.redisConnection = GetRedisConnection();
 22         }
 23 
 24         private ConnectionMultiplexer GetRedisConnection()
 25         {
 26             if (this.redisConnection != null && this.redisConnection.IsConnected)
 27             {
 28                 return this.redisConnection;
 29             }
 30             lock (redisConnectionLock)
 31             {
 32                 if (this.redisConnection != null)
 33                 {
 34                     //釋放redis連接
 35                     this.redisConnection.Dispose();
 36                 }
 37                 this.redisConnection = ConnectionMultiplexer.Connect(redisConnenctionString);
 38             }
 39             return this.redisConnection;
 40         }
 41 
 42         public void Clear()
 43         {
 44             foreach (var endPoint in this.GetRedisConnection().GetEndPoints())
 45             {
 46                 var server = this.GetRedisConnection().GetServer(endPoint);
 47                 foreach (var key in server.Keys())
 48                 {
 49                     redisConnection.GetDatabase().KeyDelete(key);
 50                 }
 51             }
 52         }
 53 
 54         public bool Contains(string key)
 55         {
 56             return redisConnection.GetDatabase().KeyExists(key);
 57         }
 58 
 59         public TEntity Get<TEntity>(string key)
 60         {
 61             var value = redisConnection.GetDatabase().StringGet(key);
 62             if (value.HasValue)
 63             {
 64                 return SerializeHelper.Deserialize<TEntity>(value);
 65             } else
 66             {
 67                 return default(TEntity);
 68             }
 69         }
 70 
 71         public void Remove(string key)
 72         {
 73             redisConnection.GetDatabase().KeyDelete(key);
 74         }
 75 
 76         public void Set(string key, object value, TimeSpan cacheTime)
 77         {
 78             if (value != null)
 79             {
 80                 redisConnection.GetDatabase().StringSet(key, SerializeHelper.Serialize(value), cacheTime);
 81             }
 82         }
 83     }
 84 }
View Code

這裡在存儲數據的時候使用到了序列化和反序列化,用的序列化工具是Newtonsoft.Json,同樣也可以在nuget中找到。

image

SerializeHelper序列化幫助類

  1 namespace Wchl.WMBlog.Common
  2 {
  3     public class SerializeHelper
  4     {
  5         /// <summary>
  6         /// 序列化
  7         /// </summary>
  8         /// <param name="item"></param>
  9         /// <returns></returns>
 10         public static byte[] Serialize(object item)
 11         {
 12             var jsonString = JsonConvert.SerializeObject(item);
 13 
 14             return Encoding.UTF8.GetBytes(jsonString);
 15         }
 16         /// <summary>
 17         /// 反序列化
 18         /// </summary>
 19         /// <typeparam name="TEntity"></typeparam>
 20         /// <param name="value"></param>
 21         /// <returns></returns>
 22         public static TEntity Deserialize<TEntity>(byte[] value)
 23         {
 24             if (value == null)
 25             {
 26                 return default(TEntity);
 27             }
 28             var jsonString = Encoding.UTF8.GetString(value);
 29             return JsonConvert.DeserializeObject<TEntity>(jsonString);
 30         }
 31     }
 32 }
View Code

三、日誌處理:Nlog日誌框架

1、首先實現一個日子介面ILogger

  1 namespace Wchl.WMBlog.Common.Log
  2 {
  3     public interface ILogger
  4     {
  5         void Debug(string message);
  6         void Debug(string message, Exception exception);
  7         void Error(string message);
  8         void Error(string message, Exception exception);
  9         void Fatal(string message);
 10         void Fatal(string message, Exception exception);
 11         void Info(string message);
 12         void Info(string message, Exception exception);
 13         void Warn(string message);
 14         void Warn(string message, Exception exception);
 15     }
 16 }
View Code

2.在nuget中添加Nlog框架

image

nlog.config是日誌框架的配置文件。

Nloglogger類

  1 namespace Wchl.WMBlog.Common.Log
  2 {
  3     public class NLogLogger : ILogger
  4     {
  5         private readonly Logger logger = LogManager.GetCurrentClassLogger();
  6         public void Debug(string message)
  7         {
  8             logger.Debug(message);
  9         }
 10 
 11         public void Debug(string message, Exception exception)
 12         {
 13             logger.Debug(exception, message);
 14         }
 15 
 16         public void Error(string message)
 17         {
 18             logger.Error(message);
 19         }
 20 
 21         public void Error(string message, Exception exception)
 22         {
 23             logger.Error(exception, message);
 24         }
 25 
 26         public void Fatal(string message)
 27         {
 28             logger.Fatal(message);
 29         }
 30 
 31         public void Fatal(string message, Exception exception)
 32         {
 33             logger.Fatal(exception, message);
 34         }
 35 
 36         public void Info(string message)
 37         {
 38             logger.Info(message);
 39         }
 40 
 41         public void Info(string message, Exception exception)
 42         {
 43             logger.Info(exception, message);
 44         }
 45 
 46         public void Warn(string message)
 47         {
 48             logger.Warn(message);
 49         }
 50 
 51         public void Warn(string message, Exception exception)
 52         {
 53             logger.Warn(exception, message);
 54         }
 55     }
 56 }
View Code

3、配置日誌文件NLog.config,這裡是在webUI層應用這個文件,因為最終日誌是在web下運行。

image

在targets的節點下麵配置,這裡是以文件的方式保存日子,你也可以使用這個配置一個直接把日子寫到資料庫中

  1 <target xsi:type ="File"
  2     name="file"
  3     header="------------------------------Start------------------------------"
  4     footer="------------------------------End------------------------------"
  5     fileName="${basedir}/App_Data/Logs/${shortdate}.log"
  6     layout="${longdate} - ${level:uppercase=true}:${message} ${callsite:fileName=true} ${exception:format=Type,Message,Method,StackTrace:maxInnerExceptionLevel=5:innerFormat=ShortType,Message,Method,StackTrace}"
  7     keepFileOpen="false"
  8     archiveFileName="${basedir}/App_Data/Logs/Backup_${shortdate}.{##}.log"
  9     archiveNumbering="Sequence"
 10     archiveEvery="Day"
 11     maxArchiveFiles="30">
 12 
 13     </target>
View Code

在rules節點下配置 <logger name="*" minlevel="Error" writeTo="file" />表示什麼級別的日誌對應放在哪個配置裡面。

image

這裡日誌保存在發佈站點App_Data\Logs下

image

4、日誌測試

4.1在測試之前首先設置一個全局錯誤機制文件ExpFilter繼承HandleErrorAttribute,放在Webcore下麵

image

這裡需要添加System.Web.Mvc.dll程式集。

ExpFilter類:

  1 namespace Wchl.WMBlog.WebCore
  2 {
  3     public class ExpFilter:HandleErrorAttribute
  4     {
  5         public override void OnException(ExceptionContext filterContext)
  6         {
  7             Exception exp = filterContext.Exception;
  8 
  9             //獲取ex的第一級內部異常
 10             Exception innerEx = exp.InnerException == null ? exp : exp.InnerException;
 11             //迴圈獲取內部異常直到獲取詳細異常信息為止
 12             while (innerEx.InnerException!=null)
 13             {
 14                 innerEx = innerEx.InnerException;
 15             }
 16             NLogLogger nlog = new NLogLogger();
 17             if (filterContext.HttpContext.Request.IsAjaxRequest())
 18             {
 19 
 20                 nlog.Error(innerEx.Message);
 21                 JsonConvert.SerializeObject(new { status = 1, msg ="請求發生錯誤,請聯繫管理員"});
 22             }
 23             else
 24             {
 25                 nlog.Error("Error",exp);
 26                 ViewResult vireResult = new ViewResult();
 27                 vireResult.ViewName = "/Views/Shared/Error.cshtml";
 28                 filterContext.Result = vireResult;
 29             }
 30 
 31             //告訴MVC框架異常被處理
 32             filterContext.ExceptionHandled = true;
 33             base.OnException(filterContext);
 34         }
 35     }
 36 }
 37 
View Code

4.2這裡對兩種請求方式做處理一種是Ajax請求,一種是對鏈接地址做處理,另外還需要在webui下創建一個錯誤提醒頁面。(/Views/Shared/Error.cshtml)

image

4.3在homecontroller控制器下寫錯誤代碼

image

4.4日誌測試結果:這裡直接開始執行(不調試)

image

然後在項目文件下查看web站點下的\App_Data\Logs查看日子文件

image

日誌信息:錯誤信息,以及錯誤是那個文件多少行都有顯示。

image

四、創建BaseController類

這裡使用反序列化工具都是Newtonsoft.Json

BaseController類:

  1 namespace Wchl.WMBlog.WebCore
  2 {
  3     public class BaseController: Controller
  4     {
  5         protected override JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
  6         {
  7             return new JsonNetResult { Data = data, ContentType = contentType, ContentEncoding = contentEncoding, JsonRequestBehavior = behavior };
  8         }
  9     }
 10 }
View Code

JsonNetResult類:

  1 namespace Wchl.WMBlog.WebCore
  2 {
  3     public class JsonNetResult:JsonResult
  4     {
  5         public override void ExecuteResult(ControllerContext context)
  6         {
  7             if (context==null)
  8             {
  9                 throw new ArgumentException(nameof(context));
 10             }
 11 
 12             var response = context.HttpContext.Response;
 13 
 14             response.ContentType = !string.IsNullOrEmpty(ContentType) ? ContentType : "application/json";
 15 
 16             if (ContentEncoding != null)
 17             {
 18                 response.ContentEncoding = ContentEncoding;
 19             }
 20 
 21             var jsonSerializerSetting = new JsonSerializerSettings();
 22             //首字母小寫
 23             jsonSerializerSetting.ContractResolver = new CamelCasePropertyNamesContractResolver();
 24             //日期格式化
 25             jsonSerializerSetting.DateFormatString = "yyyy-MM-dd HH:mm:ss";
 26             var json = JsonConvert.SerializeObject(Data, Formatting.None, jsonSerializerSetting);
 27 
 28             response.Write(json);
 29 
 30         }
 31     }
 32 }
View Code

直接在創建的控制器下集成:

image

   接下來就是準備實現頁面佈局,先做個簡單的前臺查看,後臺分佈的功能,然後在一步一步的完善,希望大家多多指點,多多支持,謝謝了。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 主要涉及:JOIN 、JOIN 更新、GROUP BY HAVING 數據查重/去重 ...
  • http://www.cnblogs.com/lyhabc/p/3533027.html 一般的交易系統裡面我們都會以自增列或交易時間列作為聚集索引列,因為一般這些系統都是寫多讀少 每天的交易數據會不停的插入到資料庫,但是讀取數據就沒有數據插入那麼頻繁 因為這些系統一般是寫多讀少,所以我們會選擇在自 ...
  • 本案例是一個小型數據抽取分析類系統,通過抽取數據共用中心中的配網台區(一個台區一個配變)的相關數據進行整合,完成有關台區的50多個欄位按照日、月、多月等維度的集中計算展示。新使用的控制項有:作業、轉換、檢驗欄位的值、使用javascript腳本驗證、等待、設置變數、表輸入、資料庫連接、表輸出(同構)、... ...
  • 瞭解: Yum:Yellowdog Updater,Modified的簡稱,起初由yellow dog發行版的開發者Terra Soft研發,用Python編寫,後經杜克大學的Linux@Duke開發團隊進行改進,遂有此名。Yum是一個shell前端軟體包管理器,基於RPM包管理,能夠從指定的伺服器 ...
  • 最近在開發服務後臺的時候,使用c#調用了多個c++編寫的dll,期間遇到了一系列的問題,經過一番努力最後都一一解決了,在此做個總結,方便以後參考。主要有:類型對照問題、記憶體釋放問題、版本問題、編譯問題、資源載入問題、異常捕獲與問題定位、vs實時調試問題等。 ...
  • 前言 面向對象三大基本特性:封裝、繼承、多態。上一篇中介紹了類的定義,下麵就瞭解下F 中繼承和多態的使用吧。
  • 背水一戰 Windows 10 之 控制項(彈出類): ToolTip, Popup, PopupMenu ...
  • 準備 IDE:VisualStudio 2015 Language:VB.NET/C# 圖形API:Win2D MSDN教程:UWP游戲開發 寫在前面的話 沒有什麼比重覆造輪子更讓人心碎的事情了。 (如果有,那就是造了兩遍) 是否有必要開發游戲引擎? 現在市面上有很多成熟的跨平臺游戲引擎,對個人開發 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...