Christophe

.NET, technology and a lot more!
.NET and Java job board where experts and companies meet
posts - 17, comments - 21, trackbacks - 0

Thursday, August 21, 2008

View your exception in C# with "$exception"

Sometimes, when working on your application, an exception is raised, and you don't necessary have a try ... catch block to handle this exception, or even to see it!

When you are in the debug mode, just launch a "quick watch" and type "$exception".

Could be useful!

posted @ Thursday, August 21, 2008 8:03 PM | Feedback (1) | Filed Under [ Visual Studio .NET ]

Wednesday, June 11, 2008

Using specific encoding with HttpWebRequest and HttpWebResponse

When sending or receiving data with a HttpWebRequest or a HttpWebResponse, you probably need to provide an explicit Encoding for the data you send or the data you receive. If you don't do that, you might have a conversion problem, because of an invalid encoding. For instance, if the stream returned by your request is ib Unicode and if you read it in the Latin encoding, you will have invalid characters.

To avoid this problem, when receiving data, you need to use the encoding from your HttpWebResponse:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Encoding responseEncoding = Encoding.GetEncoding(response.CharacterSet);
StreamReader myStream = new StreamReader(response.GetResponseStream(), responseEncoding);

In the same way, when sending data, you need to first encode your data in the expected encoding:

String dataToSend = "......";
byte[] bContent = requestEncoding.GetBytes(dataToSend);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
Stream reqStream = request.GetRequestStream();
try
{
  reqStream.Write(bContent, 0, bContent.Length);
  reqStream.Flush();
}
finally
{
  reqStream.Close();
}

Here is a full sample of posting data and reading the response in the expecting encoding:

String dataToSend = "......";
byte[] bContent = requestEncoding.GetBytes(dataToSend);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
Stream reqStream = request.GetRequestStream();
try
{
  reqStream.Write(bContent, 0, bContent.Length);
  reqStream.Flush();
}
finally
{
  reqStream.Close();
}

HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Encoding responseEncoding = Encoding.GetEncoding(response.CharacterSet);
StreamReader myStream = new StreamReader(response.GetResponseStream(), responseEncoding);

If you want to know more about GETing and POSTing data, while using a specific encoding, I advice you to read this detailed article from West Wind Technologies.

posted @ Wednesday, June 11, 2008 10:47 PM | Feedback (0) | Filed Under [ ASP.NET .NET ]

Thursday, May 29, 2008

Sending/receiving cookies with HttpWebRequest/HttpWebResponse

When using a HttpWebRequest or a HttpWebResponse, you might need to send or receive cookies. If you try to access directly the Cookie property of your HttpWebRequest, no cookie will be returned.

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost/MyApp/MyPage");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
// response.Cookies is always empty

It's a bit tricky, but to be able to access the cookies, you need to first assign the CookieContainer of your request.

A CookieContainer contains cookies for many requests. In fact, while the CookieCollection just store a list of Cookie, the CookieContainer store many CookieCollection, each for a specified URI. It allows storing cookies for different URI in a single place.

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost/MyApp/MyPage");
CookieContainer cookieContainer = new CookieContainer();
request.CookieContainer = cookieContainer;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response.Cookies != null && response.Cookies.Count != 0)
{
    foreach(Cookie cookie in response.Cookies)
    {
      // Access to each cookie here
    }
}
else
{
    // No cookie
}

In some cases, you might need to perform several requests, GET or POST, toward several URLs, and pass each time the cookie information gathered from the previous requests. The easiest way to do that is to reuse your CookieContainer object. For instance:

CookieContainer cookieContainer = new CookieContainer();

HttpWebRequest request1 = (HttpWebRequest)WebRequest.Create("http://localhost/MyApp/MyPage1");
request1.CookieContainer = cookieContainer;
HttpWebResponse response1 = (HttpWebResponse)request1.GetResponse();

// Do something here

