locked
For how long we should put OutputCache for better performance RRS feed

  • Question

  • User1052662409 posted

    Hi All,

    I am using MVC5. In my application when a user get login he/she finds a menu depending on the designation/ role he/she have.

    I am creating the menu when user logs in. It takes more that usual time to get login and it just because of menu creation process. For that I am trying to use  OutputCache to make the performance better. But I am not sure for how long I should use the duration, because user might be stay for 1 hr or may be 15 mins.

    Below is my Action result

           [OutputCache(CacheProfile = "Long")]
            public ActionResult Index(Login login)
            {
                if (ModelState.IsValid)
                {
                   
    
                    // code for check user valid creadentials
    
                    if (Convert.ToInt32(Param1.Value) > 0) // checking for valid credentials
                    {
                        
    
                        FormsAuthentication.SetAuthCookie(
                        login.pvcUsername.Trim(), false);
                        FormsAuthenticationTicket ticket1 =
                           new FormsAuthenticationTicket(
                                1,                                   // version
                                login.pvcUsername.Trim(),   // get username  from the form
                                DateTime.Now,                        // issue time is now
                                DateTime.Now.AddMinutes(540),         // expires in 10 minutes
                                false,      // cookie is not persistent
                                
                                                                       // in userData
                                );
                        HttpCookie cookie1 = new HttpCookie(
                          FormsAuthentication.FormsCookieName,
                          FormsAuthentication.Encrypt(ticket1));
                        Response.Cookies.Add(cookie1);
                        if (Convert.ToString(Param6.Value) == "True")
                        {
                             
    			// getting user's data for creating menu  like Session["AdminID"], Session["USER-Country"]
    						 
                            #region Getting All Menu
                            List<MenuModel> MenuData = db.AdminSection_GEN.GroupJoin(db.AdminSection_GEN, first => first.bintId_Pk, second => second.IntParentId_FK, (first, second) =>
                                   new { a = first, b = second } // b is a collection which belongs to a 
                                   ).Where(m => m.a.IntParentId_FK == 0).OrderBy(m => m.a.IntOrder).SelectMany(x => x.b.DefaultIfEmpty(),
                                             (x, y) => new MenuModel { MainMenuId = x.a.bintId_Pk, MainMenuName = x.a.vcTitle, SubMenuName = y.vcTitle, ControllerName = y.controller, ActionName = y.action, Parent_Id = y.IntParentId_FK, IntOrder = x.a.IntOrder, IntOrderchild = y.IntOrder, Status = y.btStatus, SuperADMIN = y.superadmin, SubMenuId = y.bintId_Pk }
                                        ).Where(m => m.Status == true).OrderBy(e => e.IntOrder).ThenBy(e => e.IntOrderchild).ToList();
    
                            List<MenuModel> AssignedMenu = new List<MenuModel>();
                            List<Country_Module_Assign> MenuPermissionInCountry = db.Country_Module_Assign.ToList();
                            List<AdminSectionPermission_GEN> MenuPermissionForUser = db.AdminSectionPermission_GEN.ToList();
                            foreach (var item in MenuData)
                            {
                                int country_id = Convert.ToInt32(Session["USER-Country"].ToString());
                                int user_id = Convert.ToInt32(Session["AdminID"].ToString());
    
                                bool country_permission = (db.Country_Module_Assign.Any(o => o.CountryID == country_id && o.ModuleID == item.SubMenuId)); // checking coutry permission for module
                                bool user_permission = (db.AdminSectionPermission_GEN.Any(o => o.bIntSectionId_FK == item.SubMenuId && o.bIntAdminId_FK == user_id));// checking user permisson for module
    
                                if (user_permission && country_permission)
                                {
                                    AssignedMenu.Add(item);
                                }
    
                            }
                            Session["MenuMaster"] = AssignedMenu;
                            #endregion
    						}
    						else
                        {
                            
    
                        }
    
                    }
    
                    else
                    {
                        return RedirectToAction("Index","Login");
                    }
                }
    
                return View();
    
    
            }
    

    In web config I set caching 

     <caching>
          <outputCacheSettings>
            <outputCacheProfiles>
              <add name="Long" duration="60" varyByParam="id" />
              <add name="Medium" duration="60" varyByParam="none" />
              <add name="Short" duration="10" varyByParam="none" />
            </outputCacheProfiles>
          </outputCacheSettings>
        </caching>

    Please suggest.

    Wednesday, September 4, 2019 10:53 AM

