I am trying to implement caching in an MVC 4.0 ASP.net application. I can cache using outputcache
[OutputCache (Duration=60)]
public ActionResult myaction(string parm1)
{
--logic to construct the model object
-- followed by this return statement
return PartialView(model);
}
But I need to clear the cache after editing data which is stored in an xml file.
So I tried to add
HttpResponse.RemoveOutputCacheItem(Url.Action("myaction", "myController"));
in another action of the same controller before calling return RedirectToAction(myaction);
But the cache is not getting reset.
Is this the method to refresh outputcache using actions? I call these actions from jquery using ajax.
Use ICacheProvider instead.
OutputCache is very limited on what you can do.
Once you need to change the data that is cached, you can invalidate that particular data using ICacheProvider while using OutputCache, you either cache the entire ActionResult or none.
Also OutputCache does neither have the flexibility that ICacheProvider has, nor the beauty of working with it.
You may have cached the output on the user's machine instead of the server. Try specifying the Location:
[OutputCache(Location= System.Web.UI.OutputCacheLocation.Server, Duration=60]
Otherwise the cache deletion won't work because you've cached the HTML output on the user's machine
ASP.NET MVC supports donut-hole caching but not donut caching. You can cache partial views and exclude parent view BUT you cannot cache parent view and exclude partial views. Write a custom filter for caching or use https://www.nuget.org/packages/MvcDonutCaching
Related
I am using the MvcSiteMapProvider Html Helper to create a navbar. The content of the navbar depends on the visitor rights therefore I am using security trimming to only display content which the person is authorized for. For performance improvement I am trying to cache this navbar.
The navbar is created in a partial view with the following content:
#Html.MvcSiteMap().Menu("MenuHelper", new { name = "MainMenu" })
Inside the layout file it is called by an action method which returns the partial view:
[System.Web.Mvc.OutputCache(Duration = 10, VaryByCustom = "User")]
[ChildActionOnly]
public ActionResult MainMenu()
{
return PartialView("MainMenu");
}
The caching of works fine at the root page of the sitemap. However when the cache duration runs out and the action method is called from deeper levels, no sitemap is returned.
When I disable security trimming or the output caching it works perfectly fine at all levels.
Is it possible that action method which returns the navbar, is called when the authorization data is unavailable and therefore returns a corrupt sitemap?
If you analyze the source for AuthorizeAttribute, you will note that it is not designed to work with child actions that are output cached (they go to some great lengths to ensure that child actions that are output cached will throw an exception).
Of course, it also won't work right if you have a custom AuthorizeAttribute that overrides OnAuthorization that does not duplicate this important logic.
However, there are a couple of things you can do to improve performance when using Security Trimming:
Make sure that your injection constructors are simple, especially on your controllers. If you have heavy processing in your constructors, it can really slow things down (with or without MvcSiteMapProvider, but Security Trimming makes this much more apparent).
If that doesn't improve things enough and you are not using a custom AuthorizeAttribute, you could use the roles attribute/property to duplicate your role logic into the SiteMap and remove the AuthorizeAttributeAclModule from your configuration (external DI only).
See this discussion for more details.
Can we cache Model in Partial View if not NULL.
So that if my page make a round trip it will still have values in model.
Because i have an action that returns a list of records based on search parameters.
and that list is bound to the grid.
This grid has paging.
so when i click on 2nd page, this grid is making a round trip to the partial view and second time the model in that partial view is empty.
Can any one suggest a best approach to not to loose data in model.
here i can't do output cache for the Action that returns result list.
any idea would be greatly appreciated.
thanks
You can add the Cache attribute to your controller, it works a treat.
[OutputCache(Duration=60,VaryByParam="ParamA;ParamB;")]
public PartialViewResult CachableAction(string SomeParameter)
{
...
}
MVC is a RESTful architecture, you have to provide the data/Model to your View from the Controller on each request.
If you decide to use OutputCache or other mechanisms, make sure your application can fall back and get the real resources. Cache in general can get removed by the server for various reasons and should not be relied in order for your functionality to work. Caching should be used for performance and scalability.
Take a look at the PagedList.
Im thinking in use the Output cache attribute for caching views in MVC.
My question is simple:
When i use output cache attribute on top of an action method, if in the next request the view was cached the action is not executed right?
Yes, you are correct. This is easliy tested:
[OutputCache(Duration=10, VaryByParam="id")]
public function TestCache()
{
return Content(" I was generated at " + DateTime.Now);
}
However, you can invalidate the cache using the VaryByParam property, which allows you to control the cache depending on request parameters or similar.
In my example, the cache will vary depending on which id is specified in the request parameters. This is useful when you have a dynamic page which loads data from the database.
Yes you are right , the cached action is not executed unless you use varyByParam or some other property of that attribute.
Since upgrading from mvc 2 beta 2 to rc I'm having trouble with an ajax submission in Internet Explorer. Upon carrying out a jquery form post, the function returns a url to a controller action. This worked fine with the controller action picking up it was a ajaxrequest and then piping back a partial view to update the page. This still works fine in Firefox, however in Internet Explorer the final call to the controller action now comes from cache and returns therefore returns a full view rather than partial.
I've tried setting the outputcache to 0 with no success and I've also tried the nocache actionfilter as described here Disable browser cache for entire ASP.NET website with no luck. The only way I can stop IE from pulling from cache is to physically delete the cached version.
Anyone have any ideas (apologies if this isn't very clear, tricky one to explain!)?
For some reason, IE is really aggressive about caching AJAX GETs. So if you are fetching that via AJAX, the behavior is not surprising to me. Also not surprising is that using output cache attribute didn't fix the problem, because it is IE, rather than the server, which is doing the caching. What you need to do is to tell IE not to cache the request, by setting the appropriate headers in the HTTP. Here is how we do it:
[CacheControl(HttpCacheability.NoCache), HttpGet]
public JsonResult DoStuff()
{
//...
}
public class CacheControlAttribute : ActionFilterAttribute
{
public CacheControlAttribute(HttpCacheability cacheability)
{
this._cacheability = cacheability;
}
private HttpCacheability _cacheability;
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
cache.SetCacheability(_cacheability);
}
}
My 2 cents to Craig's great solution -
If you're using a user control and rendering it using an "RenderAction"
<% Html.RenderAction("UserList", "User"); %>
And this page invokes it via GET as well as POST then don't mention the request method in the attribute declaration.
[CacheControl(HttpCacheability.NoCache)]
For example, I've a search Grid and a search panel on top of it. I've made my Grid a user-control so that I can invoke the sort & paging via AJAX (GET) still it is also invoked when I press the "search" button (POST) so I need it for both.
I have an action that returns a view with a master page with a logon user control at the top. When I set outputcache, it caches the entire output including the current user, so everybody would see whoever was the last person to hit the page to refresh the cache as the current user. Is there a way to prevent the master page from being included in the cache?
I am using the following code:
[OutputCache(Duration=3000, VaryByParam={params})]
public ActionResult {actionName}({params})
{
{codeGoesHere}
}
There was a concept of "donut caching" (excluding parts of a page from the output cache) but it didn't made it in asp.net MVC 1. For solution to your problem you can try this workaround.
Output cache is associated with the controller, not the view. A controller may return different views, based on the passed parameters. Caching may also be done by parameters (like you have in your example). When the result of a controller is cached, that cached value is the view's generated html (including the master page if any). So, the short answer is, no, you can't exclude the master page from the cache.