我們在asp.net 開發中已經封裝了最強大的HttpContext,我們可以在HttpContext中可以獲取到幾乎任何想獲取的東西,也可以在HttpContext寫入需要返回客戶端的信息。但是這些還遠遠不能滿足一些要求,比如在任何地方可以獲取到登錄用戶的信息等等。
之前獲取登錄用戶的信息基本上都是哪里用到就從session里獲取,這樣做的缺點很多就不一一說明了。
現在我們通過封裝一個WebWorkContext就可以隨用隨取,不用再次從session、數據庫或者緩存中獲取了。
1、首先新建類WebWorkContext
為了演示方便就不建立多個項目了,WebWorkContext就直接建在Mvc的Model中了。
1 public class WebWorkContext 2 { 3 4 /// <summary> 5 /// 判斷用戶是否登錄 6 /// </summary> 7 public bool IsLogin { get; set; } 8 9 /// <summary> 10 /// 用戶ID 11 /// </summary> 12 public int UserId { get; set; } 13 14 /// <summary> 15 /// 用戶名稱 16 /// </summary> 17 public string UserName { get; set; } 18 19 /// <summary> 20 /// 用戶郵箱 21 /// </summary> 22 public string UserEmail { get; set; } 23 24 /// <summary> 25 /// 是否是Get請求 26 /// </summary> 27 public bool IsGet { get; set; } 28 29 30 /// <summary> 31 /// 是否是Ajax請求 32 /// </summary> 33 public bool IsAjax { get; set; } 34 35 36 }
2、在Controller中新建類BaseController,並繼承Controller
剛剛提出剛才的需求就會有很多人想到用繼承了,確實是用繼承,不過后面也許會有你想不到的好處。
1 public class BaseController : Controller 2 { 3 /// <summary> 4 /// 創建上下文Context 5 /// </summary> 6 protected WebWorkContext WorkContext = new WebWorkContext(); 7 8 /// <summary> 9 /// 重寫Controller中的Initialize方法。在此方法中獲取用戶和其他的信息 10 /// </summary> 11 /// <param name="requestContext"></param> 12 protected override void Initialize(RequestContext requestContext) 13 { 14 base.Initialize(requestContext); 15 16 // 判斷用戶信息 17 if (!string.IsNullOrEmpty(Convert.ToString(Session["USERID"]))) 18 { 19 WorkContext.IsLogin = true; 20 WorkContext.UserId = Convert.ToInt32(Session["USERID"]); 21 WorkContext.UserName = Convert.ToString(Session["USERNAME"]); 22 WorkContext.UserEmail = Convert.ToString(Session["USEREMAIL"]); 23 } 24 25 // 判斷是否是Get請求 26 WorkContext.IsGet = requestContext.HttpContext.Request.HttpMethod == "GET"; 27 28 // 判斷是否是Ajax請求 29 WorkContext.IsAjax = requestContext.HttpContext.Request.IsAjaxRequest(); 30 31 } 32 33 }
3.1、在Controller中使用WebWorkContext
我們剛才所做的所有代碼都是為了方便使用一些封裝的信息,在Controller中使用WebWorkContext是最簡單的一種使用方式,只要Controller繼承新建的BaseController就可使用WebWorkContext中的任何東西。
1 public class HomeController : BaseController 2 { 3 public ActionResult Index() 4 { 5 var userId = WorkContext.UserId; 6 var userName = WorkContext.UserName; 7 return View(); 8 } 9 } 10 }
3.2、在View(cshtml)中使用WebWorkContext
重點來了,之前的幾步對於有一點工作經驗的都可以很簡單的完成,但是在View中使用自定義的類有很多童鞋還是不明白其中的道理。
第一首先要明白我們可以在View中使用比如Html/Ajax/Model之類的東西,是因為我們的頁面都繼承了一個類WebViewPage。
明白這個道理以后就很簡單了,我們只要讓我們的View繼承我們自定義的一個類,然后讓我們自定義的類繼承WebViewPage即可,然后我們就可以在我們自定義的類中做你想做的任何事了。
還要明白一個很重要的知識點,就是在哪更改View繼承類,當然微軟已經為我們擴展做好了,在每個Views文件夾下都有個web.config,找到pageBaseType,更改值為我們自定義類的即可。
3.2.1、新建自定義WebViewPage類(WebWorkContextWebViewPage)
1 public abstract class WebWorkContextWebViewPage<TModel> : System.Web.Mvc.WebViewPage<TModel> 2 { 3 public WebWorkContext WorkContext; 4 public sealed override void InitHelpers() 5 { 6 base.InitHelpers(); 7 BaseController baseController = ((this.ViewContext.Controller) as BaseController); 8 if (baseController != null) 9 { 10 WorkContext = baseController.WorkContext; 11 } 12 13 } 14 }
3.2.2、更改View的繼承,在Views文件夾中的web.config中找到pageBaseType,值更改為我們自定義的類就行了。
1 <system.web.webPages.razor> 2 <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> 3 <pages pageBaseType="WebWorkContextDemo.WebWorkContextWebViewPage"> 4 </pages> 5 </system.web.webPages.razor>
3.2.3、最后一步就是使用了,這個更簡單了直接調用即可。
這里需要注意的是,我們觀察代碼就知道,View中的WebWorkContext其實是獲取BaseController中的,所以使用WebWorkContext的View所對應的Controller必須繼承BaseController。
1 @{ 2 ViewBag.Title = "Home Page"; 3 } 4 5 用戶的郵箱是: @WorkContext.UserEmail<br /> 6 用戶名是: @WorkContext.UserName<br /> 7 8 @{ 9 var id = WorkContext.UserId; 10 }
4、【擴展】,在BLL和DAL中使用WebWorkContext
在Asp.net MVC中使用WebWorkContext已經結束了,但是有很多的時候在需要在其他的層也需要把一些重要的信息沉淀下去,當然最簡單的就是每次調用方法把需要的值通過方法參數傳遞至BLL和DAL。當然這樣不是最優的解決方案,如果一個類中的很多方法都需要一個參數,我們肯定不會每次都通過方法傳遞的,我們會通過設置屬性,或者通過一個方法設置值,然后在調用我們需要的方法。
這樣說就簡單了,我們可以在Action每次調用BLL方法之前先設置我們的WebWorkContext就可以了。
1 public class HomeController : BaseController 2 { 3 4 UserBLL bll = new UserBLL(); 5 6 /// <summary> 7 /// 重寫Initialize,給BLL設置WebWorkContext 8 /// </summary> 9 /// <param name="requestContext"></param> 10 protected override void Initialize(RequestContext requestContext) 11 { 12 base.Initialize(requestContext); 13 bll.WorkContext = WorkContext; 14 } 15 }
這樣我們就可以在BLL中任意的使用WebWorkContext了。
同樣的道理也可以設置DAL中的WebWorkContext。
BLL:
public class UserBLL : BaseBLL { UserDAL dal = new UserDAL(); public override WebWorkContext WorkContext { get { return base.WorkContext; } set { base.WorkContext = value; dal.WorkContext = value; } } public string GetBLLUserAge() { return WorkContext.UserId.ToString(); } }
DAL:
public class UserDAL : BaseDAL { public string GetUserAge() { return WorkContext.UserId.ToString(); } }
在BaseBLL和BaseDAL中都只有一段代碼,設置可以重寫的WebWorkContext。
public virtual WebWorkContext WorkContext { get; set; }
總結:這樣我們就可以幾乎在整個解決方案中使用WebWorkContext了,這樣每次使用的時候直接用就可以,不需要再次判斷獲取。
源碼Github:https://github.com/Emrys5/Asp.MVC-01-WebWorkContext
