Date Calculations – How to Compute Weeks?

Although everyone would probably agree that the DateTime object exposes extremely useful functionality, many people wonder why they have not included methods or properties to determine if a date on the same week than another or two weeks away or what be it.

So a lot of people go and create lots of complicated date algorithms and make it available on the net for people to plug into their code. While very altruistic, unfortunately their efforts are in vain. That is because .Net does include functionality to deal with weeks, it’s just that this functionality is not in the DateTime object…it’s in the CultureInfo class!

You might be wondering why in hell that is so. Well, it’s very simple really. The concept of a week changes depending on the country. Some countries consider it to start on Sunday, others on Monday, for example. So the determinant of a week is both the date and the country you’re in.

So, if you want to, say, compare if a date1 is on the same week as date2 this is what you should do:

C#
using System.Globalization;

CultureInfo cult = CultureInfo.CurrentCulture;
int date1WeekNo = cult.Calendar.GetWeekOfYear(date1);
int date2WeekNo = cult.Calendar.GetWeekOfYear(date2);

//now you have the number of the week for both dates in the current year
//all you need to do now is simple comparisson
if (date1WeekNo == date2WeekNo)
//same week; do something

So, first we get a CultureInfo object based on the current culture we’re in. Inside the CultureInfo object you will find anothe object called Calendar which has many methods for manipulating dates but automatically taking into context the current culture you’re working in. One of these niceties is the GetWeekOfYear() method which takes a date and automatically gives you what week number that date is in the current year. You can do this for every date you want and then it all becomes simple arithmetic. You can just take the difference between two week numbers, for instance, and find out how many weeks ago or ahead one date is from another. Simple, huh?

The nice thing about this approach is that you don’t even need to know what week system the culture you’re working in uses. It all happens automagically for you!

So next time you need a date function you can’t find in DateTime, look first on CultureInfo.Calendar and you might just save yourself a lot of coding!

SiteMap ASP 2.0 – No root node

If you are using the new Menu Control for the first time in ASP.Net 2.0, after defining your site map file, you might encounter an error like this:

Exactly one <sitemapnode> element is required directly inside the <sitemap> element.

Yes, it’s true. The site map xml file expects a root siteMapNode under the siteMap element. You’re probably thinking, “what the f**?surely Microsoft is not dumb enough to think that web site menus all have one single menu item from which other menus stem from?” You’re right, they’re not that dumb.

All you have to do is go to your SiteMapDataSource control which you must have dropped on your page, click on it, and set the property ShowStartingNode to false.

It’s a bit awkward, but, hey, at least they gave us the option.

ASP.NET Kernel-Mode Output Caching is bad!

I was bit shocked when opening my VS today I got a link from the RSS feed from Microsoft on my start page to an article that talks about 10 ASP.Net pitfalls .

One of the things the author talks about is an issue with Kernel-Mode output caching. Apparently, if you’re ASP.NET either 1.1 or 2.0 on Windows Server 2003 on IIS 6 (which is probably at the very least 50% of people) there is a known and very dangerous problem with using kernel-mode output caching. If turned on then you will get random “cross-session” problems, that is, a user might be injected into someone else’s session!

That is because the kernel-mode output caching sometimes loads the sessionID along with everything else from the cache!! Crazy stuff.

The reccomendation is: if you’ve got the above setup (Windows Server 2003, ASP.Net on IIS 6) turn off Kernel-mode output caching! It’s preffered to turn it off on the web.config file but you can also turn it off for the whole server by using the registry.

With this, it makes you wonder if output caching is really worth it, since without enabling kernel-mode the performance of the caching system will drop drastically.

For more details on the issue and to read the full article (well worth a read) see:
http://msdn.microsoft.com/msdnmag/issues/06/07/WebAppFollies/default.aspx

C# syntax: the @ symbol

a friend of mine asked me the other day what the @ symbol did in C#. He said he had looked everywhere but couldn’t find an answer. And, it’s true, it’s not that easy to find it on the net.

anyway, for him and for you, here it is:

the @ symbol in C# is placed before a string to denote it is a literal such as “Hello I’m a string” as opposed to being like this “Hello” + var1 + var2.

so if you want to assign that literal to a variable you could write it like this:
string hello = @”Hello I’m a string”;

so, what’s the advantage of adding the @?Couldn’t I just leave it out?

Yes you could and in this case the “@” is not doing much at all. Its power comes when you need to use characters that must be escaped in a string because once a string is marked as literal, C# will not attempt to interpret any characters in any other way than plain text so there is no need to escape special characters anymore.

for instance, if you have a path variable and you want assign it to your c drive, you would have to do:

