PS:如果图片模糊,鼠标右击复制图片网址,然后在浏览器中打开即可。

一、回顾系统进度以及本章概要

目前博客系统已经数据库创建、以及依赖注入Autofac集成,接下来就是日志和缓存集成,这里日志用的是Nlog,其实还有其他的日志框架如log4,这些博客园都有很多介绍,这里就不说了,缓存机制用的是微软自带的MemoryCache和比较流行Redis,这里我也只是了解使用,没有做更升入的研究,以后好好学一下Redis,然后就是实现一个BaseController父类用来重写JsonResult方法为的是返回时间格式问题,默认json返回的时间格式是Date(84923838332223)转为常见的yyyy-MM-dd HH:mm:ss格式。

二、缓存机制实现

1、在公共程序集中创建连个文件加一个Cache用来存放缓存类,一个是Log是用来创建Nlog类,这里都使用接口来实现,以便可以以后可以多个实现。

2、首先创建一个ICacheManager接口类。

  ICacheManager接口类代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace _52MVCBlog.Common.Cache
{
public interface ICacheManager
{
/// <summary>
// 获取
// </summary>
// <typeparam name="TEntity"></typeparam>
// <param name="key"></param>
// <returns></returns>
TEntity Get<TEntity>(string key);
//设置
void Set(string key, object value, TimeSpan cacheTime);
//判断是否存在
bool Contains(string key);
//移除
void Remove(string key);
//清除
void Clear();
}
}

3、在实现微软缓存机制的时候需要引用System.Runtime.Caching.dll,创建一个MemoryCacheManager 类

  MemoryCacheManager 类代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;
using System.Text;
using System.Threading.Tasks; namespace _52MVCBlog.Common.Cache
{
public class MemoryCacheManager:ICacheManager
{
public TEntity Get<TEntity>(string key)
{
return (TEntity)MemoryCache.Default.Get(key);
} public void Set(string key, object value, TimeSpan cacheTime)
{
MemoryCache.Default.Add(key, value, new CacheItemPolicy { SlidingExpiration = cacheTime });
} public bool Contains(string key)
{
return MemoryCache.Default.Contains(key);
} public void Remove(string key)
{
MemoryCache.Default.Remove(key);
} public void Clear()
{
foreach (var item in MemoryCache.Default)
{
this.Remove(item.Key);
}
}
}
}

4、创建SerializeHelper公共帮助类用来做系列化和反序列化,需要用nuget下载JSON.Net引用

  SerializeHelper类代码:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace _52MVCBlog.Common
{
public class SerializeHelper
{
/// <summary>
/// 序列化
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public static byte[] Serialize(object item)
{
string jsonString = JsonConvert.SerializeObject(item);
return Encoding.UTF8.GetBytes(jsonString);
} /// <summary>
/// 反序列化
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static TEntity Deserialize<TEntity>(byte[] value)
{
if (value == null)
{
return default(TEntity);
}
var jsonString = Encoding.UTF8.GetString(value);
return JsonConvert.DeserializeObject<TEntity>(jsonString);
} }
}

5、实现RedisCacheManager类,这里我们使用的免费的Redis客服端是StackExchange.Redis.可以在nuget中下载到。建议使用控制台命令Install-Package StackExchange.Redis -Version 1.2.6

  RedisCacheManager类代码:

using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace _52MVCBlog.Common.Cache
{
//Install-Package StackExchange.Redis -Version 1.2.6
public class RedisCacheManager : ICacheManager
{
private readonly string redisConnenctionString;
public volatile ConnectionMultiplexer redisConnection;
private readonly object redisConnectionLock = new object(); public RedisCacheManager()
{
//链接redis服务语句
string redisConfiguration = ConfigurationManager.ConnectionStrings["redisCache"].ToString();
if (string.IsNullOrWhiteSpace(redisConfiguration))
{
throw new ArgumentException("redis config is empty", "redisConfiguration");
} this.redisConnenctionString = redisConfiguration;
this.redisConnection = GetRedisConnection();
} private ConnectionMultiplexer GetRedisConnection()
{
if (this.redisConnection != null && this.redisConnection.IsConnected)
{
return this.redisConnection;
}
lock (redisConnectionLock)
{
if (this.redisConnection != null)
{
//释放redis连接
this.redisConnection.Dispose();
}
this.redisConnection = ConnectionMultiplexer.Connect(redisConnenctionString);
}
return this.redisConnection;
} public TEntity Get<TEntity>(string key)
{
RedisValue value = this.redisConnection.GetDatabase().StringGet(key);
if (value.HasValue)
return SerializeHelper.Deserialize<TEntity>(value);
else
return default(TEntity);
} public void Set(string key, object value, TimeSpan cacheTime)
{
if (value != null)
this.redisConnection.GetDatabase().StringSet(key, SerializeHelper.Serialize(value), cacheTime);
} public bool Contains(string key)
{
return this.redisConnection.GetDatabase().KeyExists(key);
} public void Remove(string key)
{
this.redisConnection.GetDatabase().KeyDelete(key);
} public void Clear()
{
foreach (var endPoint in this.redisConnection.GetEndPoints())
{
var server = this.GetRedisConnection().GetServer(endPoint);
foreach (var key in server.Keys())
{
this.Remove(key);
}
}
}
}
}

