ASP.NET MVC持久化数据

时间:2012-06-07 02:32:26

标签: asp.net-mvc session-state persist tempdata

我正在使用ASP.NET MVC 4并且有一种情况是我在MasterController中保存了一些数据,因为我想在跨站点导航栏中预加载一些数据。

abstract class MasterController : Controller
{
    FakeObject MyData { get; set; }

    if (this.MyData == null)
    {
        this.MyData = // do something crazy and load lots of data
    }
}

每个控制器都继承自MasterController

class HomeController : MasterController
{
    ActionResults Index()
    {
        return View();
    }
}

问题在于,每次发回帖时,MyData都会被覆盖。 我正试图找到一种方法来存储这些数据,并在不使用SessionState的情况下在PostBack之间检索它。可以这样做吗?也许我对MasterController的使用不正确。

我尝试了以下操作,但它不起作用:(

TempData.Add("mydata", MyData);
TempData.Keep("mydata");

2 个答案:

答案 0 :(得分:1)

我不确定你if(String.IsNullOrEmpty...的使用位置(我认为你错过了一个包含成员;这不是有效的代码。

但是,我认为您可能需要考虑依赖注入和松散耦合,而不是在控制器中硬编码业务逻辑。这是两个建议。

选项1:依赖注入和TempData

public interface IFakeObjectFactory
{
      FakeObject Create();
}

public class FakeObjectFactory : IFakeObjectFactory
{
      public FakeObject Create()
      {
          // create FakeObject
      }
}

然后你的控制器看起来会更像这样:

public abstract class MasterController : Controller
{
    protected IFakeObjectFactory FakeObjectFactory { get; private set; }

    private FakeObject _myData;

    protected FakeObject EnsureMyData() 
    {
         if (_myData != null) return _myData;

          _myData = TempData["myData"] as FakeObject ?? FakeObjectFactory.Create();

          TempData["myData"] = _myData;
    }

    protected MasterController(IFakeObjectFactory fakeDataFactory)
    {
        FakeDataFactory = fakeDataFactory;
    }
}


public class HomeController : MasterController
{
    public HomeController(IFakeObjectFactory fakeObjectFactory)
      : base(fakeObjectFactory)
    { }

    ActionResults Index()
    {
        ViewBag.MyData = EnsureMyData();

        return View(); // you could also use MyData as the view model, rather than using ViewBag above. not sure what you need from here.
    }
}

现在,您可以使用Inversion of Control容器来创建控制器并为您注入依赖项(一些流行的IoC是Ninject和Autofac)。如果您觉得自己没有做好准备,可以随时在EnsureMyData方法中硬编码创建工厂实例,并删除HomeControllerMasterController中的构造函数参数

使用工厂界面和依赖注入的好处是,您可以与控制器分开创建,测试和维护工厂。如果需要,您也可以在将来交换实现。

选项2:使用静态只读字段

如果MyData不变,则另一个选项是,您可以将其设为MasterController的静态成员,而不是使用TempData

public abstract MasterController : Controller
{
    public static readonly FakeData MyData;

    static MasterController()
    {
       // Initialize MyData
    }
}

public HomeController : MasterController
{
    public ActionResult Index()
    {
        ViewBag.MyData = MyData;

        View(); // you could also use MyData as the view model, rather than using ViewBag above. not sure what you need from here.
    }
}

这种方法我不推荐,除非逻辑很简单,或者你只是不关心并想要快速和肮脏的东西。测试单例和静态方法是一个痛苦的对接。

答案 1 :(得分:1)

如果这基本上是静态数据,则可以使用内置缓存。

abstract class MasterController : Controller
{
    public MasterController() { if (Cache["Foo"] == null) Cache["Foo"] = Something; }
}

class HomeController : MasterController
{
    ActionResults Index()
    {
        return View(Cache["Foo"]);
    }
}