2015-04-02 60 views
0

我正在創建一些需要進行會話感知的WEB API 2控制器。加入如何在特定控制器上實現會話感知的WEB API?

/// <summary> 
/// Application_s the post authorize request. 
/// </summary> 
protected void Application_PostAuthorizeRequest() 
{ 
    HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required); 
} 

我已經以前做過但是我們在已經高度優化網站的其他業務關鍵部分的解決方案API控制器,並返回大約500毫秒的反應,如果這個始終開啓它上升到2秒。這些控制器不需要會話感知。

我們只需要給出會話訪問某些控制器,我讀過這篇文章http://www.codeproject.com/Tips/513522/Providing-session-state-in-ASP-NET-WebAPI和在想,如果有可能,以添加會話感知不同的路線,但有映射路由時沒有RouteHandler財產。

有沒有人有任何想法?

回答

1

我想出了一個解決方案。我在我有的global.asax.cs的路由註冊期間加入第二路線如

 config.Routes.MapHttpRoute(
      name: "DefaultSessionApi", 
      routeTemplate: "sessionapi/{controller}/{id}", 
      defaults: new { id = RouteParameter.Optional }); 

然後

/// <summary> 
    /// Application_s the post authorize request. 
    /// </summary> 
    protected void Application_PostAuthorizeRequest() 
    { 
     if (HttpContext.Current.Request.FilePath.StartsWith("/sessionapi")) 
     { 
      HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required); 
     } 
    } 

這允許任何控制器能與來自會話的認識或不請求客戶因此解決了我的問題。

我的解決方案是一個整潔的配置常量等,但上面的代碼是例子。

+0

我不在Mono中工作。 – Andrus 2016-08-15 19:39:31

2

請記住,使用SessionStateBehavior.Required會產生相當大的影響,只有部分路由實際上需要對會話進行寫入訪問。最糟糕的情況是每個用戶只能處理一個請求,因爲會話必須被鎖定。

這就是說,有一種方法可以根據路線以不同的方式處理會話。

您可以使用IHttpRoute.DataTokens爲您的路線添加自定義字段。 我創建了一個小的擴展類設置SessionStateBehavior爲每個路由,分別:

public static class SessionHelper 
{ 
    private static SessionStateBehavior GetSessionStateBehavior(IDictionary<string, object> dataTokens) 
    { 
    return dataTokens.ContainsKey("SessionStateBehavior") ? (SessionStateBehavior)dataTokens["SessionStateBehavior"] : SessionStateBehavior.Default; 
    } 

    public static SessionStateBehavior GetSessionStateBehavior(this IHttpRoute route) 
    { 
    return GetSessionStateBehavior(route.DataTokens); 
    } 

    public static SessionStateBehavior GetSessionStateBehavior(this RouteData routeData) 
    { 
    return GetSessionStateBehavior(routeData.DataTokens); 
    } 

    public static void SetSessionStateBehavior(this IHttpRoute route, SessionStateBehavior behavior) 
    { 
    route.DataTokens["SessionStateBehavior"] = behavior; 
    } 

    public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate, object defaults, SessionStateBehavior behavior) 
    { 
    return MapHttpRoute(routes, name, routeTemplate, defaults, null, behavior); 
    } 

    public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate, object defaults, object constraints, SessionStateBehavior behavior) 
    { 
    var route = routes.CreateRoute(routeTemplate, defaults, constraints); 
    SetSessionStateBehavior(route, behavior); 
    routes.Add(name, route); 

    return route; 
    } 
} 

當設置你的路線,你可以使用擴展定義一個特定的會話狀態行爲:

config.Routes.MapHttpRoute(
    "DefaultSessionApi", 
    "api/{controller}/{id}", 
    new { id = RouteParameter.Optional }, 
    SessionStateBehavior.ReadOnly); 

config.Routes.MapHttpRoute(
    "WriteStuffToSession", 
    "api/writestufftosession", 
    null, 
    SessionStateBehavior.Required); 

然後,在PostAuthorizeRequest事件中,可以解析您的路由並相應地設置SessionStateBehavior:

protected void Application_PostAuthorizeRequest() 
{ 
    var context = new HttpContextWrapper(HttpContext.Current); 
    var path = context.Request.AppRelativeCurrentExecutionFilePath; 
    if (path == null || !path.StartsWith("~/api")) 
    { 
    return; 
    } 

    var routeData = RouteTable.Routes.GetRouteData(context); 
    if (routeData != null) 
    { 
    context.SetSessionStateBehavior(routeData.GetSessionStateBehavior()); 
    } 
} 
+0

感謝您的答案,但我的解決方案正在完美工作。只有對sessionapi路由的API調用需要會話,因爲有2個路由配置,可以調用其中一個,並且可以從調用腳本輕鬆切換。 – 2016-01-12 10:12:12

+0

是的,如果您的解決方案使用特定的路由模板,則授予api控制器完全訪問會話的權限。我只想指出,完全寫訪問可能並不總是需要的,因爲ASP.Net專門鎖定會話:https://msdn.microsoft.com/en-us/library/ms178581.aspx 「但是,如果兩對同一個會話發出併發請求,第一個請求獲得會話信息的獨佔訪問權限,第二個請求僅在第一個請求完成後才執行。「 – 2016-01-13 11:17:22

+1

實際上,您可以爲每個會話狀態行爲創建路由模板,例如」/ readonlysessionapi/....「,它也可以工作。 但是,您真的希望客戶端必須關心您的會話行爲?假設您更改服務器端代碼,並且現在需要對會話進行寫入訪問,則必須更新所有客戶端,因爲路由更改。 – 2016-01-13 11:24:37