三、日志处理:Nlog日志框架

1、首先实现一个日子接口ILogger

  ILogger接口代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace _52MVCBlog.Common.Log
{
public interface ILogger
{
void Debug(string message);
void Debug(string message, Exception exception);
void Error(string message);
void Error(string message, Exception exception);
void Fatal(string message);
void Fatal(string message, Exception exception);
void Info(string message);
void Info(string message, Exception exception);
void Warn(string message);
void Warn(string message, Exception exception);
}
}

2.在nuget中添加Nlog框架

  Install-Package NLog -Version 5.0.0-beta11

  Install-Package NLog.Schema -Version 4.5.0-rc01

  Install-Package NLog.Config -Version 4.5.0-rc01

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

  Nloglogger类代码:

using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace _52MVCBlog.Common.Log
{
public class NLogLogger : ILogger
{
private readonly Logger logger = LogManager.GetCurrentClassLogger();
public void Debug(string message)
{
logger.Debug(message);
} public void Debug(string message, Exception exception)
{
logger.Debug(exception, message);
} public void Error(string message)
{
logger.Error(message);
} public void Error(string message, Exception exception)
{
logger.Error(exception, message);
} public void Fatal(string message)
{
logger.Fatal(message);
} public void Fatal(string message, Exception exception)
{
logger.Fatal(exception, message);
} public void Info(string message)
{
logger.Info(message);
} public void Info(string message, Exception exception)
{
logger.Info(exception, message);
} public void Warn(string message)
{
logger.Warn(message);
} public void Warn(string message, Exception exception)
{
logger.Warn(exception, message);
}
}
}

3、配置日志文件NLog.config,这里是在从Common程序集拷贝到webUI层应用这个文件,因为最终日志是在web下运行。

  在targets的节点下面配置,这里是以文件的方式保存日子,你也可以使用这个配置一个直接把日子写到数据库中

  这里日志保存在发布站点App_Data\Logs下

  在rules节点下配置 <logger name="*" minlevel="Error" writeTo="file" />表示什么级别的日志对应放在哪个配置里面。

  NLog.config配置代码:

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="false"
internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log"> <!-- optional, add some variables
https://github.com/nlog/NLog/wiki/Configuration-file#variables
-->
<variable name="myvar" value="myvalue"/> <!--
See https://github.com/nlog/nlog/wiki/Configuration-file
for information on customizing logging rules and outputs.
-->
<targets>
<!-- 定义输出模板:
type="File":这个记录方式为文件类型
fileName="${logDirectory}/All.log":表示输出到文件All.log中
layout="...":输出文件中错误的显示格式
${logDirectory}:为上述定义的路径
${longdate}:输出长日期 yyyy-MM-dd HH:mm:ss.ffff(例:-- ::21.2120)
${level}:错误等级(由低到高为Trace,Debug,Info,Warn,Error,Fatal)
${newline}:输出 新的一行
${stacktrace}:输出 堆栈信息
${callsite:className=True:fileName=True:includeSourcePath=True:methodName=True}:输出 命名空间.类名.方法名(文件路径:行号)
${message}:输出错误信息-->
<target xsi:type="File"
name="file"
header="------------------------------Start------------------------------"
footer="------------------------------End------------------------------"
lineEnding="CR"
fileName="${basedir}/App_Data/Logs/${shortdate}.log"
layout="${longdate} - ${level:uppercase=true}:${message} ${callsite:fileName=true} ${exception:format=Type,Message,Method,StackTrace:maxInnerExceptionLevel=5:innerFormat=ShortType,Message,Method,StackTrace}"
keepFileOpen="false"
archiveFileName="${basedir}/App_Data/Logs/Backup_${shortdate}.{##}.log"
archiveNumbering="Sequence"
archiveEvery="Day"
maxArchiveFiles=""> </target> <!--
add your targets here
See https://github.com/nlog/NLog/wiki/Targets for possible targets.
See https://github.com/nlog/NLog/wiki/Layout-Renderers for the possible layout renderers.
--> <!--
Write events to a file with the date in the filename.
<target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${message}" />
-->
</targets> <rules>
<!-- add your logging rules here -->
<logger name="*" minlevel="Error" writeTo="file"/>
<!--
Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace) to "f"
<logger name="*" minlevel="Debug" writeTo="f" />
-->
</rules>
</nlog>

4、日志测试

