I would like to cache an entire page to a distributed cache (specifically Redis) in an ASP.NET Core 2.1 MVC web app. When a user visits a page, the code in the action method and the view cshtml is executed, and a page is generated and sent to the user. I would like this page to get cached at the end of the request, so that when subsequent users visit the page it should get presented from the cache, without having to execute any code in the action method or the view. And more specifically, I would like it to be cached in Redis. I am familiar with how to store key-value pairs in Redis from a web app, and also familiar with how to cache parts of a page to Redis, but I cannot figure out how to cache the entire page to Redis.
I have successfully used a Redis specific implementation of the IDistributedCache interface to store key value pairs to Redis. This was achieved by installing the Microsoft.Extensions.Caching.Redis.Core NuGet package, and adding the following statement to ConfigureServices():
services.AddDistributedRedisCache(options =>
{
options.Configuration = "localhost";
options.InstanceName = "SampleInstance";
});
Once that was done, I was able to dependency inject the Redis IDistributedCache implementation into a controller, and then use statements like _cache.GetStringAsync() and _cache.SetStringAsync() to store and retrieve key value pairs to Redis. I can also use the <distributed-cache> tag helper in a .cshtml page to cache parts of a view.
However these techniques do not help me to cache the entire page, only parts of it. The code in the action and the view still need to execute, and the page needs to be re rendered, albeit faster since some of it is cached. What I would like to do is cache the entire page, so that everything can be served up from cache without executing code in the action method and the view cshtml.
I am also aware of how basic page caching can be accomplished in ASP Core 2.1 using the built in functionality. All one needs to do is add a [ResponseCaching(Duration=...)] attribute to the action method, add the statements services.AddResponseCaching() and app.UseResponseCaching() to ConfigureServices() and Configure() respectively in Startup.cs. Unfortunately, the page gets cached on the server instance, presumably in the server's memory. I cannot figure out how to tell it to cache this page in Redis instead.
Basically I want something like [ResponseCaching(Duration=..., CACHE=REDIS)]. How does one accomplish this?
Old ASP.NET 4 Equivalent
In ASP.NET 4, one would simply add an [OutputCache(Duration=...)] attribute to the action, install the Microsoft.Web.RedisOutputCacheProvider NuGet package, and put the following in web.config
<caching>
<outputCache defaultProvider="MyRedisOutputCache">
<providers>
<add name="MyRedisOutputCache" type=... host="" ssl="true" />
</providers>
</outputCache>
</caching>
And the entire page would subsequently be cached to Redis. It was really simple. This is exactly the functionality I am trying to replicate in ASP Core 2.1.
you can use ASP.NET MVC Action Filters.
overwrite OnResultExecuted to store final result in Redis cache.
check if cache exist in OnActionExecuting.
the OnResultExecuted call after the html view is ready, so you can store rendered html.
the OnActionExecuting call before the action so you can load data from cache.
check ASP.NET MVC Action Filters in this link.
Related
Is it possible to cache entire Views in ASP.NET Core?
One can use IMemoryCache to cache data in ASP.NET Core, however I can't see any way of caching the compiled Views so that they are not recompiled every time they are requested.
I initially tried to cache the ViewResult Objects returned by the View() method in the Controller, however I later found that these objects are not the actual Views.
To clarify, I would like to be able to cache dynamic Views so that their code is not compiled every time they are requested, only once a specified timeout has been exceeded.
You can do that by specifying OutputCache attribute for Action/Controller.
As MSDN stated:
OutputCacheAttribute
Output caching lets you store the output of an action method in
memory on the Web server. For example, if the action method renders a
view, the view page will be cached. This cached page is then available to the application for subsequent requests. Output caching saves your application the time and resources it would take to re-create the result of the action method.
In ASP.NET MVC, you can use the OutputCacheAttribute attribute to mark action methods whose output you want to cache. If you mark
a controller with the OutputCacheAttribute attribute, the output
of all action methods in the controller will be cached.
Properties:
NoStore : Gets or sets a value that indicates whether to store the cache.
Duration : Gets or sets the cache duration, in seconds.
For more Properties, please refer to OutputCacheAttribute Properties
Please also have a look at this Improving Performance with Output Caching.
Update
For ASP.NET Core there is also an Attribute called Response Caching.
According to Microsoft Docs
Response Caching:
Response caching adds cache-related headers to responses. These headers specify how you want client, proxy and middleware to cache responses. Response caching can reduce the number of requests a client or proxy makes to the web server. Response caching can also reduce the amount of work the web server performs to generate the response.
Unlike Output cache, it does not store HTTP response at server, it just adds "Cache-Control" header in the response (Source).
I've a web application that uses FreeMarker templates and tiles to do the View job in the MVC world. So upon my request to the application, say /load.do I would like to introduce an intermediate page that will have a loader icon just to indicate the page is being loaded on the subsequent request, which is not known to the user.
So ultimately what I'm achieving is a better user experience and also if used within framework (the iFrames) this comes handy to show the loader icon when there is a new request that is happening.
Can someone point me to the right method I can use here ?
This is possible using spring mvc.
You need to create something like a WaitController. On user submit , this controller will be called. This can trigger your original request in background and take a reference(UUID) for the call and will render a wait page having the reference id of the original request set in model. Wait page can either trigger immediately the main controller using reference id or can poll the reference id on regular intervals or use web socket to know the availability of results. Once results are ready, it should redirect user to the actual result page.
Reading the Ember guide about the data store it's not clear how you pre-populate the store with your data. I see you can set up the RESTadapter with the host name, and the 'store.find' method will trigger a 'get' request if the data is not cached, but how can I initialize a DS.Store with JSON data via ajax before ever doing a find?
Ember guide model HTTP
The context for this is, a single page app that on page load gets a blob of json, which is used to model out the rest of the site. The end result gives the illusion that the site contains multiple pages.
Sounds like you want this.store.pushPayload(..)
http://emberjs.com/api/data/classes/DS.Store.html#method_pushPayload
Note that you only have access to the store inside Routes and Controllers. Consider putting this inside the activate hook of App.ApplicationRoute
http://emberjs.com/guides/routing/defining-your-routes/#toc_initial-routes
http://emberjs.com/api/classes/Ember.Route.html#method_activate
I have tried to incorporate AJAX into an application that I built.
The basic function is:
-The user clickes a button, which triggers JS code that makes an AJAX call that does a POST to a Servlet(sending account data).
-The Servlet(which has an EJB injected into it), communicates with an EJB through it's local interface.
-The EJB(on init) initializes a DAO object, injects an EntityManager into it, and uses that DAO object to communicate with a database through JPA (Hibernate as the provider).
-The local interface methods of the EJB return Data Transfer Objects, which are parsed in the Servlets doPost() method, and the DTO's are used to build an HTML table(String) that the Servlet responds to the AJAX call with.
-On the client side, I use that HTML table(responseText) to update a div on the page.
I have 2 questions:
1) Is using a data-centric approach to the AJAX call (returning an HTML table instead of JSON Strings) a common choice in enterprise level applications that make use of AJAX?
2)I've noticed that sometimes the POST is not even called. It seems to be intermittent. I tried to add the Cache Control header, but that doesn't seem to work. This concerns me especially when I think about eventually deploying the application to production, that maybe AJAX is not the way to go, but when it works, the application works smoothly.
1) Using AJAX to submit data or update the web page is very common. Page at a time applications are the old way web applications used to be done where you would need to reload the entire page just to update a little bit of information - which would be inefficient and not to mention would create a bad user experience. These days, updating just "Part of a page" is very common and is mostly done using AJAX, and if not WebSockets.
Now you question regarding updating the page using the servers response which is HTML - to update the page, or just get a JSON String, and manipulate the DOM (ie adding tables etc). I have used a combination of these. For example if needed to add a row to a table, you could get the server to generate the HTML using a tempting engine (groovy or similar). In addition you you need a response code, so you can package the HTML and Response code in a JSON, and send it back to the client. Any combination of these works depending on your use case.
JsonObject json = new JsonObject();
json.addProperty("responseCode", responseCode);
json.addProperty("html", html);
2) You can write a simple script to send multiple requests to the AJAX url to see if it is the server that is not able to handle the amount of requests. If it works, then you can narrow down the problem to be client side. Make sure you are not using blocking techniques. You can also setup a callback function to see if there is any response if any. AJAX Post is similar to a normal POST request, just make sure you have some indicator for the user notifying them that the request is in progress/complete.
I'm looking for a NodeJS MVC framework that allows rendering partial views on client side using Ajax (without whole page refreshing).
As far as I know, you can declare partial views on server with almost any Framework (Express, Sails...), but this will lead to refresh the whole page even if there's only a small portion of your page that really changes. This problem doesn't exist with a SPA Framework (this one would just load the partial html file in a container via ajax).
I believe Microsoft ASP.NET MVC was able to handle this case, by comparing the previous version of the page with the new requested page, and just returning the portion of the page that really changed. This may be time and CPU-consuming but it just works.
Is any Node MVC Framework managing a similar thing today ? Or is it mandatory to use an SPA Framework when a reactive user interface is required (without any whole page refresh) ?
Thanks in advance !
sails.js! It supports partials as you requested. You don't need to refresh the page, if you send ajax-request or handle the stuff via websockets dynamically.