ASP.NET Web API会话还是什么?

use*_*065 63 session asp.net-web-api

我需要在每个API请求中检索我需要检索的会话(或ASP.NET Web API中的任何内容)中存储一些信息.我们将有一个api IIS网站,并将通过主机头添加多个网站绑定.当任何请求进入时,例如api.xyz.com,将检查主机头并将该网站信息存储在会话中,该会话将在调用数据库时在每个后续api请求中使用.

我知道ASP.NET Web API中没有对会话的支持.有没有其他方法来处理这种情况?我在哪里可以存储可以在每个后续请求中检索的信息?

谢谢.

Sor*_*ren 98

在Global.asax中添加

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

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

试一试 ;)

  • +1如果您知道自己在做什么,我认为在某些特殊情况下使用Web Api中的Session是可以的. (13认同)
  • 我用过这个,我的一些页面变得很慢.最好测试请求是否是Web API:if(HttpContext.Current.Request.Url.AbsolutePath.StartsWith("/ api /")) (7认同)
  • 这工作了!非常感谢你!自从route.RouteHandler似乎不起作用以来,最高答案没有起作用,因为它与Web API中的类型不同。这个答案解决了这个问题。 (2认同)

Fil*_*p W 87

好吧,REST设计是无状态的.通过添加会话(或其他类似的东西),您可以使其成为有状态并且无法使用RESTful API.

RESTful服务的整体思想是每个资源都是唯一可寻址的,使用通用语法在超媒体链接中使用,并且每个HTTP请求应该自己携带足够的信息,以便其接收者处理它以与HTTP的无状态特性完全协调".

因此,无论您在此处尝试使用Web API,如果您希望拥有RESTful API,最有可能重新构建.

话虽如此,如果你仍然愿意沿着这条路走下去,那么有一种将会话添加到Web API的hacky方式,它已经由Imran发布了http://forums.asp.net/t/1780385.aspx/ 1

代码(虽然我不会真的推荐):

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后将HttpControllerHandler添加到您的API路由:

route.RouteHandler = new MyHttpControllerRouteHandler();
Run Code Online (Sandbox Code Playgroud)

  • 控制器很难以这种方式进行单元测试.我将在控制器构造函数中添加一个HttpContextBase(或HttpSessionStateBase)参数,并使用DI将其解析为应用程序的新HttpContextWrapper(HttpContext.Current).然后在单元测试中你可以嘲笑它. (6认同)
  • 我发现Web Api控制器非常有用,因为我可以将模型或视图模型设置为返回类型,并且它与我的javascript框架很好地配合,因此我不必在普通控制器中创建JsonResults.从这个意义上讲,它们不是真正的无状态REST API控制器,而是AJAX请求的更自然的端点,因此会话状态仍然是我想要的. (4认同)
  • 谢谢。很有帮助。我不反对 REST,但我想为每个 api 请求保存数据库行程。我们有与 api 域相关联的唯一 id,它发出一个请求,我需要将其传递给每个 api 请求的数据库调用。如果我不使用 session,我最终会为每个 api 请求重复相同的逻辑。顺便说一句,有没有一种方法可以覆盖类似于我们在 asp.net 中的 PreRequestHandlerExecute 并将数据存储在我想在每个 api 请求中检索的会话中? (2认同)

Dal*_*rzo 28

在WebApi 2中,您可以将其添加到global.asax

protected void Application_PostAuthorizeRequest() 
{
    System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
}
Run Code Online (Sandbox Code Playgroud)

然后您可以通过以下方式访问会话:

HttpContext.Current.Session
Run Code Online (Sandbox Code Playgroud)

  • 这如何为其他答案添加任何内容? (3认同)