4.1在52MVCBlog.WebCore程序集下面创建Filters文件夹,在测试之前首先设置一个全局错误机制文件ExpFilter.cs继承HandleErrorAttribute,放在Filters文件夹下面(需要引用System.Web.Mvc与System.Web)

  ExpFilter类代码:

using _52MVCBlog.Common.Log;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc; namespace _52MVCBlog.WebCore.Filters
{
public class ExpFilter : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
Exception exp = filterContext.Exception; //获取ex的第一级内部异常
Exception innerEx = exp.InnerException == null ? exp : exp.InnerException;
//循环获取内部异常直到获取详细异常信息为止
while (innerEx.InnerException != null)
{
innerEx = innerEx.InnerException;
} NLogLogger nlog = new NLogLogger(); if(filterContext.HttpContext.Request.IsAjaxRequest())
{
nlog.Error(innerEx.Message);
JsonConvert.SerializeObject(new { status = , msg = "请求发生错误,请联系管理员" });
}
else
{
nlog.Error("Error", exp);
ViewResult vireResult = new ViewResult();
vireResult.ViewName = "/Views/Shared/Error.cshtml";
filterContext.Result = vireResult;
} //告诉MVC框架异常被处理
filterContext.ExceptionHandled = true; base.OnException(filterContext);
}
}
}

4.2这里对两种请求方式做处理一种是Ajax请求,一种是对链接地址做处理,另外还需要在webui下创建一个错误提醒页面。(/Views/Shared/Error.cshtml)

@{
Layout = null;
} <!DOCTYPE html> <html>
<head>
<meta name="viewport" content="width=device-width" />
<title>错误</title>
</head>
<body>
<h2>抱歉,处理您的请求出错。</h2>
<h3>请联系系统管理员</h3>
</body>
</html>

4.3在HomeController控制器下写错误代码

4.4配置全局错误处理机制,需要在App_Start文件夹下新建FilterConfig.cs配置类,才能起作用。

  FilterConfig.cs配置类代码:

using _52MVCBlog.WebCore.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace _52MVCBlog.WebUI.App_Start
{
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
//filters.Add(new HandleErrorAttribute()); //将统一的action异常捕获过滤器ExpFilter注册成为全局
filters.Add(new ExpFilter());
}
}
}

  在Global.asax中的Application_Start()中注册全局过滤器.

4.5日志和异常测试结果:这里直接开始执行(不调试)

  然后在项目文件下查看web站点下的\App_Data\Logs查看日子文件

日志信息:错误信息,以及错误是那个文件多少行都有显示。

四、在52MVCBlog.WebCore程序集创建BaseController控制器基类

这里使用反序列化工具都是Newtonsoft.Json

  JsonNetResult类继承JsonResult类,实现对首字母和时间进行格式化。代码:

using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc; namespace _52MVCBlog.WebCore
{
public class JsonNetResult:JsonResult
{
public override void ExecuteResult(ControllerContext context)
{
if (context==null)
{
throw new ArgumentNullException("context");
} var response = context.HttpContext.Response;
response.ContentType = !string.IsNullOrEmpty(base.ContentType) ? base.ContentType : "application/json";
if (base.ContentEncoding!=null)
{
response.ContentEncoding = base.ContentEncoding;
} JsonSerializerSettings jsonSerialization = new JsonSerializerSettings();
//首字母小写
jsonSerialization.ContractResolver = new CamelCasePropertyNamesContractResolver();
//日期格式化
jsonSerialization.DateFormatString = "yyyy-MM-dd HH:mm:ss"; var json = JsonConvert.SerializeObject(Data, Formatting.None, jsonSerialization); response.Write(json); //base.ExecuteResult(context);
}
}
}

  BaseController继承类Controller类,返回JsonNetResult,实现返回对首字母和时间进行格式化,代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc; namespace _52MVCBlog.WebCore
{
public class BaseController : Controller
{
protected override JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
{
return new JsonNetResult() { Data = data, ContentType = contentType, ContentEncoding = contentEncoding, JsonRequestBehavior = behavior };
}
}
}

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

接下来就是准备实现页面布局,先做个简单的前台查看,后台分布的功能,然后在一步一步的完善,希望大家多多指点,多多支持,谢谢了。

