如何在ASP.NET MVC中禁用会话状态?

77

我希望拥有一个非常轻量级的ASP.NET MVC网站,其中包括尽可能删除常规的HttpModules并禁用会话状态。然而,当我尝试这样做时,我遇到了以下错误:

SessionStateTempDataProvider需要启用SessionState。

我已在web.config中禁用了会话状态:

<sessionState mode="Off" />

我理解ASP.NET MVC在TempData中使用了会话状态,但我不需要/不想要TempData——我只想禁用会话状态。请帮忙!


不错的想法 - 我很感兴趣听听你在这方面是否遇到了其他问题,以及最终你能够轻量化多少。 - Michael Hart
在我实施了Steve的更改之后,我没有进行太多的实验,但仍然存在相当大的开销。我能够让ASP.NET运行得最快的方式是使用直接的IHttpHandler实现。有关更多信息,请参见我的答案:https://dev59.com/v3RB5IYBdhLWcg3wyqKo#510001 - Daniel Schaffer
26
这个问题在MVC 2中得到解决。我们修复了会话状态临时数据提供程序,现在只有在尝试读取/写入临时数据时才会抛出异常。 - Brad Wilson
布拉德:太棒了,好知道! - Daniel Schaffer
5个回答

48

你可以创建自己的ControllerFactory和DummyTempDataProvider。就像这样:

public class NoSessionControllerFactory : DefaultControllerFactory
{
  protected override IController GetControllerInstance(Type controllerType)
  {
    var controller = base.GetControllerInstance(controllerType);
    ((Controller) controller).TempDataProvider = new DummyTempDataProvider();
    return controller;
  }
}


public class DummyTempDataProvider : ITempDataProvider
{
  public IDictionary<string, object> LoadTempData(ControllerContext controllerContext)
  {
    return new Dictionary<string, object>();
  }

  public void SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
  {
  }
}

然后您只需要在应用程序启动时注册控制器工厂 - 比如,您可以在global.asax文件中执行此操作:

ControllerBuilder.Current.SetControllerFactory(new NoSessionControllerFactory());

1
谢谢...对我来说仍不是理想的(至少对我来说),但比在每个控制器上进行操作要好。 - Daniel Schaffer
10
抱歉,那听起来有点不太感激...但我并不是有意这样说的 :D - Daniel Schaffer
3
好的,没问题 :) 我知道这段代码可能看起来比你期望的要多一些,因为它似乎应该是可配置的东西。但 ASP.NET MVC 的一个重要优势就是可以通过提供替代实现的方式进行此类配置。这使得您可以在其中发挥很大的作用,以您希望的方式完成任务。总的来说,我认为这是一件“好事”。就我个人而言,我更喜欢键入 C# 代码而不是 xml ;) - Steve Willcock
4
在SaveTempData方法中,我添加了另一段代码:如果(values.Count != 0),则会抛出一个NotImplementedException异常,“无法设置临时数据,没有可用的会话状态”。http://tinyurl.com/mbegfr - BillRob
好主意 Bill,这将避免一些难以调试的状态缺失问题,我敢肯定 :) - Steve Willcock
显示剩余4条评论

9
我发现了一种方法,但我并不特别喜欢: 创建NoTempDataProvider
using System;
using System.Collections.Generic;
using System.Web.Mvc;

namespace Facebook.Sites.Desktop.Auth.Models
{
    public class NoTempDataProvider : ITempDataProvider
    {
        #region [ ITempDataProvider Members ]

        public IDictionary<String, Object> LoadTempData(ControllerContext controllerContext)
        {
            return new Dictionary<String, Object>();
        }

        public void SaveTempData(ControllerContext controllerContext, IDictionary<String, Object> values) { }

        #endregion
    }
}

手动在控制器中覆盖服务提供者

public class AuthController : Controller
{
    public AuthController()
    {
        this.TempDataProvider = new NoTempDataProvider();
    }
}

我非常希望能够通过配置完全实现这一点,但目前这种方法也可以。


4
是的,你的方式与我在答案中概述的方式相似 - 尽管如果你提供一个自定义的ControllerFactory来处理它,你就不必在每个控制器中手动覆盖TempDataProvider。 - Steve Willcock
6
您可以创建一个基础的控制器类,并在其构造函数中配置TempDataProvider。 - Brannon

6

1
根据Brad Wilson的说法,这个问题已经在MVC 2 Preview 1中得到了解决。请参阅herehere

0

现代解决方案:

在ASP.NET中,如果您不使用Session对象存储任何数据或处理任何Session事件(Session_OnStart或Session_OnEnd),则会禁用会话状态。

因此,不使用Session(或TempData)将禁用会话状态。

来源


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接