[asp.net mvc 奇淫巧技] 01 - 封装上下文 - 在View中获取自定义的上下文

时间:2023-03-09 02:40:51
[asp.net mvc 奇淫巧技] 01 - 封装上下文  -  在View中获取自定义的上下文

  我们在asp.net 开发中已经封装了最强大的HttpContext,我们可以在HttpContext中可以获取到几乎任何想获取的东西,也可以在HttpContext写入需要返回客户端的信息。但是这些还远远不能满足一些要求,比如在任何地方可以获取到登录用户的信息等等。

  之前获取登录用户的信息基本上都是哪里用到就从session里获取,这样做的缺点很多就不一一说明了。

  现在我们通过封装一个WebWorkContext就可以随用随取,不用再次从session、数据库或者缓存中获取了。

1、首先新建类WebWorkContext

  为了演示方便就不建立多个项目了,WebWorkContext就直接建在Mvc的Model中了。

 public class WebWorkContext
{ /// <summary>
/// 判断用户是否登录
/// </summary>
public bool IsLogin { get; set; } /// <summary>
/// 用户ID
/// </summary>
public int UserId { get; set; } /// <summary>
/// 用户名称
/// </summary>
public string UserName { get; set; } /// <summary>
/// 用户邮箱
/// </summary>
public string UserEmail { get; set; } /// <summary>
/// 是否是Get请求
/// </summary>
public bool IsGet { get; set; } /// <summary>
/// 是否是Ajax请求
/// </summary>
public bool IsAjax { get; set; } }

2、在Controller中新建类BaseController,并继承Controller

  刚刚提出刚才的需求就会有很多人想到用继承了,确实是用继承,不过后面也许会有你想不到的好处。

  public class BaseController : Controller
{
/// <summary>
/// 创建上下文Context
/// </summary>
protected WebWorkContext WorkContext = new WebWorkContext(); /// <summary>
/// 重写Controller中的Initialize方法。在此方法中获取用户和其他的信息
/// </summary>
/// <param name="requestContext"></param>
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext); // 判断用户信息
if (!string.IsNullOrEmpty(Convert.ToString(Session["USERID"])))
{
WorkContext.IsLogin = true;
WorkContext.UserId = Convert.ToInt32(Session["USERID"]);
WorkContext.UserName = Convert.ToString(Session["USERNAME"]);
WorkContext.UserEmail = Convert.ToString(Session["USEREMAIL"]);
} // 判断是否是Get请求
WorkContext.IsGet = requestContext.HttpContext.Request.HttpMethod == "GET"; // 判断是否是Ajax请求
WorkContext.IsAjax = requestContext.HttpContext.Request.IsAjaxRequest(); } }

3.1、在Controller中使用WebWorkContext

  我们刚才所做的所有代码都是为了方便使用一些封装的信息,在Controller中使用WebWorkContext是最简单的一种使用方式,只要Controller继承新建的BaseController就可使用WebWorkContext中的任何东西。

  public class HomeController : BaseController
{
public ActionResult Index()
{
var userId = WorkContext.UserId;
var userName = WorkContext.UserName;
return View();
}
}
}

3.2、在View(cshtml)中使用WebWorkContext

  重点来了,之前的几步对于有一点工作经验的都可以很简单的完成,但是在View中使用自定义的类有很多童鞋还是不明白其中的道理。

  第一首先要明白我们可以在View中使用比如Html/Ajax/Model之类的东西,是因为我们的页面都继承了一个类WebViewPage。

  明白这个道理以后就很简单了,我们只要让我们的View继承我们自定义的一个类,然后让我们自定义的类继承WebViewPage即可,然后我们就可以在我们自定义的类中做你想做的任何事了。

  还要明白一个很重要的知识点,就是在哪更改View继承类,当然微软已经为我们扩展做好了,在每个Views文件夹下都有个web.config,找到pageBaseType,更改值为我们自定义类的即可。

3.2.1、新建自定义WebViewPage类(WebWorkContextWebViewPage)

  public abstract class WebWorkContextWebViewPage<TModel> : System.Web.Mvc.WebViewPage<TModel>
{
public WebWorkContext WorkContext;
public sealed override void InitHelpers()
{
base.InitHelpers();
BaseController baseController = ((this.ViewContext.Controller) as BaseController);
if (baseController != null)
{
WorkContext = baseController.WorkContext;
} }
}

3.2.2、更改View的继承,在Views文件夹中的web.config中找到pageBaseType,值更改为我们自定义的类就行了。

  <system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="WebWorkContextDemo.WebWorkContextWebViewPage">
</pages>
</system.web.webPages.razor>

3.2.3、最后一步就是使用了,这个更简单了直接调用即可。

  这里需要注意的是,我们观察代码就知道,View中的WebWorkContext其实是获取BaseController中的,所以使用WebWorkContext的View所对应的Controller必须继承BaseController

 @{
ViewBag.Title = "Home Page";
} 用户的邮箱是: @WorkContext.UserEmail<br />
用户名是: @WorkContext.UserName<br /> @{
var id = WorkContext.UserId;
}

4、【扩展】,在BLL和DAL中使用WebWorkContext

  在Asp.net MVC中使用WebWorkContext已经结束了,但是有很多的时候在需要在其他的层也需要把一些重要的信息沉淀下去,当然最简单的就是每次调用方法把需要的值通过方法参数传递至BLL和DAL。当然这样不是最优的解决方案,如果一个类中的很多方法都需要一个参数,我们肯定不会每次都通过方法传递的,我们会通过设置属性,或者通过一个方法设置值,然后在调用我们需要的方法。

  这样说就简单了,我们可以在Action每次调用BLL方法之前先设置我们的WebWorkContext就可以了。

  public class HomeController : BaseController
{ UserBLL bll = new UserBLL(); /// <summary>
/// 重写Initialize,给BLL设置WebWorkContext
/// </summary>
/// <param name="requestContext"></param>
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
    bll.WorkContext = WorkContext;
}
}

  这样我们就可以在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

系列课程