【干货】利用MVC5+EF6搭建博客系统(三)添加Nlog日志、缓存机制(MemoryCache、RedisCache)、创建控制器父类BaseController的更多相关文章

  1. 【干货】利用MVC5+EF6搭建博客系统(四)(上)前后台页面布局页面实现,介绍使用的UI框架以及JS组件

    一.博客系统进度回顾以及页面设计 1.1页面设计说明 紧接前面基础基本完成了框架搭建,现在开始设计页面,前台页面设计我是模仿我博客园的风格来设计的,后台是常规的左右布局风格. 1.2前台页面风格 主页 ...

  2. 【干货】利用MVC5+EF6搭建博客系统(四)(下)前后台布局实现、发布博客以及展示

    二.博客系统后台布局实现 2.1.这里所用的是MVC的布局页来实现的,后台主要分为三部分:导航.菜单.主要内容 代码实现: 这里把后台单独放在一个区域里面,所以我这里建立一个admin的区域 在布局页 ...

  3. 【干货】利用MVC5+EF6搭建博客系统(二)测试添加数据、集成Autofac依赖注入

    PS:如果图片模糊,鼠标右击复制图片网址,然后在浏览器中打开即可. 一.测试仓储层.业务层是否能实现对数据库表的操作 1.在52MVCBlog.IRepository程序集下创建IsysUserInf ...

  4. 【干货】利用MVC5+EF6搭建博客系统(一)EF Code frist、实现泛型数据仓储以及业务逻辑

    习MVC有一段时间了,决定自己写一套Demo了,写完源码再共享. PS:如果图片模糊,鼠标右击复制图片网址,然后在浏览器中打开即可. 一.框架搭建 二.创建数据库 1.创建一个空的EF code fr ...

  5. 利用MVC5+EF6搭建博客系统

    https://www.cnblogs.com/wyt007/p/7880137.html

  6. Django快速搭建博客系统

    Django快速搭建博客系统 一.开发环境 Windows 7(64bit) python 3.6   https://www.python.org/ Django 2.0  https://www. ...

  7. day14搭建博客系统项目

    day14搭建博客系统项目 1.下载代码包 [root@web02 opt]# git clone https://gitee.com/lylinux/DjangoBlog.git 2.使用pid安装 ...

  8. 手把手教从零开始在GitHub上使用Hexo搭建博客教程(三)-使用Travis自动部署Hexo(1)

    前言 前面两篇文章介绍了在github上使用hexo搭建博客的基本环境和hexo相关参数设置等. 基于目前,博客基本上是可以完美运行了. 但是,有一点是不太好,就是源码同步问题,如果在不同的电脑上写文 ...

  9. hexo搭建博客系列(三)美化主题

    文章目录 其他搭建 1. 添加博客图标 2. 鼠标点击特效(二选一) 2.1 红心特效 2.2 爆炸烟花 3. 设置头像 4. 侧边栏社交小图标设置 5. 文章末尾的标签图标修改 6. 访问量统计 7 ...

随机推荐

  1. Game Theory

    HDU 5795 || 3032 把x个石子的堆分成非空两(i, j)或三堆(i, j, k)的操作->(sg[i] ^ sg[j])或(sg[i] ^ sg[j] ^ sg[k])是x的后继 ...

  2. Apache Flink 简单安装

    流计算这两年很火了,可能对数据的实时性要求高.现在用的hadoop框架,对流计算的支持,主要还是微批(spark),也不支持“Exactly Once”语义(可以使用外接的数据库解决),公司项目可能会 ...

  3. Django模板继承和引用

    一.模板继承 1.模板继承可以在创建一个基本“骨架”后,被其它子模板继承并覆盖,通过修改基础模板可以修改子模板中的所有框架 2.在模板teacher文件夹下创建基础模板 {% block xxx}与{ ...

  4. NIOS II 之串口学习

    UART中有6个寄存器分别为control, status, rxdata, txdata, divisor,endofpacket. 的寄存器是16位位宽的. UART会产生一个高电平的中断,当接收 ...

  5. redis_哈希对象

    redis哈希对象的底层编码有两种:ziplist.hashtable ziplist编码 当一个哈希键只包含少量kv对.且key和value都是小整数值.短字符串时,redis会使用压缩列表来做 z ...

  6. 回头来学习wpf的FlowDocument

    学习了一段时间的electron,其实是一个神奇的开发方式,让人神往.但其打印和ocx或是activeX方面还是让我不大放心去使用.毕竟当前首要任务还是window的应用开发. 于是重新学习wpf的F ...

  7. Java时间日期格式转换 转自:http://www.cnblogs.com/edwardlauxh/archive/2010/03/21/1918615.html

    Java时间格式转换大全 import java.text.*; import java.util.Calendar; public class VeDate { /** * 获取现在时间 * * @ ...

  8. 关于信息系统设计与开发——案例:VIP系统

    一.关于信息系统设计与开发 信息系统开发流程先对需求分析系统分析,设计数据库,设计程序,再对测试数据进行测试. 在程序设计中运用了接口:定义一个接口,可以有多种实现.变量声明为接口变量,调用接口方法, ...

  9. CSS3——animation的基础(轮播图)

    作为前端刚入门的小菜鸟,只想记录一下每天的小收获 对于animation动画 1.实现动画效果的组成: (1)通过类似Flash的关键帧来声明一个动画 (2)在animation属性中调用关键帧声明的 ...

  10. noip第24课资料