获取的ActionResult的另一个控制器动作? [英] Get ActionResult of another controller-action?

查看:142
本文介绍了获取的ActionResult的另一个控制器动作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要存储在应用程序缓存中的项目因此它的延迟加载从主布局视图。

I want to store items in the application cache so it's lazy loaded from the main layout view.

我也希望能够缓存失效,因此,如果它是在请求的项目收集无效,接下来的时间,它的重新加载到高速缓存位置。

I also want to be able to invalidate the cache, so if it's invalid, next time when the items-collection is requested, it's reloaded to that cache location.

下面是我已经实现了:

在控制器:

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;
}

我的视图(还好说'一'的看法,我希望能够从每个视图加载它):

I the view (better said in 'a' view, I want to be able to load it from every view):

@{
  var sliderController = new LevEl.Controllers.Admin.SliderController().  
  var sliderModel = sliderController.GetSlides();
}

,因为当我在视图初始化控制器,的HttpContext 属性返回null(这导致了的NullReferenceException )。

It throws an exception because when I initialize the controller in the view, the HttpContext property returns null (which leads to a NullReferenceException).

任何其他方式来实现,这也将受到欢迎。

Any other ways to implement this will also be welcome.

推荐答案

首先,你可能要考虑使用缓存,而不是应用字典,特别是因为你的缓存数据会在某个时候过期。看看

First of all, you may want to consider using the Cache instead of the Application dictionary, specially since your cached data will expire at some point. Take a look at this question

另外,还要考虑如果控制器方法只是在视图中使用,因为MVC会暴露在控制器的所有公共方法。如果您想鸵鸟政策此方法使用URL然后设置 [无为] 属性

Also, consider if the controller method will just be used by the views because MVC will expose all public methods in the controller. If you don´t want this method to be freely accessed using an URL then set the [NonAction] attribute.

关于你的错误,一个快速的方法来解决这个问题将通过 System.Web.HttpContext.Current 在控制器的CachedSlides属性的实现来访问应用程序对象

Regarding your error, a quick way to fix it will be accessing the Application object through System.Web.HttpContext.Current in the implementation of the CachedSlides property of the controller.

您也可以在视图中创建SliderController的新实例时设置的ControllerContext。通过这种方式,访问CachedSlides属性时在控制器中的HttpContext不会返回空

You could also set the ControllerContext when creating a new instance of the SliderController in the view. That way, the HttpContext in the controller will not return null when accessing the CachedSlides property:

@{
    var sliderController = new LevEl.Controllers.Admin.SliderController();
    sliderController.ControllerContext = new ControllerContext(ViewContext.RequestContext, sliderController);
    var sliderModel = sliderController.GetSlides();
}

如果是有意义的,你有一个基本的控制器类,将处理所有这些意见,然后让该控制器将清洁剂。你只需要转换 ViewContext.Controller 实例作为基础类:

If it makes sense for you to have a base controller class that will handle all of these views, then getting the controller will be cleaner. You would just need to cast the ViewContext.Controller instance as that base controller class:

var sliderController = ViewContext.Controller as BaseSlideController;
var sliderModel = sliderController.GetSlides();

然而,所有这些方法都需要你的那件code的添加到每个视图。您可以考虑为您的所有意见,这将需要访问幻灯片集合的基类:

However all of those approaches will require you to add that piece of code to every view. You may consider having a base class for all of your views that will require accessing the Slide collection:

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标记添加到您的看法,让他们从我们刚才创建(当使用@inherits,则不能同时使用@model,所以在@inherits你会界基类继承通用基础视图类型TI的具体型号)。这将允许您使用在基本 SlidesEnabledView 视图类中定义的属性。假设命名空间SlidesEnabledView是Level.ViewClasses.Admin,这将是这样的:

You will then add the @inherits tag to your views, so they inherit from the base class we have just created (When the @inherits is used, you cannot also use the @model, so in the @inherits you will bound the generic base view type ti a concrete model type). This will allow you to use the property defined in the base SlidesEnabledView view class. Assuming the namespace for SlidesEnabledView is Level.ViewClasses.Admin, this would look like:

@inherits Level.ViewClasses.Admin.SlidesEnabledView<SomeViewModelClass> 

Number of Slides: @Slides.Count() 

最后,如果你是通过你的网站使用DI和你配置一个DependencyResolver,那么你可以考虑把逻辑得到滑入自己的类和接口如 ISlidesProvider CachedSlideProvider 。然后,您可以使用属性注入抽象视图类用于获取将在幻灯片财产使用ISlidesProvider的一个实例:

Finally, if you are using DI through your site and you have configured a DependencyResolver, then you could consider moving the logic for getting the slides into its own class and interface like ISlidesProvider and CachedSlideProvider. You could then use property injection in the abstract view class for getting an instance of ISlidesProvider that will be used in the Slides property:

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; }        
}

当你创建一个使用参数的构造函数控制器的一个实例,可能是你没有在网站上使用DI。所以这个DI选项可能有点矫枉过正只是为了解决这方面的问题。

As you were creating an instance of the controller using a parameterless constructor, probably you are not using DI on your site. So this DI option may be a bit of overkill just for resolving this particular problem.

这篇关于获取的ActionResult的另一个控制器动作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