2013-02-05 11 views
6

Ich arbeite an einer Webshop-ähnlichen asp.net mvc 4-Website mit einem Daten-Layer für den WCF-Dienst. Meine Anwendung wird mit Hauptkategorien, Unterkategorien und Produkten erstellt. Jedes Produkt kann nur in einer Untergruppe sein und meine URLs sind wie folgt aus:Wie man einen neuen MvcSitemapProvider-Knoten zur Laufzeit hinzufügt

/maincategoryname/subcategoryname/{productid}/producttitle

und die entsprechenden Brotkrumen:

Home> Hauptkategorie> Unterkategorie> Producttitle

Ich verwende derzeit MvcSitemapProvider, um meine Navigationsmenüs und Breadcrumbs zu generieren. Ich lade alle URLs als dynamische Knoten ohne Cache. Diese Lösung funktioniert für einige Produkte, aber wenn ich 1000 Produkte hinzufüge, dauert die Sitemap 6,5 Sekunden, was viel zu lang ist.

Ich habe das Zwischenspeichern in MvcSitemapProvider aktiviert. Auf diese Weise lädt die Anwendung viel schneller. Wenn ein Benutzer jedoch ein neues Produkt hinzufügt und zu diesem neuen Produkt (Seite) navigiert. Die URL befindet sich noch nicht in der Sitemap-Datei, da sie den Cache verwendet. Auf diese Weise werden meine Navigation und Breadcrumbs nicht generiert.

Meine Frage ist:

Ist es möglich, einen neuen Knoten zur Sitemap zur Laufzeit hinzuzufügen, nachdem ein Benutzer ein neues Produkt ergänzt?

Antwort

0

MvcSiteMapProvider ermöglicht Dynamic Sitemaps, die für Cache-Abhängigkeiten zu lösen.

Sie können dies aktivieren, indem Sie eine Klasse erstellen, die IDynamicNodeProvider implementiert. Im Folgenden finden Sie ein Beispiel, das basierend auf einer Datenbankabfrage dynamische Knoten generiert und eine Cacheabhängigkeit für dieselbe Abfrage einrichtet.

public class ProductNodesProvider : IDynamicNodeProvider 
{ 
    static readonly string AllProductsQuery = 
    "SELECT Id, Title, Category FROM dbo.Product;"; 
    string connectionString = 
     ConfigurationManager.ConnectionStrings ["db"].ConnectionString; 

    /// Create DynamicNode's out of all Products in our database 
    public System.Collections.Generic.IEnumerable<DynamicNode> GetDynamicNodeCollection() 
    { 
    var returnValue = new List<DynamicNode>(); 

    using (SqlConnection connection = new SqlConnection(connectionString)) { 
     SqlCommand command = new SqlCommand (AllProductsQuery, connection); 
     connection.Open(); 
     SqlDataReader reader = command.ExecuteReader(); 
     try { 
     while (reader.Read()) { 
      DynamicNode node = new DynamicNode(); 
      node.Title = reader [1]; 
      node.ParentKey = "Category_" + reader [2]; 
      node.RouteValues.Add ("productid", reader [0]); 

      returnValue.Add (node); 
     } 
     } finally { 
     reader.Close(); 
     } 
    } 

    return returnValue; 
    } 

    /// Create CacheDependancy on SQL 
    public CacheDescription GetCacheDescription() 
    { 
    using (SqlConnection connection = new SqlConnection(connectionString)) { 
     SqlCommand command = new SqlCommand (AllProductsQuery, connection); 
     SqlCacheDependency dependancy = new SqlCacheDependency (command); 

     return new CacheDescription ("ProductNodesProvider") 
     { 
     Dependencies = dependancy 
     }; 
    } 
    } 
} 

Während dies alles sehr geschicktes ist - und sollte den Cache ungültig machen, wenn Ihre Kunden Produkte der datbase ändern - die ganze SqlCacheDependancy kann schwierig sein und ist SQL Server-Version abhängig.

Sie können stattdessen mit einer benutzerdefinierten CacheDependacy gehen, wenn Sie den Cache verwenden, um Ihre Produkte zu speichern.

5

Die angenommene Antwort ist jetzt ein wenig veraltet. In MvcSiteMapProvider v4 gibt es in einem DynamicNodeProvider keine GetCacheDescription() -Methode mehr. Das schien sowieso nicht zu funktionieren.

Sie können nun invalidate the cache manually durch die Verwendung von [SiteMapCacheRelease] -Attribut auf den Aktionsmethoden, die die Aktualisierung der Daten:

[MvcSiteMapProvider.Web.Mvc.Filters.SiteMapCacheRelease] 
[HttpPost] 
public ActionResult Edit(int id) 
{ 

    // Update the record 

    return View(); 
} 

oder durch eine statische Methode aufrufen:

MvcSiteMapProvider.SiteMaps.ReleaseSiteMap(); 

Sie haben auch die Möglichkeit, jetzt um das Framework auf supply your own cache dependencies zu erweitern.

Verwandte Themen