I have a site that gets deployed to over a dozen clients. The main website has a base template, and each client has a client folder that overrides the colours. The problem is that there are a lot of CSS files, so making a change that forces us to update every client takes a long time. The automated build process takes care of replacing the updated files.
I would like to change the CSS files to be usercontrols instead, and those usercontrols could then inherit from another usercontrol where client specific values are stored.
So instead of having a forms.css file and then a /client/forms.css file I would have a Forms.ascx file that inherits from a usercontrol that contains the colours.
Ex:
<%# Control Language="C#" ClassName="Forms" %>
<%# Register TagPrefix="css" TagName="Client" Src="~/css/ClientStyling.ascx" %>
/* CSS Document */
body
{
color:<%=Client.BodyColor%>
}
Then the masterpage would inherit from the usercontrol instead. This would make the maintenance of the client sites much easier.
So is this solution efficient and recommended? Or is there a better way to accomplish the same end result?
If this is possible, would it also be possible to have the Forms.ascx control output the markup as CSS? Or make the extension .css and still have the ascx properties?
Instead of a Web Control, you're likely better off creating a Generic Handler. This won't have the overhead that a web control has.
In your handler, accept the clientID via querystring - this allows you to cache on a client level
In your .master file, you can link to it < link src="MyCssHandler.ashx?ClientID=<%=ClientID%>" >
In your handler you have a few ways to work with the CSS.
Just have a bunch of response.write for the css, and put in relevant client values
Create an external CSS file with it's own special identifier - maybe <% %>. You could then load all the client specific values in a NameValuePair Collection, and then loop through the external CSS file, parsing <% NAME %> and replacing with the correct value. Then response.write this file. More complicated true but it allows for a hell of a lot cleaner CSS files
Another option to consider may just be to use a "CSS compiler" -- such as SASS, LESS or even HSS which may support handy constructs like "mixins" and including other files. This approach may allow a system that, while not dynamic, is easily configurable to your different client's needs.
For instance, with a "CSS compiler" the entire color schema could be stored in a single file as exportable variables or templates (depends on "compiler") -- modify that file, "recompile"** and wham, new color-scheme interface is everywhere (SASS also supports math on colors -- such as Hue shifting). This may make the deployment/management of using static content feasible enough for your purposes.
I use SASS (it fit my needs/style whereas LESS/HSS did not). I would not switch back unless I really, really had to (which is to say: uhh, never) -- SASS in SCSS mode also understands CSS syntax so you can micro-evolve or mix and match (LESS and HSS also work like this, but HSS only works with a stricter subset of CSS syntax). CSS compilers can also be used in conjunction templates engines (such as TT4) or take advantage of including dynamically generated files (not dynamic-dynamic as in the question, but dynamic in the sense that they come from some other data-source) if extra power is needed.
While just normal CSS cascading and class names/selectors can go a long ways, I find it much easier to separate the "logical cascade" (CSS, where CSS/cascading is vital) and "geeze, I wish this worked like a template" (CSS compiler, which should handle cases where CSS/cascading is abused).
** Both SASS and LESS can monitor files and recompile them automatically for you. SASS even allows monitoring entire directories
Write it out as a file and let the browser pick it up as it would any other CSS file.
Making inline stylesheets prevents the client cache mechanism, forcing your CSS to be served up with every page.
This is entirely possible. You might want to consider cascading your stylesheets too, so that the dynamic one imports a (presumably larger) static one.
Asp.NET has support for themes, too, but to be honest CSS is much more powerful.
Why are you thinking ASCX instead of ASPX though? I'd have thought that since one css file represents an entire response, it could all fit in a page.
an ashx is probably the lightest, fastest form of handler you can implement, so you might want to look at that...
Oh and make sure you get your caching parameters right!
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.
I want to be able to "A" dynamically generate a CSS file - or "B" be able to read a css file and change certain attributes of the CSS classes in C#.
Reason being, I have site that is going to be configured to a user's company, utilizing their colors, logos, text sizes, etc...
The first thought was to dynamically create a CSS file - but I can't find anywhere on the net where anyone shows examples or whatnot. The second thought was to read the css file and change the CSS classes based on a user's login.
Is there a simple way to do either?
Generally this is handled in a few different ways. You could include an additional or different CSS file based on properties of the request (e.g. current site). You could also output HTML that includes different classes based on request properties. A common technique is to add classes to root elements like or when certain conditions are met, and then write CSS to make use of those classes.
For example, if you are using the same code base for multiple sites, on site A you could have <html class="site-a"> and on site B you'd have <html class="site-b">. Then you can override styles based on the site easily.
/* Default to white background */
body {
background: white;
}
/* Use a black background for Site A */
.site-a body {
background: black;
}
/* Use a blue background for Site B */
.site-b body {
background: blue;
}
This is of course a very simple example. In the case of entire sites, separate CSS files makes more architectural sense, as you'd store them along with other site specific files.
I recommend studying more around how applications typically organize their front end presentation layers and files. For example, MVC is a way to separate out parts of an application. Within the context of presentation, you have concepts like templates and themes to encapsulate parts of the UI and turn it into reusable parts.
EDIT: Lost in my answer is that I didn't talk about actually dynamically generating CSS files. This is because dynamically generating CSS files is uncommon and generally not the right solution to a problem. As commentors have pointed out, there are CSS preprocessors like LESS and SASS which are generally targeted at solving some of CSSs internal issues (mostly redundancy). Preprocessors fix problems with CSS and are extremely useful, but aren't used in the way that it sounds like you've asked about. Separate CSS files or CSS files that key off of different classes and IDs are the solution, not dynamically creating a CSS file or block with different property values.
It seems rather convenient. I was wondering if there was a good reason to load one of the RegisterScript methods.
The RegisterScript methods can be used without placing any markup in the page, and without knowing the specific type of the page. Also, you can add the same script more than once, and it will only be included once in the page.
This is convenient when you want to include script from a user control, as you then can use the control in different pages, and more than once in the same page.
Maybe I'm wrong, but I don't recall RegisterScript methods working on pages without a <form runat="server">...</form>. That bit me once. In those cases, using literals or placeholders is not a particularly bad option. The other options I can think of is to make sure the head tag (or some other useful tag) has runat="server" and then dynamically add to it.
Depends on what you are trying to achieve. Do you really need to generate the javascript dynamically? You could just create a separate js file and reuse that.
As with the RegisterScript methods you can control where you want to place the javascript. For example with RegisterStartupScript, it registers your script at the end of the page (helps perceived performance and ensure that all objects have been loaded)
If you use literal controls, you might have to remember to but it at the end or top of page.
I'm developing a newsletter in asp.net that will be send to a large quantity of users, so each kilobyte that I can reduce will help a lot in the use of bandwidth consumption, what I do until know is write the aspx excluding some spaces between tags, and before render, i've renamed some controls ids to "-" to save more space.
So now, the file has 50kb. I need a file with 25 Kb.
Can anyone teach me any other way do save more space ?
ps.: I Use 3 divs with some data, and 2 repeaters, one inside other, to generate a table with some data for me.
EDIT: I've disabled viewstate, and remove unnecessary divs, I'll try to verify if gzip is enabled in IIS.
thanks in advance
Make sure HTTP compression is enabled. It will help to reduce the amount of HTML, but enabling HTTP compression will give more than the marginal improvements you're likely to see.
There are different ways to enable compression, depending on your version of IIS. For instance, in IIS 6.0, you can manually edit metabase.xml or run:
cscript adsutil.vbs set w3svc/filters/compression/parameters/HcDoDynamicCompression true
You can check HTTP headers to verify that compression is enabled using something like https://addons.mozilla.org/en-US/firefox/addon/3829/ Live HTTP Headers for Firefox. Check your headers for "Content-Encoding: gzip".
Don't use an aspx page if you want full control. Make a Generic Handler, and then you can have full control over every byte generated.
Instead of using Repeaters, just loop through a dataset and output tables or spans or something. Although, I have to say, repeaters are very easy to control the exact output of, too.
Look at your generated html and see if you can identify any obvious culprits.
You can disable the viewstate and optimize image files if you are using any.
I recommend going over this article if your using ASP.Net Web Forms - explains how to correctly utilize ViewState:
http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/Truly-Understanding-Viewstate.aspx
You might want to look into IIS Compression(it uses gzip IIRC). That should knock the file size down.
Also minify the javascript/css(I've done that and seen up to 40% reduction on js/css file sizes), here's a link to a book/website that talks about other things you can do: http://developer.yahoo.com/performance/rules.html, the book's title is "High Performance Web Sites", the ISBN: 978-0-596-52930-7
It may not work out to much savings, but you can also reduce markup by seriously considering whether to use DIVs for styling purposes when styling the contents directly would achieve the same result.
For instance,
<div class="sidebar">
<ul>
<li>Lorem</li>
</ul>
</div>
In most cases you can get the same result from styling the UL directly:
<ul class="sidebar">
<li>Lorem</li>
</ul>
But in your case, the repeaters are probably the main source of the bloat. Make sure you're using a custom template for them with clean HTML, and not relying on the out of the box rendering, which can be quite messy.
Like someone else posted, turn off viewstate for any controls you don't need it on - that's a TON of junk alone.
Is there a c# command to include another web page - the equivelant of the php require?
I know how to do server side includes but was looking for something code based.
Thanks
Thanks for the answers all. I think I might need to explain further. I have several sub-pages that I will be loading during the use of the site using an xmlhttp request. Initially however, I need to load the starting sub-page before the user has interacted with the site. I could do this with js, but that would require more overhead in server calls from the client for the initial load. I already use master pages, but this is a little different. Since this is done serverside initally but must remain able to be refreshed clientside, I don't think I can make these pages into controls can I? I am pretty new to .Net so I may be making my life harder than I need to.
I think what you may be looking for are MasterPages and UserControls. A MasterPage allows you to define a basic template that is "filled in" by the implementing pages by having the implementing page add it's own content to the ContentPlaceHolders defined on the MasterPage. A UserControl is a re-usable piece of markup and associated code that you can reference from your mark up or add dynamically to the page being rendered in codebehind.
The way ASP.NET is structured, you shouldn't really need to do this. Code is compiled, so all of your classes and functions should be accessible simply by referencing the relevant assembly or namespace, without having to include individual code files.
You might be looking for user controls, which allow you to create fragments of markup with their corresponding code behind, and then reference these in your page.
With ASP.NET MVC it looks like this:
<% Html.RenderPartial("LogOnUserControl"); %>
This way you can put another UserControl on your page.
you can use include in asp.net like php include from below mentioned code
<!--#include file="include/leftmenuscript.inc"-->
You can also use a master page, as someone stated below, which flushes out your basic layout and lets you define content place holders, which other pages can implement and fill in the content. Master pages are a popular approach for defining page elements that are consistent across all pages, like your nav there (also things like headers, footers, common scripts, CSS, etc.).