How to add a new MvcSitemapProvider node at runtime
Asked Answered
B

2

6

I'm working on a webshop-like asp.net mvc 4 website with a wcf-service datalayer. My application is build with maincategories, subcategories and products. Each product can only be in one subcategory and my url's are like this:

/maincategoryname/subcategoryname/{productid}/producttitle

And the corresponding breadcrumb trail:

Home > Maincategory > Subcategory > Producttitle

I'm currently using MvcSitemapProvider to generate my navigation menu's and breadcrumbs. I'm loading all the url's as dynamic nodes without cache. This solution works for a couple of products but when I add 1000 products the sitemap takes 6,5 second to populate, wich is way too long.

I turned on caching in MvcSitemapProvider. This way the application loads much faster. But when a user adds a new product and navigates to this new product (page). The url is not yet in the sitemap file because it uses cache. This way my navigation and breadcrumbs are not generated.

My question is:

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

Bernardina answered 5/2, 2013 at 13:8 Comment(0)
F
5

The accepted answer is now a little out of date. In MvcSiteMapProvider v4, there is no longer a GetCacheDescription() method in a DynamicNodeProvider. This didn't seem to work anyway.

You can now invalidate the cache manually by using the [SiteMapCacheRelease] attribute on 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 a static method:

MvcSiteMapProvider.SiteMaps.ReleaseSiteMap();

You also have the option now to extend the framework to supply your own cache dependencies.

Fault answered 18/8, 2013 at 11:16 Comment(0)
F
0

MvcSiteMapProvider allows for Dynamic Sitemaps that solve for Cache Dependancies.

You can enable this by creating a class which implements IDynamicNodeProvider. Below is an example that generates dynamic nodes based on a database query, and also sets up a cache dependency on that 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'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
      };
    }
  }
}

While this is all very nifty - and should invalidate the cache when your customers change products in the datbase - the whole SqlCacheDependancy can be tricky and is SQL Server-Version dependent.

You may go with a custom CacheDependacy instead, if you're using the cache to store your products.

Fumed answered 23/4, 2013 at 8:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.