Compiling with wrong attributes - asp.net

We have an asp.net custom control which is used in our webforms asp.net project. I renamed a control's property and expected to get a compile time error in a place where this property is used as an attribute but it doesn't happen. Why is it so?

ASP.NET markup isn't actually schema-checked, at compile time or even at runtime. You're perfectly within your rights to write any old tag soup you like - ASP.NET won't complain unless you explicitly do something that doesn't make sense.
<asp:Label runat="server" fjsdkfj="sdjkfldskfls">Hello</asp:Label>
Put the above on an aspx and you will get no complaint at compilation, nor even at runtime - you'll just get
<span fjsdkfj="sdjkfldskfls">Hello</span>
send to the browser. However, do
<asp:Label runat="server" fjsdkfj="sdjkfldskfls" Height="ohdear">Hello</asp:Label>
and at runtime you'll get a parser error, as ASP.NET attempts to convert ohdear into a height value.
To find this second type of error earlier, you can use ASP.NET precompilation. To find the first category of errors, I know of no other way than testing - even ReSharper appears not to offer any useful inspection.

Related

New runat="server" div element on aspx, does it require compiling?

A new div element with a runat="server" property added to an ASP.NET presentation control does not require compilation, but can anyone explain why this works without a rebuild? If you were to perform a rebuild would the assemblies contain any new information?
I am trying to understand how the .NET framework treats these changes and why runat="server" controls can be added without rebuilding the related assemblies.
When adding new runat="server" controls the related designer files are updated to include additional references, therefore the compiled output differs.
Does anyone know what tools I could use to examine assemblies in this level of detail and perform side-by-side comparisons to identify minor alterations in their content?
It will work without a rebuild, so why do I care?
I have a fix for a current project which involves the addition of a new runat="server" div element and I need to know if I can deploy this fix without new assemblies.
I know it will work, but I need to know the technical differences (if any) between deploying just the aspx files and deploying the aspx files with a rebuilt dll.
This question was raised to help write a deployment process for a production environment I had no direct access to. The client was particularly hot on tracking changes and maintaining a clear audit trail.
Deployment packages for hotfixes would have to be small for rapid production and deployment, but must ensure environments match.
It works because you only changed the markup so the new HTML div will be rendered in the page and nothing is going to break because the code behind is not aware of the new control so does not even try to use it.
All html controls like div, tr-s, td-s and etc. are located in aspx file and adding runat="server" will not require rebuild. This will basically convert them into server-side controls, and they will be processed with full asp.net lifecycle.
But you need to remember, as soon as you will use it for example: Div1.Visible = false; it will require rebuild.
Looking back through unanswered questions, providing updates where possible.
This question was raised in an attempt to understand the inner workings of the .NET framework in regards to runat="server" controls.
When adding a new control I can see the designer files changing which would suggest that on build the related dll would differ.
However, you could make the change to the aspx element and deploy this without a new dll and it would work fine, there would be no error thrown saying the aspx included a runat="server" control that the assembly did not know about.
It was this relaxed handling of runat="server" controls I was trying to understand.
Useful tools
For anyone interested in understanding compilation output, assemblies can be decompiled to view their content using tools such as:
https://www.jetbrains.com/decompiler/
http://ilspy.net/
FYI: Using a decompiler I can see that the reference is included in the dll, meaning adding a runat="server" control will change your assemblies. If environments must be identical, then assemblies must be deployed.

Does ASP.NET use reflection to check for existance of event handlers?

I create an asp.net page e.g. default.aspx.
I then define a button...
<asp:Button ID="btnNew" runat="server" Text="New" OnClick="btnNew_OnClick" />
... however I do not define the handler for btnNew_OnClick in code.
ASP.Net will tell me this when I start the page and throw an exception.
Therefore, does it use reflection to check if the class that implements my page has this method ?
Is this efficient if it has to do this each time it parses a page's markup?
Not specifically. This happens when ASP.NET compiles your ASPX markup. ASPX markup is compiled the first time the page is hit on the fly, and stored somewhere in C:\WINDOWS\Microsoft.NET\Framework\vX\Temporary ASP.NET Files.
The exception to that is if you precompile your pages using aspnet_compiler.exe. However, if you were to pre-compile it you'd see there error there, not when you hit the site.
Is this efficient if it has to do this each time it parses a page's markup?
ASP.NET isn't parsing the markup on every page view and post back; it's only parsing it once when it's compiled. It stored a hash of the page (usually called hash.web somewhere in Temporary ASP.NET Files) and compares the hashes. If the hash is different (the page changed) then it recompiles it. Here is an example of what that compiled code may look like:
#line 58 "C:\X\UserControls\FilterControl.ascx"
#__ctrl.Click -= new System.EventHandler(this.btnApply_Click);
#line default
#line hidden
#line 58 "C:\X\UserControls\FilterControl.ascx"
#__ctrl.Click += new System.EventHandler(this.btnApply_Click);
This of course gets compiled into an executable assembly. Effectively, what the ASPX compiler is doing is compiling the server side markup into C# code, then compiler that into an assembly.
ASP.NET actually generates a class descending from your page using the ASPX markup as a template of sorts. You can find the generated classes source code in the folders under %WINDIR%\Microsoft.NET\v[FRAMEWORK VERSION]\Temporary ASP.NET File.
My understanding is it generates a class which instantiates the control and wires the event handlers to whatever method applies. This is why things break badly when you, say, make your event handler private -- the descendant class can't access it.
The code generation is pretty expensive up-front; it is partially responsible for that lengthy asp.net warm-up most of us asp.net developers suffer through. But it is very, very efficient once the app gets warmed up as everything is rendering via compiled code.
No it does not use reflection. As #Wyatt Barnett said, the compiler generates code for this. The generated code is the same as if you would register the event yourself.
btnNew.Click += new EventHandler(btnNew_Click);
As the code for the markup is generated it is the same regarding performance, maybe except for the first call.

