It can be quite handy to use the ~ with ResolveUrl or for url properties of server controls, however, it does not work for ordinary markup, for instance: <a href="~/Foo/Bar.aspx"></a>
would not work since you have to add the runat="server". You can work around this with the following if you happen to have access to Page: <a href="<%=ResolveUrl("~/Foo/Bar.aspx") %>"></a>
But what if you do not have access to Page? Well, there is the option of rolling your own ResolveUrl, which is the approach I have taken many times.
I am still on a mission brushing up on my ASP.NET and found a community comment on the MSDN Docs for ASP.NET Web Site Paths that has a out-of-the-box way of doing this as follows: <a href="<%=System.Web.VirtualPathUtility.ToAbsolute("~/Foo/Bar.aspx")%>"></a>
Very handy! and its been in since .NET 2.0 so it shows how much I am missing out on by not thumbing through the ASP.NET docs.
According to the ASP.NET Docs on XHTML Conformance if you try to validate an ASP.NET page with the W3C XHTML validation service it might not report it as valid XHTML simply because the W3C validation service does not report itself as a browser that ASP.NET recognises.
You can get around this problem by creating a browser definition in a .browser file that you put into your App_Browsers folder of your ASP.NET website.
Yoinked directly from the docs: <browsers> <browser id="W3C_Validator" parentID="default"> <identification> <userAgent match="^W3C_Validator" /> </identification> <capabilities> <capability name="browser" value="W3C Validator" /> <capability name="ecmaScriptVersion" value="1.2" /> <capability name="javascript" value="true" /> <capability name="supportsCss" value="true" /> <capability name="tables" value="true" /> <capability name="tagWriter" value="System.Web.UI.HtmlTextWriter" /> <capability name="w3cdomversion" value="1.0" /> </capabilities> </browser> </browsers>
This might just be handy to know at some point, although most good browser based web dev tool suites offer the ability to validate XHTML, and I believe they send the content to validate from rendered markup in your browser.
Yesterday, I thumbed through the C# Docs looking for stuff I might not know yet, and today I am doing the same thing for ASP.NET in hope to fill in some gaps that might help me with a technical interview I have coming up on tuesday.
This is something I did not know, in the web.config you can add a tag to define what level of XHTML compliance to render. <system.web> <!-- other elements here --> <xhtmlConformance mode="Legacy" /> </system.web>
Where mode could be one of 3 values (taken directly from the MSDN How to page for XHTML Conformance):
Legacy (which is similar to how markup was rendered in previous versions of ASP.NET)
Transitional (XHTML 1.0 Transitional)
Strict (XHTML 1.0 Strict)
Another keyword I have not used much is the new modifer, the MSDN docs for the new Modifer open up with the following:-
When used as a modifier, the new keyword explicitly hides a member inherited from a base class. When you hide an inherited member, the derived version of the member replaces the base-class version. Although you can hide members without the use of the new modifier, the result is a warning. If you use new to explicitly hide a member, it suppresses this warning and documents the fact that the derived version is intended as a replacement.
The new modifier has an interesting but important effect when casting, as the following example demonstrates. class Program
{
public class Animal
{
public void Say()
{
Console.WriteLine("I am an animal!");
}
}
public class Cat : Animal
{
public new void Say()
{
Console.WriteLine("Meeeoooooww!");
}
}
public class WildCat : Cat
{
public new void Say()
{
Console.WriteLine("ROAR!");
}
}
static void Main()
{
WildCat wildCat = new WildCat();
Cat cat = wildCat;
Animal animal = cat;
wildCat.Say();
cat.Say();
animal.Say();
}
}
The code outputs the following. ROAR! Meeeoooooww! I am an animal!
The code demonstrates when downcasting, WildCat and Cat use their own implementations of Say(), I am not sure I would want that type of behaviour, since it could be rather dangerous if its not used intentionally, but its interesting to know anyway.
public abstract class Animal{}
public class Cat : Animal
{}
public class Ornament
{
public static explicit operator Ornament(Cat cat)
{
return new Ornament();
}
}
class Program
{
static void Main()
{
Cat cat = new Cat();
// This line fails to compile
Ornament jug = cat as Ornament;
// this works with our explicit operator defined for Ornament
Ornament anotherJug = (Ornament)cat;
}
}
Well the holes in my C# knowledge never cease to amaze me, I mean, I knew what I could do with the as keyword but I did not know the subtle difference it has to a direct cast.
By using the as keyword to cast from one type to another, if the cast is not possible it will result in a null, however using a direct cast will throw an exception.
An example demonstrates the use of the as keyword. public abstract class Animal{}
public class Cat : Animal{}
public class Ornament{}
class Program
{
static void Main()
{
object cat = new Cat();
// jug will be null after this conversion since
// cat is not an Ornament
Ornament jug = cat as Ornament;
// this throws an InvalidCastException
jug = (Ornament) cat;
// This works since Cat is an Animal, animal will not
// have a reference to cat
Animal animal = cat as Animal;
}
}
Quite handy really, but there is one thing to note, notice that we say object cat = new Cat();? This is because we get a compilation error if we had used Cat cat = new Cat();
Cannot convert type 'ConsoleApplication1.Cat' to 'ConsoleApplication1.Ornament' via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion
The reason for this (I believe) is because of the limitation described in the MSDN Docs for the as keyword.
Note that the as operator only performs reference conversions and boxing conversions. The as operator cannot perform other conversions, such as user-defined conversions, which should instead be performed by using cast expressions.
An example below shows this, it has been slightly modified by adding an explicit cast operator to Ornament so we can use a cast expression for anotherJug to show the difference between a cast and a conversion with the as keyword, so as the docs say:- user-defined conversions do not work with the as keyword.
Well, smack me with a wet kipper, I have never really considered the difference between do and do while, since I have always just used a while loop.
Anyway, the difference is, that a do-while will always execute before checking the condtion, whereas a while loop, checks the condition before executing the code block.
Quite a fundamental difference that could prove to be useful, I definetly see a 'gotcha!' interview question from this one if it was ever asked. class Program
{
static void Main()
{
int x = 0;
// Will always output "Hello World"
do
{
Console.WriteLine("Hello World");
x++;
} while (x <= 0);
// Will not output anything
while (x <= 0)
{
Console.WriteLine("Hello World");
x++;
}
}
}
I had a great job interview for a great company on tuesday just gone, they are a Microsoft Gold Certified Partner so that suits me down to the ground since I am a Microsoft fanboy! I have a second stage interview with them that will be technical, so it would probably involve a test and lots of questions, so I have decided to put in some more study into my profession and brush up on stuff, starting with C#.
I think myself as a fairly good C# programmer, not the best, but fairly good, but, there are some things that I have never needed to learn, in this post I will look at the checked keyword. The checked keyword is used to control the overflow-checking context of integral-type arithmetic operations and conversions - cited from the msdn docs.
At first glance, since some things are not always clear to me, my thoughts are - what does this mean?
Well, if we take a byte, we know that a byte can only have maximum value of 255, so any greater value than 255 would result in an overflow.
So what checked does is - if you perform an arithmetic operation that results in an overflow, it will throw an OverflowException, the following example shows this. class Program
{
static void Main()
{
byte a = 200;
byte b = 200;
byte c = checked((byte)(a + b));
Console.WriteLine(c);
}
}
Without the checked, the calculation would wrap giving c a value of 144.
I have never needed to use this yet, but I guess if an important calculation was being performed then I would consider it, for instance if it was going to lose a lot of money!
I had a second interview today for a job that I am very keen on getting, after the interview it struck me that somehow I must have done something wrong, infact it was during the question 'Do you have any questions?' I realised that I had somehow missed an opportunity or somehow screwed up. Even further it was after something said to me along the lines of 'well, you are just one of a number and we will have some feedback for you as soon as possible', followed again by 'Do you have any questions?'.
This sounded a lot like 'This is your last chance to ask us some deal breaking questions right now?' but I am hoping that this is just the way that I percieved it. Still I had no questions. Well, saying that I did have one question but that was asking wether they had used LINQ to NHibernate and then following up on that by saying how great LINQ is, which ended up sounding like an instruction (according to one of the interviewers, I am not sure if it was meant literaly however it made me feel uncomfortable, like I just gave an instruction to use LINQ to NHibernate, but this is not what I was indicating).
Although this was the only question I did ask, I don't think it was the right question, I failed to ask about the job, about what I might be doing, what my responsibilities would be and where I would fit into the team, it stands to reason that if your going to a job and the job details do not specifically answer these questions then maybe they should be asked.
The thing that I think stopped me from asking them is that I just assumed that, since I am going for a C# Developer role that I would pretty much be involved in writing C# Code in answer to some business idea, plan or problem, which is infact the case since I was already told that the position involves writing B2B enterprise applications.
Reflecting on myself after this interview, I think I may have babbled to much, when asked a direct questions, I seem to have gave an entire story rather than a direct answer, I am not sure why I did this, I think it may have been that I felt I had to prove something, which, I guess I did since thats what your supposed to do in job interviews? right?
I still feel, that getting this job will be the next step in my career, even though it ended on an anti-climax, assuming that the interview was a climax or a superficial climax for me and an anti-climax for them with me babbling on that it made me seem as if I am some big head who knows it all.
Anyway, I hope I get this job!
Recently at a job interview during a technical test I had to answer a question:
What is the difference between a delegate and a multicast delegate?
Unfortunately I did not have the answer, I have used delegates plenty but I have never obviously used them enough to know this difference, and the dissapointing thing is that the answer was glaringly obvious.
A multicast delegate is multiple instances of the same delegate chained together using the + operator, Events in .NET make use of this to attach multiple event handlers to an event.
An example: public delegate void SaySomething(string something);
class Program
{
static void Main(string[] args)
{
// At first, something is just a delegate
SaySomething something = new SaySomething((s) => Console.WriteLine(s));
// By adding together more instances of the SaySomething delegate.
// we get a multicast delegate
something += new SaySomething((s) => Console.WriteLine(s.ToUpper()));
something += new SaySomething((s) => Console.WriteLine(s.ToLower()));
something("Hello");
}
}
The output would give:
Hello HELLO hello
It pains me to think I have now been at this for 6 years and there are still aspects to C# that I have not yet come across, yet I do not think of myself as a bad developer, I am sure there are plenty of things that I am aware of that the interviewer has no idea about, and it makes me wonder if the whole point is to see areas of where I could improve my knowledge, or the purpose is to scrutinise my knowledge in a way that an incorrect answer would make me out to be some kind of fraud.
I guess at least now if this question comes up again I will be able to answer it.
At work I was implementing a search form that required a 3 tier drop down, so I thought the CascadingDropDown would be perfect for this.
It turns out that the CascadingDropDown was not quite right for the requirements, the last drop down in the 3 tiers had to be enabled and items had to be selectable but also had to filter the other 2 upper tiers.
After some thought, the only way to achieve this was having the ability to programatically add my own values to be passed to the knownCategoryValues argument of the web service method for a CascadingDropDown behavior.
To do this, I had to redefine a method on the CascadingDropDown behavior, I could then invoke this method to force the ajax callback for any CascadingDropDown of my choice. Here is that method. AjaxControlToolkit.CascadingDropDownBehavior.prototype._onParentChange2 = function(evt, inInit, moreKnownCatValues) {
/// <summary>
/// Handler for the parent drop down's change event
/// </summary>
/// <param name="evt" type="Object">
/// Set by the browser when called as an event handler (unused here)
/// </param>
/// <param name="inInit" type="Boolean">
/// Whether this is being called from the initialize method
/// </param>
/// <returns />
var e = this.get_element();
// Create the known category/value pairs string for sending to the helper web service
// Follow parent pointers so that the complete state can be sent
// Format: 'name1:value1;name2:value2;...'
var knownCategoryValues = '';
var parentControlID = this._parentControlID;
while (parentControlID) {
var parentElement = $get(parentControlID);
if (parentElement && (-1 != parentElement.selectedIndex)) {
var selectedValue = parentElement.options[parentElement.selectedIndex].value;
if (selectedValue && selectedValue != "") {
knownCategoryValues = parentElement.CascadingDropDownCategory + ':' + selectedValue + ';' + knownCategoryValues;
parentControlID = parentElement.CascadingDropDownParentControlID;
continue;
}
}
break;
}
if (knownCategoryValues != '' && this._lastParentValues == knownCategoryValues) {
return;
}
this._lastParentValues = knownCategoryValues;
// we have a parent but it doesn't have a valid value
//
if (knownCategoryValues == '' && this._parentControlID) {
this._setOptions(null, inInit);
return;
}
// Show the loading text (if any)
this._setOptions(null, inInit, true);
if (this._servicePath && this._serviceMethod) {
// Raise the populating event and optionally cancel the web service invocation
var eventArgs = new Sys.CancelEventArgs();
this.raisePopulating(eventArgs);
if (eventArgs.get_cancel()) {
return;
}
if (moreKnownCatValues) {
knownCategoryValues += ";" + moreKnownCatValues;
}
// Create the service parameters and optionally add the context parameter
// (thereby determining which method signature we're expecting...)
var params = { knownCategoryValues: knownCategoryValues, category: this._category };
if (this._useContextKey) {
params.contextKey = this._contextKey;
}
// Call the helper web service
Sys.Net.WebServiceProxy.invoke(this._servicePath, this._serviceMethod, false, params,
Function.createDelegate(this, this._onMethodComplete), Function.createDelegate(this, this._onMethodError));
$common.updateFormToRefreshATDeviceBuffer();
}
}
The method above is just a copy of _onParentChange method of the CascadingDropDown behavior, I called it _onParentChange2 and call this one when I want to invoke an ajax callback, the only difference is the extra argument moreKnownCatValues, the value of this argument will be appended to the knownCategoryValues which will get passed to the callback method. The changes to the original method have been bolded.
Now its possible to invoke a callback on any CascadingDropDown with the code below. $find('CDD1')._onParentChange2(null, false, "CountryId:25");
The line above will get a reference to a CascadingDropDown behaviour that I have given a BehaviorID of CDD1, it will then invoke the new _onParentChange2 method passing through my extra value of CountryId:25.
Its a shame that the CascadingDropDown does not have a more elegant approach for adding to the knownCategoryValues programatically, but at least this workaround is not to hacky.
|