string path = “c:\test”;

that is because the backslash is a special character and must be escaped. However, if you include the @ before the literal string then you dont’ need to escape your characters anymore and then you could write it like this:

string path = “c:test”;

which is much better.

Updating an XML File

This is very easy to do, albeit not necessarily efficient. All you need is create an XMLDocument object, then navigate the DOM to retrieve whatever nodes you want to update and then save the file. So let’s say, for instance, that I want to update a section of my file which has text for my home page. Here is how you would do it:

Vb.Net 

‘load a XMLDocument object with the appropriate file
Dim doc as new XMLDocument(“mySite.xml”)
‘retrieve the part that you want to update.
Dim homePage as XMLNode = doc.selectSingleNode(“/mySite/home”)
‘do the update
homePage.InnerText = “This is the updated text”
‘and now save the changes
doc.Save()

You have to be careful though when using XML like this, mostly with very large files, because, as you can see, while it’s easy enough to get to specific sections of the file and update them using .Net you not only have to load the whole file in memory in order to find the piece of the file that you want,but also when you use Save() it actually saves the whole file again.

File Upload in .Net 1.1

For copy/pasters or quick references, click here to jump straight to the full code.

Even though I classified this post as intermediate, there’s a chance you might be a long-time programmer and never really needed to use this function (that was my case for a while after I started programming a long time ago).

Maybe you just assumed that there is a standard control that could be dropped onto your page and all you would have to do is capture some kind of “save” event if you ever needed to include file uploading on your page one day. Well, the good news is that this is true as of .Net 2.0 (finally!). The FileUpload control offers all that functionality and more. However, if you are using .Net 1.x I’m afraid you are going to have to work a bit harder.

On the other hand, if all you want is to save an uploaded file as a file in your local server as opposed to storing its bytes on a database, for instance, then there actually is a “save” function that will do all the dirty work for you. It just takes some set up before that can happen.

.Net 1.x doesn’t have direct support for file uploading. You must therefore use the same <input type="file"> as you would on a regular html file and transform that into a server control by adding runat=server to its definition so you can manipulate it on the server-side. Let’s look at this in detail.

1 – Setup


step 1:add a form The first requirement for implementing file uploading on your web page, whether it’s just simple HTML, PHP, ASP.NET or whatever, is to have a form. Well, lucky you, if you are programming in .Net you already necessarily have that.

step 2:form’s method must be “post” The second requirement is that the form uses the post method;again something that you probably don’t have to worry about if you are using an IDE like Visual Studio or Dreamweaver to build your .Net pages since this is usually the default.

step 3: form’s enctype must be “multipart/form-data”

Now this is where you have to really pay attention. The third and last requirement as far as “forms” are concerned is that you have to set the enctype attribute of the form to multipart/form-data. If you are using an IDE like Visual Studio or Dreamweaver, the enctype attribute is not added automatically for you to your form tags so you’ll have to do that manually. This is absolutely necessary otherwise the uploads will always fail and you will get an error on your page if you try to submit. Something like:

Form was submitted with no enctype=”multipart/form-data”
Please correct the form attributes and try again.

So, in one easy step, on your aspx page so far your form tag should be looking like this:


<form action="me.aspx" method="post" enctype="multipart/form-data">

step 4: add an input field to the form of type file
Now, all you need to do is add a standard HTML input element to your form of type file, give it some id and transform it into a server control, like this:

<input type=”file” id=”upload_control” runat=”server”>

Note that so far everything we have done was just standard HTML, except for adding the runtat=server to the input tag.

step 5: declare the field on your code-behind
Now we have to declare our input field on our code-behind so we can manipulate it.
The input field of type file maps to the HtmlInputFile control which belongs to the HtmlControls namespace.
So in your code-behind, add the following declaration:

Vb.Net
Protected upload_control as As System.Web.UI.HtmlControls.HtmlInputFile 

C#
protected HtmlInputFile file_whatever;

 

2-Receiving The File


By now, if you followed the steps above, you have a web page which allows the user to browse his computer for files and upload it to the server by submitting the form. That’s right, all the uploading job is done for you automatically. All you have to do is learn how to save this data to whatever medium it is you want. Mediums include saving to a file or directly to a database BLOB column, for instance. Although the latter will not be covered here, even because I strongly discourage such practice, I will show you how to get the content of the file in bytes so you can do as you please with it as well as showing you how to just save the contents to a file on your local server, which is not only what I reccomend but also it’s much simpler actually. You should always avoid storing binary data on the database if possible since they weren’t really made for that and it generates unnecessary overhead. In the case of storing images, I am a big advocate of saving it locally and only storing the path to the file on the database.

