How to add a new MvcSitemapProvider node at run time

I am working on an asp.net mvc 4 website with a wcf-service file. My application is built using the main categories, subcategories, and products. Each product can be in only one subcategory, and my url is as follows:

/ maincategoryname / subcategoryname / {ProductID} / producttitle

And the corresponding track for tiny crumbs:

Home> Home Category> Subcategory> Producttitle

I am currently using MvcSitemapProvider to create my navigation menu and breadcrumbs. I load the entire url as dynamic nodes without a cache. This solution works for several products, but when I add 1000 products, the sitemap takes 6.5 seconds to fill, too long.

I have included caching in MvcSitemapProvider. Thus, the application loads much faster. But when the user adds a new product and goes to this new product (page). The URL is not yet in the sitemap because it uses the cache. Thus, my navigation and breadcrumbs are not generated.

My question is:

Is it possible to add a new node file to the sitemap at runtime after a user adds a new product?

+6
source share
2 answers

The accepted answer is now a little outdated. MvcSiteMapProvider v4 no longer has the GetCacheDescription () method in DynamicNodeProvider. It does not seem to have worked.

Now you can manually invalidate the cache using the [SiteMapCacheRelease] attribute in the action methods that update the data:

[MvcSiteMapProvider.Web.Mvc.Filters.SiteMapCacheRelease] [HttpPost] public ActionResult Edit(int id) { // Update the record return View(); } 

Or by calling the static method:

 MvcSiteMapProvider.SiteMaps.ReleaseSiteMap(); 

You also have the opportunity to expand the scope to provide your own cache dependencies .

+5
source

MvcSiteMapProvider allows "Dynamic Sitemaps" that are resolved for cache dependencies.

You can enable this by creating a class that implements IDynamicNodeProvider . Below is an example that generates dynamic nodes based on a query to the database, and also sets the cache dependency on the same query.

 public class ProductNodesProvider : IDynamicNodeProvider { static readonly string AllProductsQuery = "SELECT Id, Title, Category FROM dbo.Product;"; string connectionString = ConfigurationManager.ConnectionStrings ["db"].ConnectionString; /// Create DynamicNode 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 }; } } } 

Although this is all very elegant - and this should lead to a cache invalidation when your customers change products in the database - the whole SqlCacheDependancy can be complex and depends on the version of SQL Server.

Instead, you can use custom CacheDependacy if you use a cache to store your products.

0
source

All Articles