March 2005 - Posts
Stored Procedures rule, because they facilitate manipulating the dataset you get from a database or the way you are inserting or deleting data in a database without changing your application. Or your business layer for that matter. But you can’t always use stored procedures for the actions you would like your application to take. Or maybe your database doesn’t support stored procedures. In that case it’s back to queries for you! And that’s what I would like to talk about… queries. And how to protect them.
Please note: I’m not posting actual code. Normally, I would check the existence of querystring values, check if the ID is actually an integer and so on, but this is just a sample to get my point across. And believe me; I’ve seen pages constructed like this, or worse.
Let’s assume we’re writing a very simple webpage where we want to show the details for a customer. We pass the customer ID in the querystring. That way we can show the customer’s data. An example of such a URL:
URL: bloggingabout.net/rick/custinfo.aspx?custid=12
In the page called custinfo.aspx will be logic to grab the customer ID from the querystring and query the database for the data for this customer. Here’s where the interesting part begins. Let’s assume the query for the customer data is constructed as follows:
SqlClient.SqlCommand cmd = new SqlClient.SqlCommand();
cmd.CommandText = “Select * from customers where customers.customerID = “ + Request.QueryString[“custid”];
This works like a charm, as long as you have other pages redirecting to this page using only valid customer ID’s. Now think about what will happen when the visitor of a site sees this URL, and decides to change it to this:
URL: bloggingabout.net/rick/custinfo.aspx?custid=12;Delete from customers
query: Select * from customers where customers.customerID = 12;Delete from customers
You can imagine the impact of this query: first all data for customer with id 12 will be fetched. Next, your customers table will be emptied. And by changing everything after the semicolon the visitor is able to manipulate the entire database! This should never be possible. One of the ways to protect your (web) application from SQL injection is using parameterized queries:
SqlClient.SqlCommand cmd = new SqlClient.SqlCommand();
cmd.CommandText = “Select * from customers where customers.customerID = @custid“;
cmd.Parameters.Add(“@custid”, int.Parse(Request.QueryString[“custid”]));
No matter what is inserted in the querystring, the parameterized query sees the entire value as the value that should be assigned to the parameter and makes sure it gets it all.
FYI: in this example there would be an error (FormatException) when the user enters the wrong value for the querystring, because int.Parse wouldn’t be able to parse the querystring to an integer. Unfortunately you can’t rely on this kind of errors to stop all SQL injection so parameterized queries would be the way to go. ;)
After promising you a post on using delegates to create events several times, I’m now using my break to post it. Because it will be a while if I wait until I can find the time… ;)
As I mentioned earlier a delegate can be seen as an interface for a method. Because you don’t know what the method that will handle an event on your user control will look like, delegates are a great way to provide your user control with events. (For the basics on delegates see my post on them earlier).
First, you will have to declare the delegate that will be used to call the event. This is no different from the regular delegate declaration.
//Define public delegate
public delegate void OnLabelTextChanged(object sender, EventArgs e);
Next, you will have to declare a local variable to hold the method that handles your event. This way you can check if the eventhandler was implemented by the calling application. If it was, you can trigger the event. If it wasn’t, don’t ;)
//Declare local variable of delegate type
private OnLabelTextChanged ltcDelegate;
The last step is to add the event to the available events for the user control. You do this by declaring a public virtual event of the type you named your delegate. The text between the brackets places this event in the category “property changed” with the description “Text was changed”.
//Declare public event of delegate type
[Category("Property changed"), Description("Text was changed")]
public virtual event OnLabelTextChanged LabelTextChanged
{
//point event to local delegate variable
add
{
ltcDelegate += value;
}
remove
{
ltcDelegate -= value;
}
}
This way, the local variable (ltcDelegate in this example) will be null if the eventhandler was not implemented. If the eventhandler was implemented, you can call the eventhandler. In this example the eventhandler is triggered when the text for a label changes. This is the code in the property for the text:
[Category("Appearance"), DefaultValue("")]
public string LabelText
{
get
{
return _lbltxt;
}
set
{
_lbltxt = value;
lblDelTest.Text = _lbltxt;
//if eventhandler is implemented, trigger it
if (ltcDelegate != null)
{
ltcDelegate(this, EventArgs.Empty);
}
}
}
That's how easy it is to use delegates to create an event for your user control! If you have any questions: contact me through the contact page, or drop a line in the comments.
All I wanted to do was check if my application was running in debug-mode or in release-mode. Searching MSDN library and Google (groups) both did not deliver the solution to me. I was about to let go when, out of the blue, a webpage showed up in my browser telling me the following:
Visual Studio automatically generates a pre-processor directive called DEBUG which is linked to the mode you run your application in. Beware: these directives are case sensitive...
This meant an easy solution for my 'problem'!
Pre-processor directives can be defined using #define (making the directive true) and #undef (making it false) in C#. When you check one of these directives using an #if ... #else ... #endif statement Visual Studio even greys out the code that will not be compiled, because of the directives. This gives you a pretty good idea which code will and which code will not be compiled into the final assembly.
Because of the pre-processor directive behaviour, you can easily create cross-platform applications by simply changing one directive. Changing that one directive may change complete pieces of code in your application.
The answer to my question was simple:
#if (DEBUG)
imgPath = GetDirectoryName(Application.ExecutablePath);
#else
imgPath = GetDirectoryName(Application.ExecutablePath) + "\\images\\";
#endif
Yesterday I attended the Microsoft DevDays 2005 in The Hague. The MSDN TechNet briefings in Veldhoven I attended last year (was that October or November?) were great. Because the DevDays would (or should) be even greater I could hardly wait for DevDays 2005 to begin! Here's my short opinion on the DevDays 2005. Interested in a more elaborate version? Comment!
Keynote
Prashant Sridharan kicked off with a killer keynote. This guy alternated humour with fact, example with slides and gave an overall really good presentation. I listened to him with ease for almost one and a half hour and after that I was sure: the DevDays were going to be great!
Visual Studio Tools for Office 2005
The name could make you think otherwise, but this session was about Visual Studio (2005) Tools for Office (2003). Lex Oskam made the crowd enthusiastic about these tools, which make it possible to create rich applications within a Word or Excel document. Great session to follow Prashant's keynote.
Software factories
The guy who spoke here wanted to share a lot of information, and that's where it went wrong: the story he told was very scattered and sometimes he was quiet for just too long, indicating he himself lost the line of his story. Being complicated, software factories should be made concrete. Unfortunately this presentation stayed to abstract.
BizTalk in action
There were two guys for this session, and why became very clear during the first demo: one of them was there for the presentation, the other was the technical guy who actually knew how the stuff worked. His presenting skills were not all that good… The demos were too simple: “This is what we made and look, it works!”
ASP.NET Web Services 2.0
Starting out, this session promised to be one of the best of the day. The speaker was very good and told his story very interesting. Near the end he went in too deep, and lost some of his viewers. I think this session was too complicated to be given at the end of such a tiring day.
Overall
The DevDays didn’t bring what I hoped they would bring. The sessions I attended were mostly too abstract or too boring. The day started out great with the keynote and Lex Oskam’s presentation, from then on it seemed to get worse with every session.
Delegates can be seen as interfaces for methods. Let’s look at an example of a delegate and what it really represents.
delegate double Calculation(double one, double two);
All this line of code really does, is tell the class it is in that there might be one or more methods with the given signature: a method returning a double and taking two doubles as parameters. You cannot call a method Calculation now, because it does not have a body, so it doesn’t have any functionality. It’s just a blueprint for future reference. You’re saying something like: “You might find one or more methods somewhere having this signature which do something for you, but don’t ask me where or what they are called. Just be ready!” Next, let us create a method with the same signature as the delegate.
static double Multiply(double first, double second)
{
return (double)(first * second);
}
This method has the same signature as the delegate. But, just for fun, let’s make another…
static double Divide(double A, double B)
{
return (double)(A / B);
}
Notice that not only the names of the two methods are different, even the parameter names are not the same. The delegate doesn’t care: you have defined it for methods returning a double, and taking two doubles as parameters and that’s all that matters to the delegate. The delegate now lets you call either one of these methods using a new object of the delegate you declared:
Calculation calc = new Calculation([functionname]);
Substitute [functionname] with the name of the function you would like to use, and you are ready to go:
Calculation calc = new Calculation(Multiply);
double answer = calc(50, 4);
Result for answer here is 200.
or
Calculation calc = new Calculation(Divide);
double answer = calc(50, 4);
Result for answer here is 12.5.Because the delegate was created stating it had to return a double and would take two doubles as parameters, it’s enough to pass the method name to the creator of the new delegate. This will only accept names of methods that have the right signature. Otherwise, you will get an error stating
Method ‘method name’ does not match delegate ‘complete delegate statement’.
In my next post I will be showing how delegates can be used to create eventhandlers.
When using XmlSerializer in .Net on a self-made class, you might receive the FileNotFound exception at runtime upon instantiating the serializer. You don't get enough info to debug this problem, and the filename of the file it didn't find can't explain much either, because the dll-name is different 'garbage' every time.
Chris Sells has developed the
XmlSerializerPreCompiler tool, which gives you more info about why instantiating an XmlSerializer for your class won't fly.
The XmlSerializer PreCompiler is a command-line program that performs the same steps as the constructor of the XmlSerializer. It reflects over a type, generates serialization classes, and compiles them. Any compilation errors are written to the console.
The tool is very easy to use. You simply point the tool at the assembly that contains the type that causes the exception, and specify which type to pre-compile. But it gets even better! Mathew Nolton has written a GUI for the tool, so using it is even easier. A link to the graphical version of the XmlSerializerPreCompiler can be found at Chris Sells' site.
The tool finally told me the XmlSerializer couldn't be instantiated because of a test-change I made: I made an inner class private, because I added an .Add method for the collection of that innerclass in the main class. That won't fly during serialization.