Answers

All replies

  • User475983607 posted

    You're caching the login action which will return the login results of the first user that logs in without executing the code.

    I use memory cache where the cache key is the role.  Then fetch the cached menu by role.  Cache duration depends on how long you want to wait before seeing the menu update (on the screen) after adding a new menu item or a role change. 

    Wednesday, September 4, 2019 11:24 AM
  • User-821857111 posted

    How often are the menu contents modified? Hourly, Daily? Weekly? 

    Wednesday, September 4, 2019 11:59 AM
  • User1052662409 posted

    Mikesdotnetting

    How often are the menu contents modified? Hourly, Daily? Weekly? 

    In database it doesn't modified. In database it will remain same.

    It gets created  every time when a user logs in depending on the  conditions, means  almost daily.

    // after login
    foreach (var item in MenuData) { int country_id = Convert.ToInt32(Session["USER-Country"].ToString()); int user_id = Convert.ToInt32(Session["AdminID"].ToString()); bool country_permission = (db.Country_Module_Assign.Any(o => o.CountryID == country_id && o.ModuleID == item.SubMenuId)); // checking coutry permission for module bool user_permission = (db.AdminSectionPermission_GEN.Any(o => o.bIntSectionId_FK == item.SubMenuId && o.bIntAdminId_FK == user_id));// checking user permisson for module if (user_permission && country_permission) { AssignedMenu.Add(item); } }

    For a particular user it remains the same for many months.

    Wednesday, September 4, 2019 12:16 PM
  • User1052662409 posted

    You're caching the login action which will return the login results of the first user that logs in without executing the code.

    Yes, this will do the same, that is why I want different cache for every user.

    Wednesday, September 4, 2019 12:18 PM
  • User-474980206 posted

    mgebhard

    You're caching the login action which will return the login results of the first user that logs in without executing the code.

    Yes, this will do the same, that is why I want different cache for every user.

    then you should use session (unique by user), rather than cache (unique by site).

    Wednesday, September 4, 2019 2:02 PM
  • User1052662409 posted

    then you should use session (unique by user), rather than cache (unique by site).&

    You mean paramby Session [userID]? There may be more than one user can who can have same menu. It won't make any difference?
    Wednesday, September 4, 2019 2:17 PM
  • User475983607 posted

    Yes, this will do the same, that is why I want different cache for every user.

    Are you sure?  Generally HTTP POST responses are not cached only HTTP GET.  We cannot see the "long" configuration so it's not clear how you are varying the output cache but output cache seems like the wrong approach as you should never output cache user specific items.  You are running the risk of sharing user data.

    You mean paramby Session [userID]? There may be more than one user can who can have same menu. It won't make any difference?

    Global cache like memory cache is a good choice.  The cache can be keys by the role or query the cache by role.  Memory cache has the added benefit of a timeout which you can control.

    But Session works too and by using Session the Menu times out with the user however you need to set Session state for every user which is the problem you are trying to avoid.

    Wednesday, September 4, 2019 3:56 PM
  • User1052662409 posted

    Global cache like memory cache is a good choice.

    Do you have any reference or link where I can get the implementation?

    Thanks

    Thursday, September 5, 2019 5:37 AM
  • User475983607 posted

    Do you have any reference or link where I can get the implementation?

    Memory cache and caching in general is covered in the standard documentation.

    https://docs.microsoft.com/en-us/dotnet/api/system.runtime.caching.memorycache?view=netframework-4.8

    Google resutls

    https://www.google.com/search?q=memorycache+c%23&rlz=1C1GGRV_enUS812US812&oq=memorycache+&aqs=chrome.1.69i57j0l5.4499j0j7&sourceid=chrome&ie=UTF-8

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, September 5, 2019 10:54 AM