3

メインのレイアウトビューから遅延ロードされるように、アイテムをアプリケーションキャッシュに保存したいと思います。

また、キャッシュを無効にできるようにしたいので、無効な場合は、次にitems-collectionが要求されたときに、そのキャッシュの場所に再ロードされます。

これが私が実装したものです:

コントローラ内:

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

私はビューです(「a」ビューで言うと、すべてのビューからロードできるようにしたいと思います):

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

HttpContextビューでコントローラーを初期化すると、プロパティがnullを返すため(これはになります) 、例外がスローされますNullReferenceException

これを実装する他の方法も歓迎されます。

4

2 に答える 2

4

まず、アプリケーションディクショナリの代わりにキャッシュの使用を検討することをお勧めします。特に、キャッシュされたデータはある時点で期限切れになるためです。この質問を見てください

また、MVCはコントローラー内のすべてのパブリックメソッドを公開するため、コントローラーメソッドがビューによってのみ使用されるかどうかを検討してください。URLを使用してこのメ​​ソッドに自由にアクセスしたくない場合は、[NonAction] 属性を設定します。

System.Web.HttpContext.Currentエラーに関しては、コントローラーのCachedSlidesプロパティの実装を通じて、アプリケーションオブジェクトにアクセスすることでエラーを修正する簡単な方法があります。

ビューにSliderControllerの新しいインスタンスを作成するときに、ControllerContextを設定することもできます。そうすれば、コントローラーのHttpContextは、CachedSlidesプロパティにアクセスするときにnullを返しません。

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

これらすべてのビューを処理する基本コントローラークラスを用意することが理にかなっている場合は、コントローラーの取得がよりクリーンになります。ViewContext.Controllerインスタンスをその基本コントローラークラスとしてキャストする必要があります。

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

ただし、これらのアプローチはすべて、そのコードをすべてのビューに追加する必要があります。スライドコレクションにアクセスする必要があるすべてのビューの基本クラスを用意することを検討してください。

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であるとすると、これは次のようになります。

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

Number of Slides: @Slides.Count() 

ISlidesProvider最後に、サイトでDIを使用していて、DependencyResolverを構成している場合は、スライドを取得するためのロジックをとのような独自のクラスとインターフェイスに移動することを検討できますCachedSlideProvider。次に、抽象ビュークラスでプロパティインジェクションを使用して、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; }        
}

パラメーターなしのコンストラクターを使用してコントローラーのインスタンスを作成していたため、サイトでDIを使用していない可能性があります。したがって、このDIオプションは、この特定の問題を解決するためだけに少しやり過ぎかもしれません。

于 2012-12-16T13:16:36.360 に答える
1

GetSlidesメソッドを次のように定義できますBaseController

public class BaseController : Controller
{
    protected IEnumerable<Slide> CachedSlides
    {
        get { return HttpContext.Application[SlidesCacheKey] as IEnumerable<Slide>; }
        set { HttpContext.Application[SlidesCacheKey] = value; }
    }

    private void ClearSlides()
    {
        CachedSlides = null;
    }

    public IEnumerable<Slide> GetSlides()
    {
        if (CachedSlides == null)
            CachedSlides = Context.Slides.OrderBy(p => p.SortOrder).ToArray();
        return CachedSlides;
    }
}

したがって、すべてのコントローラーは から継承する必要がありますBaseController

ビューでは、これを行うことができます:

@{
    var baseController = (BaseController)ViewContext.Controller;
    var slides = baseController.GetSlides();
}
于 2012-12-16T11:58:55.330 に答える