step 6: getting information about the file uploaded with HttpInputFile
Now, there is only one property that really matters of the HttpInputFile: PostedFile. This property returns an object of type HttpPostedFile which contains all information about the file uploaded. If no files were uploaded then it returns null.
So, we should check to see if anything was uploaded at all before anything else, and if so then we can grab our HttpPostedFile and move on.

review: upload_control is the id of our HttpInputFile, as declared previously 

VB.Net
Dim file as HttpPostedFile
file = upload_control.PostedFile
if file is nothing then
‘do nothing
else
‘DO FILE READING AND SAVING HERE
end if

C#
HttpPostedFile file;
file = upload_control.PostedFile
if (file == null)
{
//do nothing
}
{
//DO FILE READING AND SAVING HERE
}

Exploring: HttpPostedFile
Before moving on to the next steps, let’s familiarize ourselves with the HtmlInputFile control.
It is important to know that the “currency” when dealing with files is always bytes, that is we are dealing with files on the lowest level: a sequential sequence of bytes.

The three properties that stand out for this control are:

  • ContentLength
    This property returns an integer with the total of bytes that compose the file
  • FileName
    This is a tricky one! This property returns the full path of the file uploaded as is on the user’s computer, not just the file name itself! For instance, if the user uploaded a file from his computer which was “C:my imagesmy photome.jpg” this is exactly what this property will contain, so you will have to take care of extracting just the file name (the last portion of that string) yourself. Fortunately it is very easy to do that with .Net by using the Path class. We’ll see that in a minute.
  • InputStream
    Last but certainly not least, the InputStream gives us exactly what it describes, the input stream for this file. In other words, this is where all the bytes are (i.e. the content of the file whether it’s an image, text file, 3-D movie, what be it)

So what we are going to do next is get our HttpPostedFile and play with it in order to receive and save our file.

step 7: saving the file (…finally!)
From here on everything is much more straight-forward .Net stuff. Once you get your HttpPostedFile, you’ve pretty much done everything that has to do in particular with uploading files; now ayou have two choices: if you want to save to a file then all you have to do is invoke the SaveAs method of the HttpPostedFile and pass in a string with the path and name of the file you want to create. However, if you intend to do anything else with the file then you are going to have to play with streams to save the data by using the HttpPostedFile input stream.
Here’s how to do it both:

Saving to a file

VB.Net and C#
file.SaveAs(“fileNameYouWantToGive”)

or
Getting the file content in bytes

review: file is our HttpPostedFile object as retrieved in the last step by using the HttpInputFile.HttpPostedFile property 

VB.Net
Dim length As Integer

Dim fileName As String = “”

file = file_publication.PostedFile
‘====get the length for the file
length = file.ContentLength
‘create a byte array which will be populated with all the bytes from the file
‘this array can then be passed to the Write function of a FileStream object
‘in order to create a local file on your server
Dim data(length) As Byte
‘==========get the filename
‘remember:the FileName property of HttpPostedFile
‘is tricky; it returns the full path of the file as it was on the
‘computer of the user who uploaded the file
‘fortunately the shared function of the Path class called GetFileName does just that!
fileName = Path.GetFileName(file.FileName)

‘read the content of the file(its bytes) into our byte array
file.InputStream.Read(data, 0, length)

‘data now contains the whole content for the file
‘and you may do as you please with it

C#
int length = 0;

String fileName = “”;

file = file_publication.PostedFile
//====get the length for the file
length = file.ContentLength
//create a byte array which will be populated with all the bytes from the file
//this array can then be passed to the Write function of a FileStream object
//in order to create a local file on your server
Byte data[length];
//==========get the filename
//remember:the FileName property of HttpPostedFile
//is tricky; it returns the full path of the file as it was on the
//computer of the user who uploaded the file
//fortunately the shared function of the Path class called GetFileName does just that!
fileName = Path.GetFileName(file.FileName)

//read the content of the file(its bytes) into our byte array
file.InputStream.Read(data, 0, length)

‘data now contains the whole content for the file
‘and you may do as you please with it

 

And that’s it!

Now, for you inpatient, copy/pasters or just simply practical ones, here is the full code with no dissecting or long explanations (though it still contains some comments to help you out):

upload.aspx:

<form id="form1" method="post" enctype="multipart/form-data">
<input id="upload_control" runat="server" type="file">
</form>
note: the code for receiving the file has been conviniently modularized
into a fucntion named receiveFile() so you may call it wherever you want in your code, such as the Page_Load event, for example. 

VB.Net

upload.vb
Protected upload_control as As System.Web.UI.HtmlControls.HtmlInputFile

