ASP.NET?MVC自定義異常過(guò)濾器使用案例
在上一篇文章中講解了自定義異常過(guò)濾器,這篇文章會(huì)結(jié)合工作中的真實(shí)案例講解一下如何使用自定義異常過(guò)濾器。
一、需求
本案例要實(shí)現(xiàn)的功能需求:在發(fā)生異常時(shí)記錄日志,日志內(nèi)容包括發(fā)生異常的Controller名稱、Action名稱、使用瀏覽器類(lèi)型和版本等。
二、案例
1、創(chuàng)建工具類(lèi)
首先創(chuàng)建項(xiàng)目中需要使用的工具類(lèi)。
1.1、創(chuàng)建日志工具類(lèi)
在案例中使用Log4net來(lái)記錄日志。首先要添加對(duì)Log4net的引用,直接在NuGet里面搜索Log4net,然后安裝即可。
日志消息實(shí)體類(lèi)代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace MVCCuetomerExcepFilterDemo.Models { /// <summary> /// 日志消息實(shí)體類(lèi) /// </summary> public class LogMessageEntity { /// <summary> /// 操作時(shí)間 /// </summary> public DateTime OperationTime { get; set; } /// <summary> /// Url地址 /// </summary> public string Url { get; set; } /// <summary> /// 類(lèi)名 /// </summary> public string Class { get; set; } /// <summary> /// IP /// </summary> public string Ip { get; set; } /// <summary> /// 主機(jī) /// </summary> public string Host { get; set; } /// <summary> /// 瀏覽器 /// </summary> public string Browser { get; set; } /// <summary> /// 操作人 /// </summary> public string UserName { get; set; } /// <summary> /// 內(nèi)容 /// </summary> public string Content { get; set; } /// <summary> /// 異常信息 /// </summary> public string ExceptionInfo { get; set; } /// <summary> /// 異常來(lái)源 /// </summary> public string ExceptionSource { get; set; } /// <summary> /// 異常信息備注 /// </summary> public string ExceptionRemark { get; set; } } }
創(chuàng)建日志級(jí)別枚舉類(lèi)型,分別對(duì)應(yīng)Log4net中的日志級(jí)別,代碼如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Web; namespace MVCCuetomerExcepFilterDemo.Models.Enums { /// <summary> /// 日志級(jí)別 /// </summary> public enum LogLevel { /// <summary> /// 錯(cuò)誤 /// </summary> [Description("錯(cuò)誤")] Error, /// <summary> /// 警告 /// </summary> [Description("警告")] Warning, /// <summary> /// 信息 /// </summary> [Description("信息")] Info, /// <summary> /// 調(diào)試 /// </summary> [Description("調(diào)試")] Debug } }
創(chuàng)建一個(gè)對(duì)日志格式進(jìn)行格式化的類(lèi),代碼如下:
using MVCCuetomerExcepFilterDemo.Models; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web; namespace MVCCuetomerExcepFilterDemo.Util { /// <summary> /// 日志格式器 /// </summary> public class LogFormat { /// <summary> /// 生成錯(cuò)誤 /// </summary> /// <param name="logMessage">對(duì)象</param> /// <returns></returns> public string ErrorFormat(LogMessageEntity logMessage) { StringBuilder strInfo = new StringBuilder(); strInfo.Append("1. 錯(cuò)誤: >> 操作時(shí)間: " + logMessage.OperationTime + " 操作人: " + logMessage.UserName + " \r\n"); strInfo.Append("2. 地址: " + logMessage.Url + " \r\n"); strInfo.Append("3. 類(lèi)名: " + logMessage.Class + " \r\n"); strInfo.Append("4. Ip : " + logMessage.Ip + " 主機(jī): " + logMessage.Host + " 瀏覽器: " + logMessage.Browser + " \r\n"); strInfo.Append("5. 內(nèi)容: " + logMessage.Content + "\r\n"); strInfo.Append("-----------------------------------------------------------------------------------------------------------------------------\r\n"); return strInfo.ToString(); } /// <summary> /// 生成警告 /// </summary> /// <param name="logMessage">對(duì)象</param> /// <returns></returns> public string WarnFormat(LogMessageEntity logMessage) { StringBuilder strInfo = new StringBuilder(); strInfo.Append("1. 警告: >> 操作時(shí)間: " + logMessage.OperationTime + " 操作人: " + logMessage.UserName + " \r\n"); strInfo.Append("2. 地址: " + logMessage.Url + " \r\n"); strInfo.Append("3. 類(lèi)名: " + logMessage.Class + " \r\n"); strInfo.Append("4. Ip : " + logMessage.Ip + " 主機(jī): " + logMessage.Host + " 瀏覽器: " + logMessage.Browser + " \r\n"); strInfo.Append("5. 內(nèi)容: " + logMessage.Content + "\r\n"); strInfo.Append("-----------------------------------------------------------------------------------------------------------------------------\r\n"); return strInfo.ToString(); } /// <summary> /// 生成信息 /// </summary> /// <param name="logMessage">對(duì)象</param> /// <returns></returns> public string InfoFormat(LogMessageEntity logMessage) { StringBuilder strInfo = new StringBuilder(); strInfo.Append("1. 信息: >> 操作時(shí)間: " + logMessage.OperationTime + " 操作人: " + logMessage.UserName + " \r\n"); strInfo.Append("2. 地址: " + logMessage.Url + " \r\n"); strInfo.Append("3. 類(lèi)名: " + logMessage.Class + " \r\n"); strInfo.Append("4. Ip : " + logMessage.Ip + " 主機(jī): " + logMessage.Host + " 瀏覽器: " + logMessage.Browser + " \r\n"); strInfo.Append("5. 內(nèi)容: " + logMessage.Content + "\r\n"); strInfo.Append("-----------------------------------------------------------------------------------------------------------------------------\r\n"); return strInfo.ToString(); } /// <summary> /// 生成調(diào)試 /// </summary> /// <param name="logMessage">對(duì)象</param> /// <returns></returns> public string DebugFormat(LogMessageEntity logMessage) { StringBuilder strInfo = new StringBuilder(); strInfo.Append("1. 調(diào)試: >> 操作時(shí)間: " + logMessage.OperationTime + " 操作人: " + logMessage.UserName + " \r\n"); strInfo.Append("2. 地址: " + logMessage.Url + " \r\n"); strInfo.Append("3. 類(lèi)名: " + logMessage.Class + " \r\n"); strInfo.Append("4. Ip : " + logMessage.Ip + " 主機(jī): " + logMessage.Host + " 瀏覽器: " + logMessage.Browser + " \r\n"); strInfo.Append("5. 內(nèi)容: " + logMessage.Content + "\r\n"); strInfo.Append("-----------------------------------------------------------------------------------------------------------------------------\r\n"); return strInfo.ToString(); } /// <summary> /// 生成異常信息 /// </summary> /// <param name="logMessage">對(duì)象</param> /// <returns></returns> public string ExceptionFormat(LogMessageEntity logMessage) { StringBuilder strInfo = new StringBuilder(); strInfo.Append("1. 調(diào)試: >> 操作時(shí)間: " + logMessage.OperationTime + " 操作人: " + logMessage.UserName + " \r\n"); strInfo.Append("2. 地址: " + logMessage.Url + " \r\n"); strInfo.Append("3. 類(lèi)名: " + logMessage.Class + " \r\n"); strInfo.Append("4. 主機(jī): " + logMessage.Host + " Ip : " + logMessage.Ip + " 瀏覽器: " + logMessage.Browser + " \r\n"); strInfo.Append("5. 異常: " + logMessage.ExceptionInfo + "\r\n"); //strInfo.Append("6. 來(lái)源: " + logMessage.ExceptionSource + "\r\n"); //strInfo.Append("7. 實(shí)例: " + logMessage.ExceptionRemark + "\r\n"); strInfo.Append("-----------------------------------------------------------------------------------------------------------------------------\r\n"); return strInfo.ToString(); } } }
創(chuàng)建日志類(lèi),代碼如下:
using log4net; using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace MVCCuetomerExcepFilterDemo.Util { /// <summary> /// 日志 /// </summary> public class Log { private ILog logger; public Log(ILog log) { this.logger = log; } public void Debug(object message) { this.logger.Debug(message); } public void Error(object message) { this.logger.Error(message); } public void Info(object message) { this.logger.Info(message); } public void Warn(object message) { this.logger.Warn(message); } } }
創(chuàng)建日志初始化類(lèi),代碼如下:
using log4net; using MVCCuetomerExcepFilterDemo.Models; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Web; namespace MVCCuetomerExcepFilterDemo.Util { /// <summary> /// 日志初始化 /// </summary> public class LogFactory { static LogFactory() { FileInfo configFile = new FileInfo(HttpContext.Current.Server.MapPath("/XmlConfig/log4net.config")); log4net.Config.XmlConfigurator.Configure(configFile); } public static Log GetLogger(Type type) { return new Log(LogManager.GetLogger(type)); } public static Log GetLogger(string str) { return new Log(LogManager.GetLogger(str)); } } }
最后添加log4net的配置文件:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/> </configSections> <log4net> <!--根配置--> <root> <!--日志級(jí)別:可選值: ERROR > WARN > INFO > DEBUG --> <level value="ERROR"/> <level value="WARN"/> <level value="INFO"/> <level value="DEBUG"/> <appender-ref ref="ErrorLog" /> <appender-ref ref="WarnLog" /> <appender-ref ref="InfoLog" /> <appender-ref ref="DebugLog" /> </root> <!-- 錯(cuò)誤 Error.log--> <appender name="ErrorLog" type="log4net.Appender.RollingFileAppender"> <!--目錄路徑,可以是相對(duì)路徑或絕對(duì)路徑--> <param name="File" value="D:\log"/> <!--文件名,按日期生成文件夾--> <param name="DatePattern" value="/yyyy-MM-dd/"Error.log""/> <!--追加到文件--> <appendToFile value="true"/> <!--創(chuàng)建日志文件的方式,可選值:Date[日期],文件大小[Size],混合[Composite]--> <rollingStyle value="Composite"/> <!--寫(xiě)到一個(gè)文件--> <staticLogFileName value="false"/> <!--單個(gè)文件大小。單位:KB|MB|GB--> <maximumFileSize value="200MB"/> <!--最多保留的文件數(shù),設(shè)為"-1"則不限--> <maxSizeRollBackups value="-1"/> <!--日志格式--> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%message"/> </layout> <filter type="log4net.Filter.LevelRangeFilter"> <param name="LevelMin" value="ERROR" /> <param name="LevelMax" value="ERROR" /> </filter> </appender> <!-- 警告 Warn.log--> <appender name="WarnLog" type="log4net.Appender.RollingFileAppender"> <!--目錄路徑,可以是相對(duì)路徑或絕對(duì)路徑--> <param name="File" value="D:\log"/> <!--文件名,按日期生成文件夾--> <param name="DatePattern" value="/yyyy-MM-dd/"Warn.log""/> <!--追加到文件--> <appendToFile value="true"/> <!--創(chuàng)建日志文件的方式,可選值:Date[日期],文件大小[Size],混合[Composite]--> <rollingStyle value="Composite"/> <!--寫(xiě)到一個(gè)文件--> <staticLogFileName value="false"/> <!--單個(gè)文件大小。單位:KB|MB|GB--> <maximumFileSize value="200MB"/> <!--最多保留的文件數(shù),設(shè)為"-1"則不限--> <maxSizeRollBackups value="-1"/> <!--日志格式--> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%message"/> </layout> <filter type="log4net.Filter.LevelRangeFilter"> <param name="LevelMin" value="WARN" /> <param name="LevelMax" value="WARN" /> </filter> </appender> <!-- 信息 Info.log--> <appender name="InfoLog" type="log4net.Appender.RollingFileAppender"> <!--目錄路徑,可以是相對(duì)路徑或絕對(duì)路徑--> <param name="File" value="D:\log"/> <!--文件名,按日期生成文件夾--> <param name="DatePattern" value="/yyyy-MM-dd/"Info.log""/> <!--追加到文件--> <appendToFile value="true"/> <!--創(chuàng)建日志文件的方式,可選值:Date[日期],文件大小[Size],混合[Composite]--> <rollingStyle value="Composite"/> <!--寫(xiě)到一個(gè)文件--> <staticLogFileName value="false"/> <!--單個(gè)文件大小。單位:KB|MB|GB--> <maximumFileSize value="200MB"/> <!--最多保留的文件數(shù),設(shè)為"-1"則不限--> <maxSizeRollBackups value="-1"/> <!--日志格式--> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%message"/> </layout> <filter type="log4net.Filter.LevelRangeFilter"> <param name="LevelMin" value="INFO" /> <param name="LevelMax" value="INFO" /> </filter> </appender> <!-- 調(diào)試 Debug.log--> <appender name="DebugLog" type="log4net.Appender.RollingFileAppender"> <!--目錄路徑,可以是相對(duì)路徑或絕對(duì)路徑--> <param name="File" value="D:\log"/> <!--文件名,按日期生成文件夾--> <param name="DatePattern" value="/yyyy-MM-dd/"Debug.log""/> <!--追加到文件--> <appendToFile value="true"/> <!--創(chuàng)建日志文件的方式,可選值:Date[日期],文件大小[Size],混合[Composite]--> <rollingStyle value="Composite"/> <!--寫(xiě)到一個(gè)文件--> <staticLogFileName value="false"/> <!--單個(gè)文件大小。單位:KB|MB|GB--> <maximumFileSize value="200MB"/> <!--最多保留的文件數(shù),設(shè)為"-1"則不限--> <maxSizeRollBackups value="-1"/> <!--日志格式--> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%message"/> </layout> <filter type="log4net.Filter.LevelRangeFilter"> <param name="LevelMin" value="DEBUG" /> <param name="LevelMax" value="DEBUG" /> </filter> </appender> </log4net> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> </configuration>
1.2、創(chuàng)建網(wǎng)絡(luò)工具類(lèi)
該工具幫助類(lèi)用于獲取IP、瀏覽器信息等內(nèi)容,代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Web; namespace MVCCuetomerExcepFilterDemo.Util { /// <summary> /// 網(wǎng)絡(luò)操作幫助類(lèi) /// </summary> public class NetHelper { #region Ip(獲取Ip) /// <summary> /// 獲取Ip /// </summary> public static string Ip { get { var result = string.Empty; if (HttpContext.Current != null) result = GetWebClientIp(); if (string.IsNullOrWhiteSpace(result)) result = GetLanIp(); return result; } } /// <summary> /// 獲取Web客戶端的Ip /// </summary> private static string GetWebClientIp() { var ip = GetWebRemoteIp(); foreach (var hostAddress in Dns.GetHostAddresses(ip)) { if (hostAddress.AddressFamily == AddressFamily.InterNetwork) return hostAddress.ToString(); } return string.Empty; } /// <summary> /// 獲取Web遠(yuǎn)程Ip /// </summary> private static string GetWebRemoteIp() { return HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] ?? HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]; } /// <summary> /// 獲取局域網(wǎng)IP /// </summary> private static string GetLanIp() { foreach (var hostAddress in Dns.GetHostAddresses(Dns.GetHostName())) { if (hostAddress.AddressFamily == AddressFamily.InterNetwork) return hostAddress.ToString(); } return string.Empty; } #endregion #region Host(獲取主機(jī)名) /// <summary> /// 獲取主機(jī)名 /// </summary> public static string Host { get { return HttpContext.Current == null ? Dns.GetHostName() : GetWebClientHostName(); } } /// <summary> /// 獲取Web客戶端主機(jī)名 /// </summary> private static string GetWebClientHostName() { if (!HttpContext.Current.Request.IsLocal) return string.Empty; var ip = GetWebRemoteIp(); var result = Dns.GetHostEntry(IPAddress.Parse(ip)).HostName; if (result == "localhost.localdomain") result = Dns.GetHostName(); return result; } #endregion #region Browser(獲取瀏覽器信息) /// <summary> /// 獲取瀏覽器信息 /// </summary> public static string Browser { get { if (HttpContext.Current == null) return string.Empty; var browser = HttpContext.Current.Request.Browser; return string.Format("{0} {1}", browser.Browser, browser.Version); } } #endregion } }
2、創(chuàng)建自定義異常類(lèi)
上篇文章中講過(guò)了,要?jiǎng)?chuàng)建自定義異常類(lèi),只需要?jiǎng)?chuàng)建一個(gè)繼承自HandleErrorAttribute的類(lèi),并重寫(xiě)OnException方法即可,自定義異常類(lèi)代碼如下:
using MVCCuetomerExcepFilterDemo.Models; using MVCCuetomerExcepFilterDemo.Util; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace MVCCuetomerExcepFilterDemo.Extension { /// <summary> /// 錯(cuò)誤日志(Controller發(fā)生異常時(shí)會(huì)執(zhí)行這里) /// </summary> public class ExceptionFilters : HandleErrorAttribute { public override void OnException(ExceptionContext filterContext) { WriteLog(filterContext); base.OnException(filterContext); filterContext.ExceptionHandled = true; filterContext.HttpContext.Response.StatusCode = 200; } /// <summary> /// 寫(xiě)入日志(log4net) /// </summary> /// <param name="context">提供使用</param> private void WriteLog(ExceptionContext context) { if (context == null) return; var log = LogFactory.GetLogger(context.Controller.ToString()); Exception Error = context.Exception; LogMessageEntity logMessage = new LogMessageEntity(); logMessage.OperationTime = DateTime.Now; logMessage.Url = HttpContext.Current.Request.RawUrl; logMessage.Class = context.Controller.ToString(); logMessage.Ip = NetHelper.Ip; logMessage.Host = NetHelper.Host; logMessage.Browser = NetHelper.Browser; // 這里為了方便直接用默認(rèn)的,真實(shí)案例中不能這樣寫(xiě) logMessage.UserName = "admin"; if (Error.InnerException == null) { logMessage.ExceptionInfo = Error.Message; } else { logMessage.ExceptionInfo = Error.InnerException.Message; } string strMessage = new LogFormat().ExceptionFormat(logMessage); log.Error(strMessage); } } }
3、創(chuàng)建控制器
控制器里面有一個(gè)LogOn登錄的方法,代碼如下:
using MVCCuetomerExcepFilterDemo.Extension; using MVCCuetomerExcepFilterDemo.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Security; namespace MVCCuetomerExcepFilterDemo.Controllers { public class AccountController : Controller { // GET: Account public ActionResult Index() { return View(); } /// <summary> /// 登錄成功顯示的視圖 /// </summary> /// <returns></returns> public ActionResult Welcome() { return View(); } /// <summary> /// 顯示登錄視圖 /// </summary> /// <returns></returns> public ActionResult LogOn() { LogOnViewModel model = new LogOnViewModel(); return View(model); } /// <summary> /// 處理用戶點(diǎn)擊登錄提交回發(fā)的表單 /// </summary> /// <param name="model"></param> /// <returns></returns> [HttpPost] [ExceptionFilters] public ActionResult LogOn(LogOnViewModel model) { try { string userName = model.UserName.Trim(); int password = Convert.ToInt32(model.Password); // 用戶名是admin,密碼是123456表示驗(yàn)證通過(guò) if (userName.Equals("admin")&&password.Equals(123456)) { // 判斷是否勾選了記住我 if (model.RememberMe) { //2880分鐘有效期的cookie FormsAuthentication.SetAuthCookie(model.UserName, true); } else { //會(huì)話cookie FormsAuthentication.SetAuthCookie(model.UserName, false); } // 跳轉(zhuǎn)到Account控制器的Welcome方法 return RedirectToAction("Welcome"); } else { return View(model); } } catch (Exception ex) { // 拋出異常 throw; } } } }
4、測(cè)試
在控制器代碼中,如果輸入的用戶名是admin,密碼是123456就通過(guò),然后顯示W(wǎng)elcome視圖,如果密碼轉(zhuǎn)換失敗的時(shí)候就記錄異常日志。
首先輸入正確的用戶名和密碼:
點(diǎn)擊登錄,然后顯示W(wǎng)elcome視圖:
這次輸入錯(cuò)誤的密碼:
再次點(diǎn)擊登錄,這時(shí)查看生成的日志:
在上面的代碼中,我們?cè)贚ogOn()方法上面使用了ExceptionFilters這個(gè)特性,這樣在控制器發(fā)生異常的時(shí)候就會(huì)進(jìn)入ExceptionFilters自定義異常類(lèi),然后記錄日志。但是這樣有一個(gè)問(wèn)題:使用這種方式要再每個(gè)action方法上面都添加該特性,如果action方法比較多,寫(xiě)起來(lái)也是很煩的,那么有沒(méi)有什么好的辦法呢?可以在控制器上面添加ExceptionFilters特性,這樣就是針對(duì)整個(gè)控制器里面的action了。那么還有沒(méi)有更簡(jiǎn)潔的辦法??碅pp_Start文件夾下面的FilterConfig定義:
using MVCCuetomerExcepFilterDemo.Extension; using System.Web; using System.Web.Mvc; namespace MVCCuetomerExcepFilterDemo { public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); } } }
可以看到這里是添加的HandleErrorAttribute類(lèi),如果換成自定義的異常類(lèi)會(huì)如何呢?修改后的FilterConfig文件如下:
using MVCCuetomerExcepFilterDemo.Extension; using System.Web; using System.Web.Mvc; namespace MVCCuetomerExcepFilterDemo { public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { //filters.Add(new HandleErrorAttribute()); // 使用自定義異常類(lèi) filters.Add(new ExceptionFilters()); } } }
AccountController控制器代碼修改如下:
using MVCCuetomerExcepFilterDemo.Extension; using MVCCuetomerExcepFilterDemo.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Security; namespace MVCCuetomerExcepFilterDemo.Controllers { public class AccountController : Controller { // GET: Account public ActionResult Index() { return View(); } /// <summary> /// 登錄成功顯示的視圖 /// </summary> /// <returns></returns> public ActionResult Welcome() { return View(); } /// <summary> /// 顯示登錄視圖 /// </summary> /// <returns></returns> public ActionResult LogOn() { LogOnViewModel model = new LogOnViewModel(); return View(model); } /// <summary> /// 處理用戶點(diǎn)擊登錄提交回發(fā)的表單 /// </summary> /// <param name="model"></param> /// <returns></returns> [HttpPost] // [ExceptionFilters] public ActionResult LogOn(LogOnViewModel model) { try { string userName = model.UserName.Trim(); int password = Convert.ToInt32(model.Password); // 用戶名是admin,密碼是123456表示驗(yàn)證通過(guò) if (userName.Equals("admin")&&password.Equals(123456)) { // 判斷是否勾選了記住我 if (model.RememberMe) { //2880分鐘有效期的cookie FormsAuthentication.SetAuthCookie(model.UserName, true); } else { //會(huì)話cookie FormsAuthentication.SetAuthCookie(model.UserName, false); } // 跳轉(zhuǎn)到Account控制器的Welcome方法 return RedirectToAction("Welcome"); } else { return View(model); } } catch (Exception ex) { // 拋出異常 throw; } } } }
這樣發(fā)生異常的時(shí)候就會(huì)自動(dòng)進(jìn)入自定義異常類(lèi)了,然后記錄日志。
到此這篇關(guān)于ASP.NET MVC自定義異常過(guò)濾器使用案例的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- ASP.NET?MVC自定義操作過(guò)濾器
- ASP.NET MVC自定義授權(quán)過(guò)濾器
- ASP.NET MVC自定義異常過(guò)濾器
- ASP.NET?MVC授權(quán)過(guò)濾器用法
- ASP.NET MVC異常過(guò)濾器用法
- ASP.NET MVC緩存過(guò)濾器用法
- ASP.NET Core MVC中過(guò)濾器工作原理介紹
- .NET6自定義WebAPI過(guò)濾器
- ASP.NET Core MVC 過(guò)濾器(Filter)
- ASP.NET Core MVC 過(guò)濾器的使用方法介紹
- ASP.NET MVC過(guò)濾器執(zhí)行順序介紹
相關(guān)文章
服務(wù)端拼接json數(shù)據(jù)格式的正確寫(xiě)法(Append方式)
我們通常會(huì)在服務(wù)端拼接json數(shù)據(jù)返回給客戶端,第一種AppendFormat的方式拼接,這種方法是不行的,正確的拼接方式是Append的方式2013-07-07解讀ASP.NET密碼強(qiáng)度驗(yàn)證代碼實(shí)例分享
這篇文章介紹了ASP.NET密碼強(qiáng)度驗(yàn)證代碼實(shí)例,有需要的朋友可以參考一下2013-10-10HttpWebRequest和HttpWebResponse用法小結(jié)
在每個(gè)系統(tǒng)出寫(xiě)入報(bào)告錯(cuò)誤代碼(找個(gè)合理的理由,比如系統(tǒng)免費(fèi)升級(jí)) -> 自家服務(wù)器接收并處理錯(cuò)誤報(bào)告 -> 反饋用戶(解決掉BUG就行,不要太聲揚(yáng))2011-09-09C# SetCursorPos簡(jiǎn)介及使用說(shuō)明
該函數(shù)把光標(biāo)移到屏幕的指定位置,如果新位置不在由ClipCursor函數(shù)設(shè)置的屏幕矩形區(qū)域之內(nèi),則系統(tǒng)自動(dòng)調(diào)整坐標(biāo),使得光標(biāo)在矩形之內(nèi)2012-12-12ASP.NET 數(shù)據(jù)訪問(wèn)類(lèi)
ASP.NET 數(shù)據(jù)訪問(wèn)類(lèi)...2006-08-08Asp.Net 動(dòng)態(tài)頁(yè)面轉(zhuǎn)靜態(tài)頁(yè)面主要代碼
關(guān)于在Asp.Net中動(dòng)態(tài)頁(yè)面轉(zhuǎn)靜態(tài)頁(yè)面的方法網(wǎng)上比較多。結(jié)合實(shí)際的需求,我在網(wǎng)上找了一些源代碼,并作修改?,F(xiàn)在把修改后的代碼以及說(shuō)明寫(xiě)一下。2009-12-12