2012-07-13 31 views
48

Tôi cần lưu trữ một số thông tin trong phiên làm việc (hoặc trong bất kỳ thứ gì trong ASP.NET Web API) mà tôi cần truy xuất trong mọi yêu cầu API. Chúng tôi sẽ có một api IIS trang web và nhiều trang web ràng buộc sẽ được thêm vào thông qua máy chủ tiêu đề. Khi có bất kỳ yêu cầu nào, ví dụ api.xyz.com, tiêu đề máy chủ sẽ được kiểm tra và lưu trữ thông tin trang web đó trong phiên sẽ được sử dụng trong mỗi yêu cầu api tiếp theo khi thực hiện cuộc gọi đến cơ sở dữ liệu.Phiên ASP.NET Web API hay gì đó?

Tôi biết không có hỗ trợ cho phiên trong ASP.NET Web API. Có cách nào khác để xử lý loại tình huống này không? Tôi có thể lưu trữ thông tin có thể truy xuất trong mỗi yêu cầu tiếp theo ở đâu?

cảm ơn.

Trả lời

69

Vâng, REST theo thiết kế là không trạng thái. Bằng cách thêm phiên (hoặc bất kỳ thứ gì khác thuộc loại đó), bạn đang làm cho nó có trạng thái và đánh bại bất kỳ mục đích nào của việc có một API RESTful.

Toàn bộ ý tưởng của dịch vụ RESTful là mọi nguồn lực là địa chỉ duy nhất sử dụng một cú pháp phổ biến để sử dụng trong hypermedia các liên kếtmỗi yêu cầu HTTP nên mang theo đầy đủ thông tin của bản thân cho người nhận nó để xử lý nó được trong sự hòa hợp hoàn chỉnh với bản chất phi trạng thái của HTTP".

Vì vậy, bất cứ điều gì bạn đang cố gắng để làm với Web API ở đây, nên rất có thể được tái architectured nếu bạn muốn có một API RESTful.

với những gì đã nói, nếu bạn vẫn sẵn sàng để đi xuống con đường đó, có một cách hacky của việc thêm bị nén đến Web API, và nó được đăng bởi Imran đây http://forums.asp.net/t/1780385.aspx/1

Mã (mặc dù tôi sẽ không thực sự khuyên):

public class MyHttpControllerHandler 
    : HttpControllerHandler, IRequiresSessionState 
{ 
    public MyHttpControllerHandler(RouteData routeData): base(routeData) 
    { } 
} 

public class MyHttpControllerRouteHandler : HttpControllerRouteHandler 
{ 
    protected override IHttpHandler GetHttpHandler(RequestContext requestContext) 
    { 
     return new MyHttpControllerHandler(requestContext.RouteData); 
    } 
} 

public class ValuesController : ApiController 
{ 
    public string GET(string input) 
    { 
     var session = HttpContext.Current.Session; 
     if (session != null) 
     { 
      if (session["Time"] == null) 
      { 
       session["Time"] = DateTime.Now; 
      } 
      return "Session Time: " + session["Time"] + input; 
     } 
     return "Session is not availabe" + input; 
    } 
} 

và sau đó thêm HttpControllerHandler để định tuyến API của bạn:

route.RouteHandler = new MyHttpControllerRouteHandler(); 
+0

Cảm ơn. rất hữu ích. Tôi sẽ không chống lại REST nhưng tôi muốn lưu chuyến đi cơ sở dữ liệu cho mỗi yêu cầu api. Chúng tôi có id duy nhất liên quan đến tên miền api mà thực hiện một yêu cầu mà tôi cần phải đi qua để gọi cơ sở dữ liệu cho mỗi yêu cầu api. Nếu tôi không sử dụng phiên, tôi sẽ lặp lại cùng một logic cho mỗi yêu cầu api. BTW là có một cách tôi có thể ghi đè tương tự như PreRequestHandlerExecute chúng tôi có trong asp.net và lưu trữ dữ liệu trong phiên mà tôi muốn lấy trong mỗi yêu cầu api? – user1186065

