2016-12-12 4 views
1

Ich habe ein Kundensichtmodell, das Dropdown-Listen zur Auswahl von Land, Bereich und Sprache hat. Ich benutze ViewComponent, um die notwendigen Daten für die Dropdownlisten zu laden, und es funktioniert wie ein Charme. Mein Problem ist, dass wenn mehrere Client-Modelle auf der Seite sind, ich mehrere Aufrufe an die externe API mache, um die gleichen Daten zu erhalten. Ich habe versucht, den Component.InvokeAsync-Teil in einen Cache-Tag-Helper zu legen, aber er behält auch die Elemente, die beim ersten Aufruf benennt und die Modellbindung durcheinander bringt. Gibt es eine Möglichkeit, mehrere Anrufe für dieselben Daten zu vermeiden?Wiederholen von ViewComponent-Daten

Hier ist, wie der Code aussieht. Es ist nichts Besonderes. Die Ansichten binden nur die Eigenschaften und dort ist nichts Besonderes.

[ViewComponent(Name = "LocationSelector")] 
public class LocationSelector : ViewComponent 
{ 
    private readonly ILocationService locationsService; 

    public LocationSelector(ILocationService locationService) 
    { 
     this.locationsService = locationService; 
    } 

    public async Task<IViewComponentResult> InvokeAsync() 
    { 
     var locationManager = new LocationSelectorViewModel(); 
     locationManager.Areas = await this.locationsService.GetAreas(); 
     locationManager.Countries = await this.locationsService.GetCountries(); 
     return View("Default", locationManager); 
    } 
} 

Und die Komponente wird innerhalb des Kundenmodells so genannt. Das Problem ist, dass ich mehrere Kunden auf meiner Seite habe und sie alle Anfragen an den Service für genau die gleichen Daten stellen.

@await Component.InvokeAsync(nameof(LocationSelector)) 
+0

http://sscce.org/ – Yoda

Antwort

1

Sie sollten die Daten zwischenspeichern. Sie können IMemoryCache implementation verwenden. Ich bevorzuge es, meine eigene Abstraktionsschicht zu erstellen, die ich verwenden würde, wo immer ich sie brauche.

public interface ICache 
{ 
    T Get<T>(string key, Func<T> updateExpression = null, int cacheDuration=0);  
} 
public class InMemoryCache : ICache 
{ 
    readonly IMemoryCache memoryCache; 
    public InMemoryCache(IMemoryCache memoryCache) 
    { 
     this.memoryCache = memoryCache; 
    } 
    public T Get<T>(string key, Func<T> updateExpression = null,int cacheDuration=0) 
    { 
     object result; 
     if (memoryCache.TryGetValue(key,out result)) 
     { 
      return (T) result; 
     } 
     else 
     { 
      if (updateExpression == null) 
      { 
       return default(T); 
      } 
      var data = updateExpression(); 
      if (data != null) 
      { 
       var options = new MemoryCacheEntryOptions 
       { 
        AbsoluteExpiration = DateTime.Now.AddSeconds(cacheDuration) 
       }; 
       this.memoryCache.Set(key, data, options); 
       return data; 
      } 
      return default(T); 
     } 
    } 
} 

Jetzt in Ihrer ConfigureServices Methode der Startklasse, Caching aktivieren und unsere eigene ICache-InMemoryCache Mapping definieren.

public void ConfigureServices(IServiceCollection services) 
{ 
    services.AddTransient<ICache, InMemoryCache>(); 
    services.AddMemoryCache(); 
} 

Jetzt können Sie ICache zu jeder Klasse injizieren und es verwenden/Daten speichern, um es zu bekommen.

public class LocationSelector : ViewComponent 
{ 
    private readonly ILocationService locationsService; 
    private readonly ICache cache; 
    public LocationSelector(ILocationService locationService,ICache cache) 
    { 
     this.locationsService = locationService; 
     this.cache = cache; 
    } 

    public async Task<IViewComponentResult> InvokeAsync() 
    { 
     var locationManager = new LocationSelectorViewModel(); 

     var areas = await this.cache.Get(CacheKey.Statuses,() => 
                this.locationsService.GetAreas(),360); 
     locationManager.Areas = areas; 

     return View("Default", locationManager); 
    } 
} 
Verwandte Themen