private sub receiveFile()
Dim file as HttpPostedFile

file = upload_control.PostedFile
if file is nothing then
‘do nothing
else
‘IF YOU JUST WANT TO SAVE TO A FILE

file.SaveAs(“whateverNameYouWantToGiveToTheFile”)

‘IF YOU NEED TO READ THE CONTENT IN A BUFFER

Dim length As Integer
‘create a byte array which will be populated with all the bytes from the file
‘this array can then be passed to the Write function of a FileStream object
‘in order to create a local file on your server
Dim data(length) As Byte
Dim fileName As String = “” 

‘====get the length for the file
length = file.ContentLength
file = file_publication.PostedFile
‘==========get the filename
‘remember:the FileName property of HttpPostedFile
‘is tricky; it returns the full path of the file as it was on the
‘computer of the user who uploaded the file
‘fortunately the shared function of the Path class called GetFileName does just that! This is not a necessary step it’s only here to show you how to do it
fileName = Path.GetFileName(file.FileName)

‘read the content of the file(its bytes) into our byte array
file.InputStream.Read(data, 0, length)

‘data now contains the whole content for the file
‘and you may do as you please with it

end if
end sub

 

note: the code for receiving the file has been conviniently modularized
into a fucntion named receiveFile() so you may call it wherever you want in your code, such as the Page_Load event, for example. 

C#
protected HtmlInputFile file_whatever;

HttpPostedFile file;
file = upload_control.PostedFile
if (file == null)
{
//do nothing
}
else
{

‘IF YOU JUST WANT TO SAVE TO A FILE
file.SaveAs(“whateverNameYouWantToGiveToTheFile”)

 

‘IF YOU NEED TO READ THE CONTENT IN A BUFFER
int length = 0;
//create a byte array which will be populated with all the bytes from the file
//this array can then be passed to the Write function of a FileStream object
//in order to create a local file on your server
Byte data[length];
String fileName = “”; 

//====get the length for the file
length = file.ContentLength
file = file_publication.PostedFile
//==========get the filename
//remember:the FileName property of HttpPostedFile
//is tricky; it returns the full path of the file as it was on the
//computer of the user who uploaded the file
//fortunately the shared function of the Path class called GetFileName does just that!This is not a necessary step it’s only here to show you how to do it
fileName = Path.GetFileName(file.FileName)

//read the content of the file(its bytes) into our byte array
file.InputStream.Read(data, 0, length)

‘data now contains the whole content for the file
‘and you may do as you please with it

}
}

VB: “Or” Operand Behavior: No Short-Circuit

Now this is a very tricky thing: if you’re new to using any Vb.Net version prior to VB 2005, you might have neglected to learn that the Or operand doesn’t work as you might expect. Most books don’t put a strong emphasis on this, which is a shame cuz it always leads to people scratching their heads in despair for a few good minutes at least when they use “Or” for the first time.

The thing is that in Vb.Net the Or operand will always read both statements no matter if the first one already evaluated to true! This could generate some nasty runtime errors.

For instance:

Dim myNumber = 1
if myNumber = 1 or myNumber = 3 then
‘do something with myNumber
end if

In most languages, you would expect that the other conditions following the first one would be ignored since the first condition has been satisfied (myNumber = 1) and this is an “Or” statement, meaning only condition needs to evaluate to true. However, this is not the case in Vb.Net. It doesn’t cut the “Or” statement short and even if the very first condition evaluates to true it will continue trying to evaluate the other ones.

Now you may be wondering, what’s the big deal?Even if it evaluates the rest of the conditions, surely, the result is still the same since one of them is true anyway.

Well, yes, in most cases, the only consequence, if any, of this behavior would potentially be a hit on performance. HOWEVER, this can get ugly.

Consider the following example:

if row(“something”) is DbNull.Value or row(“something”) = “” then
‘do something
end if

The code above is a snippet from a loop on a the rows of a datatable.
If the the first condition is true and row(“something”) is NULL then this code will break and we’ll have a runtime error that says something like “Operator is not valid for type ‘DBNull’ and string “”.

This is because if the value is NULL then you cannot compare a NULL value to a string, which is what ends up happening in the second expression, row(“something”) = “” . If the statement had been cut short then this would not be a problem since it would only get to the second expression if the first one, row(“something”) was not true.

thus, unfortunately, you have to take the long road and write a bit of redundant code to force the right behavior, like this:

if row(“something”) is DbNull.Value then
‘do something
elseif row(“something”) = “” then
‘do the same thing as above
end if

The good news is that this behavior has finally been corrected in Visual Basic 2005 and the “Or” operand now has the same short-circuit capability as most othe languages do.