Is it possible to modify ASP.NET to no longer require runat="server"?

I know why runat="server" is currently required (ASP.NET why runat="server"), but the consensus is that it should not be required if you incorporate a simple default into the design (I agree of course).
Would it be possible to modify, extend, decompile and recreate, intercept or otherwise change the behavior of how ASP.NET parses ASPX and ASCX files so that runat="server" would no longer be required? For instance, I assume that a version of Mono could be branched to accomplish this goal.
In case specific requirements are helpful, the following highlights one design:
During parsing, when configured namespace tags are encountered (such as "asp"), default the element's runat property to "server"
During parsing, when configured namespace tags are encountered (such as "asp"), if the element's runat property value is available, then that value should be used in place of the default
New page-level setting introduced (can be set in the page directive or web.config) that specifies the default runat value for a specific namespace tag
I'm afraid you'd have to modify the entire page parser to accomplish this, and I don't think that's possible.
On the other hand, you should be able to create your own. See the buildProviders Element and the BuildProvider class. You should be able to create your own build provider for .aspx pages and use it to replace the built-in provider.
Unfortunately, the PageBuildProvider class used by ASP.NET is internal, and the PageParser class that it uses to parse pages is sealed. You'll be entirely on your own.
Consider that runat="server" has been in ASP.NET for a decade now, and I think you'll see that this won't change anytime soon.
You'd also lose Designer support, but maybe you don't care about that.
So far as I know, there are no hooks deep enough in the ASP.NET Page handling process that would allow this. I know of no way to override or extend the parsing or processing of actual aspx/ascx code.
While ASP.NET is fairly flexible and lets your override many default behaviors (like how ViewState is saved/loaded, where Session is stored, etc) this is not one of them.
However... technically the Page object is just another HttpHandler. You could write your handler and do anything you wanted with it. All you have to do is implement everything the Page class does and then throw in this extra functionality. :) Alternately, pull out Reflector and dig through the Page object's ProcessRequest method and see where it is actually parsing/initializing the objects declared in aspx and you might get a clue how to implement the functionality you're looking for. But I suspect you'd be wasting your time.

Custom control with invalid property generates no error

for examle
<app:CustomDropDown ID="test" runat="server" InvalidProperty="SOMETHING" />
This does not generate an error. Sometimes i spend hours trying to figure out why my custom controls are displaying no data. Most of the time it turns out they are using and old non existing property and yet no error is generated on execution.
What could cause this?
You're not getting an error because, technically, there's nothing wrong with the markup. ASP.NET will pass any un-recognized attributes through to the page.
This can be useful if you want to use some non-standard attributes to store extra data for some reason and then access it later through the DOM.

Why does ASP.NET webforms need the Runat="Server" attribute?

