title: ASP .NET Getting Data Too Slowly
body: <p>I am currently working on a web app using ASP.NET MVC and Angular. What I want to be able to do is get a list of navigation items for each user based on what their role is, store them all in a list of objects and serialize it into JSON to return to angular.</p>
  
  <p>My method currently works just fine, but it takes at least 5 seconds for the data to hit the page while my page loads in less than a second. So my user is just kind of sitting there waiting for the navitems to popup which isn't good.</p>
  
  <p>Here are the two methods that I use:</p>
  
  <pre><code>public NavDirectoryViewModel GetAllUserNavItems(string UserId)
  {
      NavDirectoryViewModel model = new NavDirectoryViewModel();
      model.NavItems = new List&lt;NavViewModel&gt;();
      foreach (var nav in GetAllNavItems())
      {
          if (GetUserNavItem(UserId, nav) != null)
          {
              if (nav.ParentId == 0)
                  model.NavItems.Add(GetUserNavItem(UserId, nav));
          }
      }
      model.NavItems = model.NavItems.OrderBy(x =&gt; x.SortOrder).ToList();
      return model;
  }
  
  public NavViewModel GetUserNavItem(string UserId, NavModel model)
  {
  
      try
      {
          if(model.AllowedUsers.FirstOrDefault(x =&gt; x.UserId.Equals(UserId)) != null || model.AllowedRoles.FirstOrDefault(x =&gt; x.Role.Users.FirstOrDefault(y =&gt; y.UserId.Equals(UserId)) != null) != null)
          {
              return new NavViewModel { Name = model.Name, Href = model.Href, Image = model.Image, SortOrder = model.SortOrder, SubItems = GetNavItems(model.Id).Where(x =&gt; x.ParentId == model.Id).Select(x =&gt; GetUserNavItem(UserId, x)).ToList() };
          }
          else
          {
              return null;
          }
      }
      catch(Exception e1) { return null; }
  }
  </code></pre>
  
  <p>Here are the two models:</p>
  
  <pre><code>public class NavViewModel
  {
      public string Name { get; set; }
      public string Href { get; set; }
      public string Image { get; set; }
      public int? SortOrder { get; set; }
  
      public List&lt;NavViewModel&gt; SubItems { get; set; }
  }
  
  public class NavModel
  {
      [Key]
      public int Id { get; set; }
      public string Name { get; set; }
      public string Href { get; set; }
      public string Image { get; set; }//string of server image path or fa class
      public int ParentId { get; set; }//Will be 0 if it has no parent
      public int? SortOrder { get; set; }
  
  
      public virtual List&lt;NavModel&gt; SubItems { get; set; }
      public virtual List&lt;RoleNavAuthorizationModel&gt; AllowedRoles { get; set; }
      public virtual List&lt;UserNavAuthorizationModel&gt; AllowedUsers { get; set; }
  }
  </code></pre>
  
  <p>The Role and UserNavAuthorizationModels only store the NavItem Id and the Role/UserId that is allowed to see the nav item.</p>
  
  <p>Originally I was serializing the NavModel which was taking 10-15 seconds so I made a view model that didn't store as much data and that sped things up a little. However I can't have my users waiting for the navbar to load when everything else is already loaded.</p>
  
  <p>When debugging I found that it is the <code>GetUserNavItem</code> method that is the one that is taking a while. Everything else was running very quickly.</p>
  
  <p>Does anyone have any suggestions on how to speed things up?</p>
  
  <p><strong>Update</strong></p>
  
  <p>Here is the code for <code>GetAllNavItems()</code>:</p>
  
  <p><code>public List&lt;NavModel&gt; GetAllNavItems() { return db.NavItems.ToList(); }</code></p>
  
  <p><strong>Update</strong></p>
  
  <p>I took Ondrej Svejdar's advice on caching and now store the JSON in the user's session so that if the page reloads while their session is active it takes no time at all to reload. I put this in my controller:</p>
  
  <pre><code>if (HttpContext.Cache[User.Identity.GetUserId() + "NAV"] == null)
  {
      string NavJSON = JsonConvert.SerializeObject(nrepo.GetAllUserNavItems(User.Identity.GetUserId()), Formatting.Indented, new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
      HttpContext.Cache[User.Identity.GetUserId() + "NAV"] = NavJSON;
      return Json(NavJSON, JsonRequestBehavior.AllowGet);
  }
  else
  {
      string NavJSON = HttpContext.Cache[User.Identity.GetUserId() + "NAV"].ToString();
      return Json(NavJSON, JsonRequestBehavior.AllowGet);
  }
  </code></pre>