HttpWebRequest request2 = (HttpWebRequest)WebRequest.Create("http://localhost/MyApp/MyPage2");
request2.CookieContainer = cookieContainer;
HttpWebResponse response2 = (HttpWebResponse)request2.GetResponse();

By doing this way, you share your cookies between the two requests. The cookies retrieve in response1 are store in your cookieContainer, and then sent within request2. Cookies retrieved in response2 are added or updated inside your cookieContainer, and so on.

posted @ Thursday, May 29, 2008 11:14 AM | Feedback (3) | Filed Under [ ASP.NET .NET ]

Sunday, May 11, 2008

try/catch/finally and resource protection: mistakes to avoid

I had to take over a project last week, an ASP.NET application. I found a lot of mistakes regarding resources protection and the use of try/catch/finally block. For instance, I found that:

SqlConnection con = new SqlConnection()
try
{
  con.Open();
  // Some code here
}
catch (Exception ex)
{
  throw ex;
}
finally
{
  if (con != null)
    con.close();
}

During a normal processing, if the code inside the try block works, everything is fine. No problem.

Now, imagine:

1- // Some code here raises an exception.
First, the execution goes to the catch block. This one does nothing than re-throwing the same exception (by the way, I advice you to read this post about rethrowing exceptions and preserving the full call stack trace, explaining how you will loose some important information like the stack trace of the exception). In this case, the block is useless.
Then, the execution goes to the finally block. The connection exists (con != null) and is closed. But the test is wrong… we should check if the connection is not null, and not if the connection is opened! The test is quite different, even if it works in this case.

2- con.Open() fails and raises an exception
The execution goes in the catch block (still useless) and then in the finally block. In this case, the connection exists (con != null) and is closed. But the con.Close() call will throw an exception, because the previous con.Open() didn’t work. The current exception will be lost (ie. “con.Open() failed”) and will be replaced by another one (ie. “con.Close() failed”). You loose some information about the problem you had.

This is now a better way to write your code:

SqlConnection con = new SqlConnection()
con.Open();
try
{
  // Some code here
}
finally
{
  con.Close();
}

In this situation:

1- If con.Open() raises an exception
The execution goes out immediately, with the “con.Open() failed” exception.

2- If // Some code here raises an exception
The execution goes directly to the finally block, closes the connection (that was previously opened) and then goes out of the function with the appropriate exception.

This method works fine, and is also much more readable!

Talking about connections, you can also use in a better way the using statement! For instance:

using (SqlConnection con = new SqlConnection())
{
  // Some code here
}

The generated MSIL code will be translated as a try/finally block (as shown in this post about the using statement), just like our previous sample. This one is just easier to read and to write, and you will not forget to close the connection.

posted @ Sunday, May 11, 2008 8:17 PM | Feedback (0) | Filed Under [ General .NET ]

Friday, May 09, 2008

Visual Studio 2008 - Web project and multiple developers

If you open your project's properties and go to the "Web" tab in the "Servers" section, the first checkbox you see should be "Apply server settings to all users (store in project file)".

If this checkbox is checked, then the server settings (IIS, Cassini, etc.) will be stored in the csproj file. If it is unchecked, then the settings will be stored in the .csproj.user file instead.

Visual Studio crashes or is unable to open your project if the settings stored in the project file don’t match the settings of your computer.

Anyway, if several developers are working on a Web project, you should uncheck this option, to let each of them use their own settings or environment.

posted @ Friday, May 09, 2008 2:15 PM | Feedback (0) | Filed Under [ ASP.NET Visual Studio .NET ]

Tuesday, April 22, 2008

Internet Explorer 8 (IE8) and compatibility

After testing my websites with different browsers, I realized they don't work with IE8! Amazing, because most of them use a standard HTML code!

I found an interesting post from the Windows Internet Explorer Blog talking about Compatibility and IE8. The solution they ended up with is a meta tag. For them, the web developer needs to test his website against one version of Internet Explorer (IE5, IE7 or IE8), and use a meta tag to specify which version of IE is working with his website. Then, IE8 will automatically use the appropriate compatibility depending on the meta tag of the website.

