views:

103

answers:

2

Hi there...

I tried to google this and came up a little short, so maybe someone here can shed some light on the topic.

For url rewriting purposes in asp.net, I would like to declare all images and other resources in my application with the runat="server" attribute to take advantage of the "~/images" server path syntax. Debugging on locahost is especially difficult when relative paths are used (when using url rewriting). I know I can modify the host files to somewhat overcome this problem, but this is not feasible due to the volume of projects we work on.

Declaring html controls to runat server would normally add to the viewstate to enable data persistence, but this would not be relevant to images, or am I mistaken with regards to this...?

I also realise that there are more controls for the asp net runtime engine to process and handle, but is this really a serious performance drain...?

Is there a serious overhead in declaring images in this manner, and if so, could someone explain where exactly the bulk of the performance knock will come from.

Thanks in advance.

A: 

There is a significant relative overhead even assuming you've turned off all the viewstate marlarky. However the absolute cost is probably inperceptible to an individual user.

Consider a markup describing a series of HTML elements, It is treated as a simple literal "control" which very efficiently sends its entire contents to the response at the appropriate point in the page render.

Compare that with all the same elements being created as full controls with all the object creation, parsing of style element, validation etc and creation of local state. Then code runs to take the local state and pretty much render the same HTML markup used to define it in the ASP.NET page in the first place.

Clearly in terms of memory and CPU using a lot of runat="server" is going to more expensive. In an individual case this is probably not an issue but for a site with significant activity it could well be.

If you are developing an application which will be placed in some virtual directory in a larger site then use relative paths for your images.

If you are developing an application which is to a site of its own then in the project or site properties modify the Virtual path in the Developer Web Server category to be just "/". That way when debugging you don't have the extra /myprojectname/ part in the URL. This will allow you use an absolute path to some assets or images folder.

AnthonyWJones
Thanks for the reply Anthony... The problem with url rewriting and relative paths is that a page sitting at root /product.aspx?pid=1, could be rewritten as /products/productgroup/some-product.aspx. Thus, all images and resources declared on the page would no longer be valid. Secondly we use IIS to debug and simply attach to the w3wp.exe process, we don't use the web developer server thus also eliminating this option. I understand what you are saying with regards to the performance costs, and appreciate the info. I suppose it would depend on the nature of the site (traffic volume etc...)
gg
If you are re-writing URLs and this is a root site then simply use absolute paths for you images.
AnthonyWJones
+3  A: 

Assuming that you are asking for the differences between:

1) <img runat="server" EnableViewState="false" src="~/images/img.png" />

and

2) <img src='<%= ResolveUrl ("~/images/img.png") %>' />

To build 1), the actual code generated (more or less) is:

System.Web.UI.HtmlControls.HtmlImage __ctrl;
__ctrl = new System.Web.UI.HtmlControls.HtmlImage();
this._bctrl_1 = __ctrl;
__ctrl.EnableViewState = false;
__ctrl.Src = "~/image.png";

Then that __ctrl is added to the control tree:

__parser.AddParsedSubObject(this._bctrl_1); // _bctrl_1 is __ctrl from above

Any event in the page lifecycle (Init, Load...) will be propagated to this control, RenderControl will be called to get the HTML from it, ResolveUrl() is called to get the actual URL, and, finally, Dispose() will be called too.

Now, in case 2), the control is not added to its parent the normal way, but instead you get something like this:

__ctrl.SetRenderMethodDelegate(new System.Web.UI.RenderMethod(this.__RenderTree));

Which is setting a delegate that will be called when its time to render the <img>. In __RenderTree the part that writes the tag we're interested in is:

__output.Write("\n<img src='");
__output.Write( ResolveUrl ("~/image.png") );
__output.Write("' />\n");

So, yes, there's "a lot" of code being run in 1) that is not run in 2). Now, as far as the impact in actual execution time I think this is not that big of a deal. I tested an empty page with nothing but the img tag/control and the difference between them in several runs was in the range of -0.5ms/+0.5ms per request. Totally negligible.

Gonzalo
Exactly what I was looking for... thanks :) never thought about option 2... gg
gg