首先來一個小的asp.net mvc 4的sample,代碼如下:
HomeController:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.SessionState; namespace MvcApplication2.Controllers { public class HomeController : Controller { // // GET: /Home/ public ActionResult Index() { return View(); } public ActionResult Test() { //這里為了測試執行了等待30秒的代碼,實際項目中會遇到 //很多類似需要很長時間的情況,比如調用webservice,或者處理很大數據 System.Threading.Thread.Sleep(30000); return View(); } } }
Global.asax:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Http; using System.Web.Mvc; using System.Web.Optimization; using System.Web.Routing; namespace MvcApplication2 { // Note: For instructions on enabling IIS6 or IIS7 classic mode, // visit http://go.microsoft.com/?LinkId=9394801 public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); } protected void Session_Start(object sender, EventArgs e) { } } }
Views中的代碼省略。
這么簡單的程序如果我們運行會發現一個問題:當我打開瀏覽器打開兩個tab,先在一個tab中打開/Home/Test,這時這個tab會等30秒才能呈現頁面,在這期間我在另一個tab中打開 /Home/Index,只有等第一個tab30秒過后,第二個tab才能呈現/Home/Index。而這種情況如果在實際項目中會非常影響性能,比如我們如果需要訪問webservice耗用大量時間獲取一些數據,同時我們又要通過ajax發送請求去處理一個查詢,這時如果按照上面的做法,只能等待webservice方法執行完畢后才能處理ajax請求。(Note:這種情況只有在同一個session下存在,如果上面的操作不打開兩個tab而是換成兩個瀏覽器,類似情況不會發生)
解決方案:
這里我們需要了解一下asp.net mvc 中的SessionState的作用:
在stackoverflow的一片文章記錄到:
Session state is designed so that only one request from a particular user/session occurs at a time. So if you have a page that has multiple AJAX callbacks happening at once they will be processed in serial fashion on the server. Going session-less means that they would execute in parallel.
大意就是Session state是用來將同一個session的請求按順序處理,如果需要並行處理則需要設置session-less。
如何設置SessionState呢?
mvc4中可以在controller上面加如下Attribute:(在System.Web.SessionState命名空間下)
[SessionState(SessionStateBehavior.ReadOnly)]
mvc3加如下Attribute:
[ControllerSessionState(SessionStateBehavior.ReadOnly)]
SessionStateBehavior四個選項中的區別:
- Default – Same as Required.
- Required – A full Session lock is taken, and requests to this controller are serialized. This is the normal MVC behavior.
- ReadOnly – A Session lock is not taken, and a controller can read values in Session, but it cannot modify the values in Session. Requests to this controller will be parallelized.
- Disabled – Session is unavailable within this controller, and attempts to use it will be met with an error. Requests to this controller will be parallelized
