2013-02-05 11 views
6

Sto lavorando su un sito Web asp.net mvc 4 simile a un negozio online con un datalayer wcf-service. La mia applicazione è costruita con maincategories, sottocategorie e prodotti. Ogni prodotto può essere solo in una sottocategoria e il mio URL di sono in questo modo:Come aggiungere un nuovo nodo MvcSitemapProvider al runtime

/maincategoryname/SubCategoryName/{productid}/ProductTitle

e il corrispondente filo di Arianna:

Home> Maincategory> Sotto> ProductTitle

Attualmente sto utilizzando MvcSitemapProvider per generare i menu di navigazione e i breadcrumb. Sto caricando tutti gli URL come nodi dinamici senza cache. Questa soluzione funziona per un paio di prodotti, ma quando aggiungo 1000 prodotti la mappa del sito impiega 6,5 ​​secondi per popolare, il che è troppo lungo.

Ho attivato la memorizzazione nella cache in MvcSitemapProvider. In questo modo l'applicazione si carica molto più velocemente. Ma quando un utente aggiunge un nuovo prodotto e naviga verso questo nuovo prodotto (pagina). L'URL non è ancora nel file Sitemap perché utilizza la cache. In questo modo la mia navigazione e i breadcrumb non vengono generati.

La mia domanda è:

E 'possibile aggiungere un nuovo nodo per la mappa del sito in fase di esecuzione dopo che un utente aggiunge un nuovo prodotto?

risposta

0

MvcSiteMapProvider consente Dynamic Sitemaps che risolve le dipendenze della cache.

È possibile abilitare questo creando una classe che implementa IDynamicNodeProvider. Di seguito è riportato un esempio che genera nodi dinamici in base a una query di database e imposta anche una dipendenza dalla cache sulla stessa query.

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

Anche se questo è tutto molto elegante - e dovrebbe invalidare la cache quando i clienti cambiano prodotti della datbase - tutta SqlCacheDependancy può essere difficile ed è Server versione di SQL dipendente.

Si può andare con una personalizzata CacheDependacy invece, se si sta utilizzando la cache per memorizzare i vostri prodotti.

5

La risposta accettata è ora un po 'obsoleta. In MvcSiteMapProvider v4, non esiste più un metodo GetCacheDescription() in un DynamicNodeProvider. Questo non sembra funzionare comunque.

È ora possibile invalidate the cache manually utilizzando l'attributo [SiteMapCacheRelease] sui metodi di azione che aggiornano i dati:

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

    // Update the record 

    return View(); 
} 

o chiamando un metodo statico:

MvcSiteMapProvider.SiteMaps.ReleaseSiteMap(); 

Hai anche la possibilità ora per estendere il framework a supply your own cache dependencies.

Problemi correlati