The different meta tags available for this compatibility issue are:
 
<meta http-equiv="X-UA-Compatible" content="IE=5" />
<meta http-equiv="X-UA-Compatible" content="IE=7" />
<meta http-equiv="X-UA-Compatible" content="IE=8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
 
The "edge" value means the website supports the last version of IE8 and even further versions.

Remark: I'm talking about website all the time, but this meta tag can be different from one page to another one. I just consider that all your website should have the same compatibility and that you shouldn't have one page working only with IE5, the other one with IE8 and so on.

When developing a website using ASP.NET, you can directly specify the compatibility tag inside your web.config file, as follow:
 
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
    <httpProtocol>
      <customHeaders>
       <clear />
        <add name="X-UA-Compatible" value="IE=7">
      </customHeaders>
    </httpProtocol>
  <system.webServer>
</configuration>

posted @ Tuesday, April 22, 2008 10:48 PM | Feedback (0) | Filed Under [ ASP.NET .NET ]

Monday, April 14, 2008

Ever wanted to test your website in different browsers?

You can now easily do it with http://browsershots.org. This website uses distributed computers to open your URL on different browsers. Here is a description of the service created by Johann C. Rocholl:

"Browsershots makes screenshots of your web design in different browsers. It is a free open-source online service created by Johann C. Rocholl. When you submit your web address, it will be added to the job queue. A number of distributed computers will open your website in their browser. Then they will make screenshots and upload them to the central server here."

If you select all the default browsers, it is quite ... really slow. But you can just let it work and come back later. Really a useful website!

PS: thank you to Erebuss for the link!

posted @ Monday, April 14, 2008 6:58 PM | Feedback (0) | Filed Under [ ASP.NET General ]

Thursday, April 10, 2008

How to use a Timer in a Windows Service

I had to create a Windows Service with a Timer inside, to perform some actions regularly (in my case, sending emails). I just created a new project, add a Timer on the main form and add my code in the Tick event.

Nothing worked. My code was never called. I spent some time debugging, changing parameters, trying to understand...

Then, I realized I didn't use the right component... I was using a System.Windows.Forms.Timer instead of a System.Timers.Timer!! I just changed by hand the designer file and it worked from the first time.

Be careful, these two components don't have exactly the same properties and events. For instance, the elapse event is called Tick for the first one and Elapsed for the second one. But the behavior is the same.

posted @ Thursday, April 10, 2008 6:03 PM | Feedback (2) | Filed Under [ WinForms .NET ]

Thursday, December 13, 2007

Handle "Maximum request length exceeded." exception

When uploading files in an ASP.NET application, you always face the "Maximum request length exceeded." when the user upload a file too big.

Of course, you can change the size of the HTTP request in the machine.config file (for all the web sites of your server) or rather in the Web.config file (only for your application):

<configuration>
  <system.web>
    <httpRuntime maxRequestLength="51200"/> <!-- 50 Mo HTTP request -->

My problem was not to increase the file size, but to handle this exception in a nice way. The easiest way I found was to handle this exception in the Application_Error event, in the Global.asax file. I just retrieve the last error, check the HTTP code and also compare the inner exception message. Here is my code:

HttpException serverException;
Exception innerException = null; // Get server exception
serverException = (HttpException)Server.GetLastError();

// Get inner exception
if (serverException.InnerException != null)
  innerException = serverException.InnerException;

// Handle "Maximum request length exceeded." exception
if (serverException.GetHttpCode() == 500 && innerException != null && innerException.Message == "Maximum request length exceeded.")
{
  Server.ClearError();
  Server.Transfer("FileTooBig.aspx");
  return;
}
 
This code is quite simple but is working fine! Any other way to do it?

posted @ Thursday, December 13, 2007 3:29 PM | Feedback (6) | Filed Under [ ASP.NET ]

Thursday, October 25, 2007

Debug Get/Post HTTP requests?

Ever wanted to debug GET or POST HTTP request? In this case, you have to use Fiddler, the "Web debugging proxy".

