I have a MVC + C# based application, which contains a lot of js files, images and css, basically static content. Its running on production as well. There was an issue reported by customer to which we provided an immediate solution by clearing cache on his machine. As per me, this should not be the ideal solution.
We have provided caching in our web.config file as given below:
<staticContent>
<clientCache cacheControlMaxAge="365.00:00:00" cacheControlMode="UseMaxAge" />
</staticContent>
It is for one year, so how do i tackle this situation, as in if there is a new deployment to production, which has changes in static content, how do I make sure, the cache will be refreshed. Our prod deploy happens generally each 2 months.
And what are generally best practices for taking care of these cache things?
We also face this problem, when we do development, change static content, then our QA tests these, they dont find the changes, and we realize we have to clear cache.
Use Bundling it for js and Css. Bundling takes care of caching.
It appends the url for a Bundle with some charactor.
If any changes comes in js or Css file it updates the appended url hence browser takes these file as new file and reloads it.
You can use Bundling with MVC3 and superior versions.
refer this link
Related
A little while back, one of the junior developers at our company was tasked with creating a website for users to enter timesheets offsite. Mostly this is used for staff that reside offshore and have limited bandwidth (it's satellite internet, so we're already looking at a 500ms - 600ms response time, typically with only 10KB/s or less, including 10% - 20% intermittent packet loss).
So it's a challenging situation...
Recently I've been tasked with helping the junior to improve the speed and functionality of the website, mostly for my own benefit, since I'm usually a desktop dev. One thing I've noticed is that the website is using MultiView and I'm wondering if that's the best approach. I can see the reasoning; download the entire website once, then just make queries back and forth, showing/hiding the various views as necessary. Except it doesn't seem to work as smoothly as that.
95% of operations required a run by the server; i.e. add a new timesheet - need to tell the server, which in turn creates a new entry in the database. When the server is done, it seems to cause the client to download the entire webpage again, which is obviously counter productive.
So my question(s) are as follows;
Is this the expected behaviour, given the above situation? i.e. Should the entire webpage be getting re-downloaded once the server has completed it's actions?
If so, is this the best approach for the situation? Would it be better to have smaller, individual pages for the various features (timesheets/leave/etc.)?
I know this is probably a bit opinion based, but any ideas or assistance is greatly appreciated; for both our benefits.
Going from memory, Multiview only renders one of the views, not all of them, but since you mention the Multiview, that tells me you are using the older WebForms technology which often carries large amounts of overhead saving/restoring state. You can try and optimize that, especially if you are using some kind of grid control.
A better approach may be to ditch WebForms and switch to a newer technology like MVC. Rewrite the application to use AJAX with a webservice that returns JSON whenever possible to reduce the amount of data that needs to be sent to and from the server. Using MVC will also reduce the number of resources required for a page load (No resource.axd, etc) which will help page load times, especially over high latency links.
Make sure the server is set to compress dynamic pages with GZIP.
Compress and minify your javascript and CSS.
Don't use inline styles (the style attribute) in your HTML (use classes or IDs+children selectors) to reduce HTMLsize.
Bundle all your javascript and CSS.
Sprite your images in CSS where possible.
Run your images through a good image optimizer like http://kraken.io
Make sure you are caching whatever you can, and the cache duration is set properly.
Minify your HTML.
Stop using WebForms (or watch your page state, and control state very closely)
Check into some of the SPA architectures out there -- you may be able to make the whole application "offline-able" with the exception of the calls to get/update/create data.
Ultimately, each page should only require 1 HTML file, 1 CSS file, 1 Javascript file, and 1 sprite sheet on the first page hit, and then every page after that should only require a single HTML file.
You might also want to look into using a client side library like angular or knockout to handle rendering views. This can reduce the amount of traffic that needs to be sent (although it likely will increase the number of requests by one).
I think the best bet is a SPA (Single Page App) with Angularjs. Done right it greatly reduces the number of http requests. Navigation does not cause entire page reload in any case. Javascript files, css files etc, are loaded just one time at app load time. Once the app is loaded in the browser, the traffic is mainly sending JSON back and forth.
There are some tricks you should apply to reduce app load time:
Bundle javascript files into just one minified javascript file.
Bundle css files into just one css file.
Levearage http cache. You can use file versioning combined with MaxAge http header, so the browser does not even ask the server if the file has changed.
Some tools to help:
Fiddler, look at what is being cached and what isn't.
Facebooks augmented Traffic Control
To my understanding, ajax would be the best choice for you. If you want to access server 95% of times and reload the page with the new elements then the performance would hamper.
So instead of doing this make partial reloading with Ajax or Jquery. There are plenty of functionality available with jquery which would use ajax and reload specific portion of the webpage instead of whole page. It would increse the performance a lot.
One more thing I would like to add is that the response packet coming from server might be huge chunk. So instead of directly throwing the response from the server, implement GZip functionality in the website. It would compress the size of the data packet and the page would load/reload much faster.
Other than these, place your CSS and JS code inside some .css and .js file instead of placing it inside the page itself(and make sure to use it maximum time from all the pages). Browser would make a cache version of those files and reuse it instead of download it every time you want to connect to the server.
I believe that you have already figured out what's wrong. No Multiview is not good if it is implemented as is without tweaks. If your website uses viewstate and on top of that you have the multiview implemented, then it is going to be a costly affair.
Here are your options.
To use most out of the code, I would recommend to convert your methods HTTP GET / POST methods which can be then called separately from the needed actions in the html.
Don't re-render the entire page, but render the content which changes on menu action.
Change the non-changing part of your page / site to static content and apply compression on the static contents.
Enable page caching.
Cache the data offline wherever possible. (Remember it comes with a overhead of syncing data).
If you are considering a revamp give a thought about HTML 5 offline features.
On the website I'm building we are using the built in bundling and minification.
We render our scripts by using the #Scripts.Render
#Scripts.Render("~/bundles/scripts")
it generates a link like:
bundles/scripts?v=3-DUUAAegZl4yp1O4V0VL0GnJ0U6gT3De8yKb41lfGs1
Here I thought that the hash:
v=3-DUUAAegZl4yp1O4V0VL0GnJ0U6gT3De8yKb41lfGs1
would be smart and change if we made changes to the inlcuded scripts but it seems like that is not the case.
Now when we are trying to implement a custom cdn for out bundling it fails on updates since the hash never seems to change.
Does anyone know of a solution to change the hash when the script changes or if we are doing something wring?
Edit:
I noticed that there is a difference in behavior depending on what environment I'm using.
Local development it seems to be working but it doesn't work on the staging server.
Should there be a difference?
Edit2:
Seems to be working as it should on production servers as well. Will have to do more research on what the cause can be.
Edit3:
Seem that the one causing the problem was in the registry LogRewrittenUrlEnabled was set to false to allow url rewrites at the same time as using dynamic content compression (gzip) so will have to find another way to enable this
You're right, the cache-buster hash should change if you change the contents of a script. There's some useful information about how the cache for bundling works that may help you here ASP.NET MVC Bundling cache. (Detecting css files changes) (internal behaviour).
The problem was that on the server we had in the registry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\InetStp\Rewrite /v LogRewrittenUrlEnabled set to false
And if you have that then the cache-buster hash is not refreshing when the content i bundle is changed.
I can't seem to get the javascript files to update in VS2013, asp.net using bundles. The image is after I have done a clean/rebuild, bundle clear and resetall, and deleted the browser history in IE (including cookies, website data, temp files and website files.) I have wasted day after day trying to get my site working. I have googled this a hundred times and found no satisfactory answers. What am I missing? There has got to be an easy way to do this.
As I said in the comment, don't use bundles during development of javascript or CSS files at all.
Just comment out the part where the bundle is rendered and include the corresponding files the classic way like this:
<script src="~/Scripts/myscript.js?v=#DateTime.Now.Ticks" type="text/javascript"></script>
When deploying the project remove that line and reactivate the previously commented bundle-rendering call.
Because the uri-parameter version string of the "classic-approach" is changing on each request you can be sure that you always have the latest version of javascript file and are not dependent on some CacheDependency of the Bundle-Framework to trigger or update (which apparently is not working all of the time).
Just don't forget to remove that manual script include so that your users' browsers can actually cache the resources.
I have added a custom button, with url + javascript by chaning the isv xml file, as described on
http://msdn.microsoft.com/en-us/library/cc150860.aspx
and all works fine. However, when I try and replace the file in the /ISV/ folder, it behaves the same as the original copy, I assume this is caching related. However, if I access the file from outside the CRM that is http://server/ISV/file.htm it has the latest and correct version. How do I get around this caching issue.
Thanks
So your ISV Option points to "/ISV/file.htm"? I think in the past I've noticed CRM's IIS site caching static files for 3 days. What I would do is when you replace your file.htm in your ISV folder, also update the ISV.config:
So change it to point to "/ISV/file.htm?vers=00001" and then increment each time you update the file.
I'm working on a site where the images and other resources will be located on a separate domain from the main content of the site. We will use something like 'www.example.com' for the main site, and then 'images.example.com' for all extra resources for styles, etc.
When developing the site I will keep all of these resources on local dev. machines. The challenge here is keeping CSS references consistent between the production server and development environments.
What I was thinking of doing was creating a web.config key that would store the URL of the images server. Then, when switching from development to production I could just change the web.config value and everything would be done.
Is there any way to add a value to a CSS file, dynamically or otherwise, from some place in a config or C# class? Or am I going about this the wrong way?
Also, I'm limited to using .NET 2.0 if that makes a difference.
UPDATE
To expand on this a little more, I know I can use a web.config setting for server controls' URLs. Those are already generated dynamically. What I'm more interested in is what options I have for modifying (or doing "something") to static CSS files that will allow me to change URLs for things such as background image resources that would be referenced in CSS. Is there anything I can do besides find/replacing the values using my IDE? Perhaps something that can be done automatically with a deployment script?
Is keeping the CSS file on the image server an option? If that it possible, you could make all the image references relative, and then you just need to update the link to the css file.
<link rel="stylesheet" href="<%= ConfigurationManager.AppSettings("css-server") %>style.css" />
If you still want to send or generate a css file dynamically:
css files don't have to end in css. aspx is fine. You could do this:
<link rel="stylesheet" href="style.aspx" />
and then in your style.aspx page:
protected void page_load(){
Response.ContentType = "text/css";
if (ConfigurationManager.AppSettings("css-server") == "local") {
Server.Transfer("css/local.css");
} else {
Server.Transfer("css/production.css");
}
}
If you still want to dynamically generate a css file, I'd use an HttpHandler, set the contenttype to "text/css", then generate the css with Response.Write. If you insist on having the page end in css, you could always register css to go to asp.net in IIS, then on incoming requests in global.asax application_Begin request, if the file ends in .css, use httpcontext.current.rewritepath to your handler.
This will have a net effect of style.css being dynamically generated at runtime.
What about putting a place holder on the web page and then selecting which CSS file to utilize (PROD, TEST, etc.) at run time and add it to the place hodler?
I think that Update had the right idea...
<link rel="stylesheet" href="<%= ConfigurationManager.AppSettings("css-server") %>style.css" />
Sounds like a job for a NAnt [link] script to me. They're pretty easy to work with and well documented.
That way your code has isn't changing your css links, they're being updated at deploy time. This isn't a code issue, it's a deployment issue, so addressing it as such feels more "right" to me. That way you know if it loads correctly (with the right images) the first time it will load every time. NAnt scripts are a good thing to have in your toolbox.
The other solutions will work, but that code will be running every time the page loads for a change that should have happened once -- when the app was deployed.
You duped your own question:
https://stackoverflow.com/questions/449236/dynamically-setting-css-values-using-asp-net
This is a common problem. What we do is have seperate web.config files for each environment. There is a appSettings key in the web.config and any config values go there like this.
<appSettings>
<add key="ImagePath" value="d:\websites\www.site.com\www\images\" />
<appSettings>
When setting the image control in the code behind, use the following:
myImage.ImageUrl = + _
System.Configuration.ConfigurationSettings.AppSettings("ImagePath") + "image1234567890.jpg"
Just change your ImagePath key to correspond with the path on the production or qa servers. Also, you could make the test server have the same path, but in my experience this solution works.
I would create a server control for my CSS that registered the css script block on page load. You could very easily change all paths at that point programmatically.
Perhaps you can do something with the hosts file on your dev server(s)? That way you won't have to actually change any code.
It IS possible to send files with the .css extension through the asp.net engine, though. You could also have .ashx handlers that return valid css and reference those handlers in the tags. Seems like kind of a waste of processor for stuff that is 90% static text though.