asp.net-mvc - 获取另一个 Controller Action 的 ActionResult?

标签 asp.net-mvc caching view controller httpcontext

我想将项目存储在应用程序缓存中,以便从主布局 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/

相关文章:

android - 我如何将谷歌纸板立体 View 更改为单 View

Android 屏幕方向已更改,不保存以编程方式添加的 TextView

asp.net-mvc - 如何通过 MVCSiteMap 使用隐式本地化?

javascript - 如何在 ASp.NET mvc 中使用 Jquery 将数组绑定(bind)到嵌套字段

asp.net-mvc - 是否可以在 mvc 中将 Controller 名称映射到另一个名称

javascript - jQuery 选择器缓存问题

python - 在 django 中需要帮助与 memcached 和 friend 一起进行中级/高级缓存

android - react native 图像缓存 Android

c# - MVC 表单无法发布对象列表

c# - 在 ASP.NET MVC 中使用分部 View