Fiddler acts as a proxy between your computer and Internet. It logs all the HTTP/HTTPs (yes, HTTPs as well!) data, offers a lot of different views for your data (text, raw, xml...), provide some charts about data usage and much more!

You can also set breakpoints on a request, change the data of the request and then continue the process! You can also replay requests. Something else that looks interesting (unfortunately I didn't try yet): you can add your own script (it includes a event-based scripting system) and then add your own actions.

A must have if you need to debug/trace your requests!

posted @ Thursday, October 25, 2007 11:47 AM | Feedback (0) | Filed Under [ ASP.NET General .NET ]

Friday, October 19, 2007

Barcode and QRCode generator

I had to generate barcodes for one of my application. Unfortunately, I know nothing about barcodes!

I found this interesting page, listing a lot of existing barcodes. For each, you have a sample picture, and a lot of information on each barcode (the kind of characters you can put inside, the size of the data and so on).

I had a low budget on this project (let's say no budget at all), so I tried to find something cheap :)

I found an article about writing a C# Barcode Generator Webservice. The main idea is nice: you use a Windows font, and when you write using this font, it'll write the barcode. Easy to use. I tried it, it works fine. But the only free font I found is the one generating the Code 39 barcode. This code doesn't allow much data to be written. Not enough for me.

And all the one dimensional barcodes are all more or less the same. So I tried to use another kind of barcode, 2 dimensional ones. And I focused on the more popular one, the QR Code. For this one, I found a open source barcode library, written in C#, to encode and decode barcodes. You can find an article here and the library here (you need to create an account first).

Really easy to use, the download comes with the full source code and a Windows application to use it. You change the parameters and make a lot of tests. I found one bug in this program: when the input data is too big (depending on the parameters you put), you will have an exception. Easy to fix, and not really important in my case because the entry data will always have the same size.

So if you are like me, looking for an open source library to encode your data into a QR Code, try this library as soon as you can!

posted @ Friday, October 19, 2007 6:42 PM | Feedback (2) | Filed Under [ ASP.NET General WinForms .NET ]

Wednesday, October 03, 2007

Blink text in javascript

In one of my Web application, I wanted to display a blink text, to inform users about something really important. Unfortunately, the <blink> tag doesn't work on IE, only on Firefox.

I found a nice way to avoid this limitation here, using a javascript.

I copy the sample below:

<body  onload="setInterval('blinkIt()',500)">
<script type="text/javascript">
function blinkIt() {
 if (!document.all) return;
 else {
   for(i=0;i<document.all.tags('blink').length;i++){
      s=document.all.tags('blink')[i];
      s.style.visibility=(s.style.visibility=='visible')?'hidden':'visible';
   }
 }
}
</script>
<blink>Am i blinking ?</blink>

So easy to integrate in your application!

posted @ Wednesday, October 03, 2007 3:38 PM | Feedback (4) | Filed Under [ ASP.NET ]

Tuesday, October 02, 2007

@@IDENTITY vs SCOPE_IDENTITY()

When dealing with SQL Server and auto identity fields, we always need to get the newly generated identity value. To do that, I've always used the @@IDENTITY function. Something simple like this:

insert into TABLE values ('My value'); select @@IDENTITY

This has been working fine ... till now! What if you have an insert trigger on the table, and what if this trigger inserts some records as well? In this case, the @@IDENTITY function will return the newly identity values generated inside the trigger, and not the one generated by the "insert into TABLE" statement.

To avoid that, you can just use the @@SCOPE_IDENTITY function. For instance:

insert into TABLE values ('My value'); select SCOPE_IDENTITY()

In this case, the newly generated identity returned will be the one from the "insert into TABLE" statement, and not the one from the last record inserted in our trigger.


You can visit the post SCOPE_IDENTITY() and @@IDENTITY Desmystified from John Papa for more details.

posted @ Tuesday, October 02, 2007 11:11 AM | Feedback (0) | Filed Under [ SQL Server ]

Friday, July 27, 2007

VS 2008 and .NET 3.5 Beta 2 ... here there are!

I've just seen the post on ScottGu's blog:  VS 2008 and .NET 3.5 Beta 2 are just released!

Among the new features, you will find:
- multi-targeting support (multiple version of .NET framework)
- improvement of the HTML/CSS support inside VS
- support for Ajax and Javascript directly in VS
- many improvements regarding LINQ and LINQ to SQL

And much more!

Download the Visual Studio 2008 product here.
Download the smaller VS 2008 Express Editions here.

posted @ Friday, July 27, 2007 5:54 PM | Feedback (0) | Filed Under [ ASP.NET Visual Studio .NET ]

Wednesday, July 25, 2007

Unable to copy file "obj\Debug\XXX.dll" to "bin\Debug\XXX.dll". The process cannot access the file 'bin\Debug\XXX.dll' because it is being used by another process.

For a few hours now, I've been having this error when compiling my solution. Really annoying!

When launching VS 2005 and compiling the solution, everything works fine. But the second compilation leads to this exception. Using Process Explorer showed the files were locked by VS itself! The easy solution is to exit/restart VS, but it's not a reasonable solution.

I started to try something on my own: clean the solution, clean .NET temporary files (in Windows\Microsoft.net directories), add a pre-build event to clean directories, add a pre-build event to kill the webserver, etc. Nothing really worked.

I looked around, trying to figure it out, and I found this interesting post on the MSDN Forums talking about it and also a feedback related to this issue here.

The solution working for me was to remove this line from my web.config file:
<hostingEnvironment shadowCopyBinAssemblies="false"/>
I tried to add this option once during the development in order to develop my own plugin system, and I forgot to remove it.

Everything working fine now!

posted @ Wednesday, July 25, 2007 4:31 PM | Feedback (1) | Filed Under [ General Visual Studio ]

Saturday, June 23, 2007

Middle button click in a TabControl/TabPage, just like FireFox

I'm working on a WinForms application, using TabControl, and I need to handle the middle button on the TabPage. I want to have the same behavior as when using my FireFox: when I click with the middle button on the TabPage, the TabPage closes.

By default, you can handle the middle button event, using the OnClick event on the TabControl. But I want to handle this event when the user clicks on the TabPage, and from that, close the selected TabPage. To do that, I use the OnClick event and check if the coordinates of the mouse match with the TabPage area.

Here is the source code below, with the appropriate comments:

private void TabControl1_Click(object sender, EventArgs e)
{
  MouseEventArgs mea = (MouseEventArgs)e;
  if (mea.Button == MouseButtons.Middle)
  {
    // Get the point from the current mouse click
    Point ptClick = new Point(mea.X, mea.Y);

    // Loop on TabPages
    for(int index = 0; index < TabControl1.TabPages.Count; index++)
    {
      // Get the TabPage that contains the click coordinates
      if (TabControl1.GetTabRect(index).Contains(ptClick))
      {
        // Remove the selected TabPage
        TabControl1.TabPages.RemoveAt(index);
      }
    }
  }
}

One might do a more appropriate treatment when closing the TabPage, maybe not just close it.

posted @ Saturday, June 23, 2007 9:45 AM | Feedback (2) | Filed Under [ WinForms ]

Friday, June 22, 2007

Hi!

Hi, my name is Christophe, and this is my first post on my weblog.

Two words about me: I studied for five years in a computer science school, and also started to work at the same time on various software projects. I started to work with Microsoft .NET from the beta one, in 2001. I have now more than 6 years of experience with the .NET technology, both ASP.NET and WinForms applications, and more than 10 years in software development.

What about this blog? I want to share technology points with you, as well as ideas and thoughts on .NET, engineering, software management and much more!

Want to know more about me? View my complete profile on

Voir un profil sur proagora.com
voir mon profil

Hope to see you soon around here!
Regards,
Christophe

posted @ Friday, June 22, 2007 10:34 PM | Feedback (0) | Filed Under [ General ]

Powered by: