我想将项目存储在应用程序缓存中,以便从主布局 View 中延迟加载。
我还希望能够使缓存失效,所以如果它无效,下次请求项目集合时,它会重新加载到该缓存位置。
这是我实现的:
在 Controller 中:
protected IEnumerable<Slide> CachedSlides
{
get { return HttpContext.Application[SlidesCacheKey] as IEnumerable<Slide>; }
set { HttpContext.Application[SlidesCacheKey] = value; }
}
private void ClearSlides()
{
CachedSlides = null;
}
[AllowAnonymous]
public IEnumerable<Slider> GetSlides()
{
if (CachedSlides == null)
CachedSlides = Context.Slides.OrderBy(p => p.SortOrder).ToArray();
return CachedSlides;
}
我的 View (最好在“a” View 中说,我希望能够从每个 View 加载它):
@{
var sliderController = new LevEl.Controllers.Admin.SliderController().
var sliderModel = sliderController.GetSlides();
}
它会抛出异常,因为当我在 View 中初始化 Controller 时,HttpContext
属性返回 null(这会导致 NullReferenceException
)。
也欢迎任何其他方式来实现这一点。
最佳答案
首先,您可能要考虑使用 Cache 而不是 Application 字典,特别是因为您的缓存数据会在某个时候过期。看看this question
此外,请考虑 Controller 方法是否仅由 View 使用,因为 MVC 将公开 Controller 中的所有公共(public)方法。如果您不希望使用 URL 自由访问此方法,请设置 [NonAction]
attribute .
关于您的错误,一种快速修复方法是在 Controller 的 CachedSlides 属性的实现中通过 System.Web.HttpContext.Current
访问 Application 对象。
您还可以在 View 中创建 SliderController 的新实例时设置 ControllerContext。这样, Controller 中的 HttpContext 在访问 CachedSlides 属性时不会返回 null:
@{
var sliderController = new LevEl.Controllers.Admin.SliderController();
sliderController.ControllerContext = new ControllerContext(ViewContext.RequestContext, sliderController);
var sliderModel = sliderController.GetSlides();
}
如果拥有一个处理所有这些 View 的基 Controller 类对您来说有意义,那么获取 Controller 会更清晰。您只需要将 ViewContext.Controller
实例转换为该基 Controller 类:
var sliderController = ViewContext.Controller as BaseSlideController;
var sliderModel = sliderController.GetSlides();
但是,所有这些方法都需要您将那段代码添加到每个 View 。您可以考虑为所有需要访问幻灯片集合的 View 创建一个基类:
public abstract class SlidesEnabledView<T> : WebViewPage<T>
{
private IEnumerable<Slide> _slides;
protected IEnumerable<Slide> Slides
{
get
{
if(_slides == null)
{
var sliderController = ViewContext.Controller as BaseSlideController;
_slides = sliderController.GetSlides();
}
return _slides;
}
}
}
然后你将@inherits标签添加到你的 View 中,因此它们继承 self 们刚刚创建的基类(当使用@inherits时,你不能同时使用@model,所以在@inherits中你将绑定(bind)通用基础 View 类型是具体模型类型)。这将允许您使用基 SlidesEnabledView
View 类中定义的属性。假设 SlidesEnabledView 的命名空间是 Level.ViewClasses.Admin,这看起来像:
@inherits Level.ViewClasses.Admin.SlidesEnabledView<SomeViewModelClass>
Number of Slides: @Slides.Count()
最后,如果您通过站点使用 DI 并且配置了 DependencyResolver,那么您可以考虑将获取幻灯片的逻辑移动到它自己的类和接口(interface)中,例如 ISlidesProvider
和 CachedSlideProvider
。然后,您可以在抽象 View 类中使用属性注入(inject)来获取将在 Slides 属性中使用的 ISlidesProvider 实例:
public interface ISlidesProvider
{
IEnumerable<Slide> GetSlides();
}
public class CachedSlideProvider : ISlidesProvider
{
//you will need a constructor that takes the "Context" object, which will be injected into this class
public IEnumerable<Slide> GetSlides()
{
if (CachedSlides == null)
CachedSlides = Context.Slides.OrderBy(p => p.SortOrder).ToArray();
return CachedSlides;
}
private IEnumerable<Slide> CachedSlides
{
get { return System.Web.HttpRuntime.Cache[SlidesCacheKey] as IEnumerable<Slide>; }
set { System.Web.HttpRuntime.Cache[SlidesCacheKey] = value; }
}
}
public abstract class SlidesEnabledView<T> : WebViewPage<T>
{
private IEnumerable<Slide> _slides;
protected IEnumerable<Slide> Slides
{
get
{
if(_slides == null)
{
_slides = this.SlidesProvider.GetSlides();
}
return _slides;
}
}
//This property will be set by your DI container
//You have configured ISlidesProvider to be resolved as CachedSlidesProvider in the DI container
//You have also implemented and registered an MVC DependencyResolver that uses your DI container
//For example, using Microsoft Unity you could set this attribute
[Dependency]
public ISlidesProvider SlidesProvider { get; set; }
}
当您使用无参数构造函数创建 Controller 实例时,您可能没有在站点上使用 DI。因此,仅仅为了解决这个特定问题,这个 DI 选项可能有点矫枉过正。
关于asp.net-mvc - 获取另一个 Controller Action 的 ActionResult?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13899019/