Why do I have to specify runat="server" on all my ASP.NET controls when it is a mandatory attribute and server is the only option available in my limited knowledge of ASP.NET, and I get an error if I don't use it?
I do understand that I can optionally use it on my HTML tags, and I do understand the client/server paradigm and what it is actually specifying.
Is it a redundant tag that could just be implied by the control being an ASP.NET control, or is there an underlying reason?
I've always believed it was there more for the understanding that you can mix ASP.NET tags and HTML Tags, and HTML Tags have the option of either being runat="server" or not. It doesn't hurt anything to leave the tag in, and it causes a compiler error to take it out. The more things you imply about web language, the less easy it is for a budding programmer to come in and learn it. That's as good a reason as any to be verbose about tag attributes.
This conversation was had on Mike Schinkel's Blog between himself and Talbot Crowell of Microsoft National Services. The relevant information is below (first paragraph paraphrased due to grammatical errors in source):
[...] but the importance of <runat="server"> is more for consistency and extensibility.
If the developer has to mark some tags (viz. <asp: />) for the ASP.NET Engine to ignore, then there's also the potential issue of namespace collisions among tags and future enhancements. By requiring the <runat="server"> attribute, this is negated.
It continues:
If <runat=client> was required for all client-side tags, the parser would need to parse all tags and strip out the <runat=client> part.
He continues:
Currently,
If my guess is correct, the parser
simply ignores all text (tags or no
tags) unless it is a tag with the
runat=server attribute or a “<%”
prefix or ssi “<!– #include… (...)
Also, since ASP.NET is designed to
allow separation of the web designers
(foo.aspx) from the web developers
(foo.aspx.vb), the web designers can
use their own web designer tools to
place HTML and client-side JavaScript
without having to know about ASP.NET
specific tags or attributes.
I usually don't like to guess, but I'm going to on this one...
If you remember Microsoft's .NET marketing hype back in the day (2001?), it was hard to tell what .NET even was. Was it a server? a programming platform? a language? something new entirely? Given the ads, it was ambiguously anything you wanted it to be - it just solved any problem you might have.
So, my guess is there was a hidden grand vision that ASP.NET code could run anywhere - server side OR client side, in a copy of Internet Explorer tied to the .NET runtime. runat="server" is just a vestigial remnant, left behind because it's client-side equivalent never made it to production.
Remember those weird ads?
Related: Article from The Register with some .NET history.
Not all controls that can be included in a page must be run at the server. For example:
<INPUT type="submit" runat=server />
This is essentially the same as:
<asp:Button runat=server />
Remove the runat=server tag from the first one and you have a standard HTML button that runs in the browser. There are reasons for and against running a particular control at the server, and there is no way for ASP.NET to "assume" what you want based on the HTML markup you include. It might be possible to "infer" the runat=server for the <asp:XXX /> family of controls, but my guess is that Microsoft would consider that a hack to the markup syntax and ASP.NET engine.
Microsoft Msdn article The Forgotten Controls: HTML Server Controls explains use of runat="server" with an example on text box <input type="text"> by converting it to <input type="text" id="Textbox1" runat="server">
Doing this will give you programmatic access to the HTML element on
the server before the Web page is created and sent down to the client.
The HTML element must contain an id attribute. This attribute serves
as an identity for the element and enables you to program to elements
by their specific IDs. In addition to this attribute, the HTML element
must contain runat="server". This tells the processing server that the
tag is processed on the server and is not to be considered a
traditional HTML element.
In short, to enable programmatic access to the HTML element add runat="server" to it.
My suspicion is that it has to do with how server-side controls are identified during processing. Rather than having to check every control at runtime by name to determine whether server-side processing needs to be done, it does a selection on the internal node representation by tag. The compiler checks to make sure that all controls that require server tags have them during the validation step.
HTML elements in ASP.NET files are, by default, treated as text. To make these elements programmable, add a runat="server" attribute to the HTML element. This attribute indicates that the element should be treated as a server control.
It's there because all controls in ASP .NET inherit from System.Web.UI.Control which has the "runat" attribute.
in the class System.Web.UI.HTMLControl, the attribute is not required, however, in the class System.Web.UI.WebControl the attribute is required.
edit:
let me be more specific. since asp.net is pretty much an abstract of HTML, the compiler needs some sort of directive so that it knows that specific tag needs to run server-side. if that attribute wasn't there then is wouldn't know to process it on the server first. if it isn't there it assumes it is regular markup and passes it to the client.
I think that Microsoft can fix this ambiguity by making the compiler add runat attribute before the page is ever compiled, something like the type-erasure thing that java has with the generics, instead of erasing, it could be writing runat=server wherever it sees asp: prefix for tags, so the developer would not need to worry about it.
If you use it on normal html tags, it means that you can programatically manipulate them in event handlers etc, eg change the href or class of an anchor tag on page load... only do that if you have to, because vanilla html tags go faster.
As far as user controls and server controls, no, they just wont work without them, without having delved into the innards of the aspx preprocessor, couldn't say exactly why, but would take a guess that for probably good reasons, they just wrote the parser that way, looking for things explicitly marked as "do something".
If #JonSkeet is around anywhere, he will probably be able to provide a much better answer.
When submitting the data to ASP.NET Web server the controls mentioned as Runat = “server” will be represented as Dot Net objects in Server Application. You can manually type the code in HTML controls or else can use Run As Server option by right clicking in design view.
ASP.NET controls will automatically get this attribute once you drag it from toolbox where usually HTML controls don't.
Pretty redundant attribute, considering the "asp" tag is obviously an ASP element and should be enough to identify it as a server side accessible element.
Elsewhere however it used to elevate normal tags to be used in the code-behind.
I just came to this conclusion by trial-and-error:
runat="server" is needed to access the elements at run-time on server side.
Remove them, recompile and watch what happens.
Any tag with runat=server is added as server control in Page and any html content between is handled as LiteralControls which are also added to Page controls collection.
runat="Server" indicates a postback to the server will occur for the HTML "control."
Web Forms use postback constantly to signal the server to process a page control event.
.NET MVC pages DO NOT use postback (except for a form "submit"). MVC relies on JQUERY to manage the page on the client side (thus bypassing the need for a lot of postback messages to the server).
So:
.NET Web Forms... use "runat" attribute a lot in the page markup.
.NET MVC hardly ever uses "runat" attribute in the page markup.
Hope this helps clarify why runat is necessary...

Resources