+4

Bộ điều khiển sẽ khó kiểm tra đơn vị theo cách này. Tôi sẽ thêm một đối số HttpContextBase (hoặc HttpSessionStateBase) trong bộ tạo điều khiển và sử dụng DI để giải quyết nó thành HttpContextWrapper (HttpContext.Current) mới cho ứng dụng. Sau đó, trong các bài kiểm tra đơn vị bạn có thể thử nó. –

+0

Như @Filip đã nói, chúng ta không đi theo con đường này (thêm phiên vào Web API được cho là không quốc tịch). Nhưng cùng Filip có một bài viết hay về Caching Web API: http://goo.gl/2rnfI Tôi chia anh ta thành gitHub và thêm một vài chức năng vào mã nguồn, bây giờ nó hỗ trợ cache đầu ra riêng biệt cho người dùng đã đăng nhập : http://goo.gl/oW4hX LƯU Ý: Tôi vẫn đang cải thiện mã và kiểm tra mã cho bất kỳ vi phạm bảo mật có thể xảy ra nào. – Tohid

2

Bạn có thể sử dụng cookie nếu dữ liệu đủ nhỏ và không thể hiện mối quan ngại về bảo mật. Cách tiếp cận dựa trên HttpContext.Current tương tự sẽ hoạt động.

Yêu cầu và đáp ứng tiêu đề HTTP cũng có thể được sử dụng để chuyển thông tin giữa các cuộc gọi dịch vụ.

+0

Tôi biết điều này là cũ, nhưng có thể giúp bất cứ ai khác đọc về nội dung này. Có một giới hạn về việc sử dụng cookie với IE8/9 nếu bạn đang sử dụng XDomainRequest để thực hiện các yêu cầu ajax của CORS. Bạn có thể đọc thêm về nó [ở đây] (http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx) – elvin

79

trong Global.asax thêm

public override void Init() 
{ 
    this.PostAuthenticateRequest += MvcApplication_PostAuthenticateRequest; 
    base.Init(); 
} 

void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e) 
{ 
    System.Web.HttpContext.Current.SetSessionStateBehavior(
     SessionStateBehavior.Required); 
} 

cho nó một shot;)

+0

Điều này đã hiệu quả! Cảm ơn nhiều! Câu trả lời hàng đầu không hoạt động kể từ khi route.RouteHandler dường như không hoạt động vì nó không phải là cùng loại trong Web API. Câu trả lời này đã giải quyết được vấn đề. – Tikkes

+10

+1 Tôi nghĩ rằng bạn có thể sử dụng Session trong Web Api trong một số trường hợp đặc biệt nếu bạn biết mình đang làm gì. – nima

+6

Tôi đã sử dụng trang này và một số trang của tôi trở nên rất chậm. Tốt hơn nên kiểm tra xem yêu cầu có phải là một API Web hay không: nếu (HttpContext.Current.Request.Url.AbsolutePath.StartsWith ("/ api /")) – nima

20

Trong WebAPI 2 bạn có thể thêm video này vào global.asax

protected void Application_PostAuthorizeRequest() 
{ 
    System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required); 
} 

Sau đó, bạn có thể truy cập phiên qua:

HttpContext.Current.Session 
+3

Làm cách nào để thêm bất kỳ điều gì vào các câu trả lời khác? –

+0

@eddie_cat chỉ đơn giản là đặt, ông được đặt nó trong PostAuthorize. Tuy nhiên, để làm điều này tốt hơn, anh ta có thể chỉ ra điều đó và thêm kiểm tra có điều kiện nếu yêu cầu là một yêu cầu api như nima chỉ ra. – Suamere

1

Bây giờ trong năm 2017 với ASP.Net Core, bạn có thể làm điều đó như được giải thích ở đây.

Gói Microsoft.AspNetCore.Session cung cấp phần mềm trung gian để quản lý trạng thái phiên.

Introduction to session and application state in ASP.NET Core

Đã thử nghiệm trên một dự án làm việc