Event performance optimization with the EventHandlerList

When using custom events (event delegates) in your ASP.NET pages, user controls and server controls, many developers might define their Events as public fields, like this:

public event EventHandler<EventArgs> MyCustomEvent;

And use this code to fire the event:

protected void OnMyCustomEvent(EventArgs e)
{
  if(MyCustomEvent != null)
  {
    MyCustomEvent(this, e);
  }
}

Nothing is wrong with the approach of the latter, but defining the MyCustomEvent as a public field introduces two problems:

  1. Even though no clients have registered any delegates to the invocation list of your event, the compiler generates
    one private delegate field for each event delegate in your class. This is a waste of server memory, especially if
    you have several events inside your class.
  2. One Add and one Remove method is generated for each event field of your class. When clients use += and -= to add
    and remove delegates from the invocation lists of your class’ events, these methods are called behind the scenes.
    These two compiler-generated methods are thread-safe, which means they include extra code to synchronize threads
    that are accessing these methods. This means, that everytime a client adds or removes a delegate to or from the
    invocation list of an event, they have to get a lock before they can do the actual work. This introduces an
    unnecessary overhead because most page developers don’t use multiple threads and therefore there is no need for
    thread synchronization.

The EventHandlerList is the answer to our issues. This class comes with the .NET Framework. The EventHandlerList is a linked list of delegates,which is optimized for adding and removing delegates. To use the EventHandlerList in your classes, you need to add a private static key for each event your class exposes. The code bellow defines a key for MyCustomEvent:

private static readonly object MyCustomEventKey = new object();

The memory is allocated only once, because the key is static.

After this, you need to define your events as properties – not fields. These event properties has a different syntax that normal get-set properties. Event properties uses add-remove instead of get-set. The following property, is an event property for MyCustomEvent:

public event EventHandler<EventArgs> MyCustomEvent
{
  add { Events.AddHandler(MyCustomEventKey, value); }
  remove { Events.RemoveHandler(MyCustomEventKey, value); }
}

Every Page, UserControl and WebControl – among others – has a protected property of type EventHandlerList named Events. With this approach, when clients use += to add a delegate to the invocation list of the MyCustomEvent, the add method of the event property calls the AddHandler method of the EventHanderList class, as the code above will tell you. As for -= the RemoveHandler method is called.

The EventHandlerList class maintains a linked list which can have none or one entry for each event. The AddHandler method checks whether this internal linked list contains an entry for an event with the given event key. If it does, the method calls the Combine method of the Delegate class to add the client delegate to the invocation list of the event. If this internal list doesn’t contain an entry for an event with the given event key, the AddHandler method just adds a new entry.

With this new approach, we need to update our OnMyCustomEvent Method, which is responsible for firing the event:

protected void OnMyCustomEvent(EventArgs e)
{
  EventHandler<EventArgs> handler = Events[MyCustomEventKey] as EventHandler<EventArgs>;

  if (handler != null)
    handler(this, e);
}

This method uses the MyCustomEventKey as an index in the Events list to access the MyCustomEvent-event. The Events list will return null if it does not contain an entry at the specified index. This will happen when no clients has subscribed to the MyCustomEvent.

Using the EventHandlerList class automatically resolves the two previously mentioned performance problems with the event fields.

Technorati Tags: ,

kick it on DotNetKicks.com

Windows Vista / Mac debugging a Silverlight app using Visual Studio 2008

[obsolete]
As I wrote here, this is no longer the way to do it as Silverlight 2.0 provides a much better experience.

As I wrote recently in another blog post about a .NET Rocks interview with Brad Abrams, I was very impressed with his keynote at ReMix Boston, where he did the Linux / Vista / Mac debugging. I referred to Richard Campbell‘s opinion that he didn’t believe it would work. At the end of the post, I wrote that I want to try it for myself, to see if it really works. Brad Abrams posted a comment to my blog post, saying that it should work just fine. Well. This post tells the story.

Prerequisites

  • A Windows machine with Visual Studio 2008 and Silverlight Tools Alpha for Visual Studio 2008 installed.
  • A Macintosh with the Silverlight 1.1 Alpha installed.
  • A network connection on both machines and a way to transfer files between the Vista box and the Mac. (A USB flash drive/stick is fine)
  • A Silverlight 1.1 Alpha project linked to a website, ready to run.
  • The website has to be remotely accessible. (Otherwise you can copy the website to the Mac as static HTML files, and run it locally from there.)

Debugging environment

This is the environment I will use for the debugging. For starters, I want to concentrate on the Vista / Mac debugging, so I won’t set up a Linux box with Apache and serve the Silverlight app on a PHP page. But there really should be no problem to it. You can even copy a static HTML page with the XAML page, and the assemblies to the Mac, and run the Silverlight app locally, and attach the Visual Studio debugger to the Safari process on the Mac. Let’s save the Linux box for another time.

The mac: Basically just a Macbook with default configurations, and no special software.

The Vista box: This is my development box. Windows Vista with Visual Studio 2008, IIS 7 and an ASP.NET website set up at localhost.

Before we get started, locate your Visual Studio 2008 folder on the Vista box (usually: C:\Program Files\Microsoft Visual Studio 9.0), and find the Silverlight folder. This folder contains the necessary files to do the initial set-up. You’ll also find a guide to set-up and start debugging, but I’ve found a few mistakes in there, and you can find yourself confused.

Setting up the Mac for Silverlight debugging

Remote debugging is not as easy as pointing Visual Studio to a remote computer, and selecting a process to debug. You have to authenticate against the remote machine. This is done via an SSL encrypted TCP channel between the debugger (The Vista box) and the target machine (The Mac). You will need to set-up the TCP port along with a private/public key pair. This is done in 6 easy steps:

  1. Copy the contents of the C:\Program Files\Microsoft Visual Studio 9.0\Silverlight\MacIntel folder to a destination on the Mac of your choosing.
  2. Start up a Terminal on the Mac, and execute the ‘configcoreclrdebug’ using an absolute filepath. e.g.: /MacIntel/configcoreclrdebug.
  3. First, your private/public key pair will be generated, and then you have to specify a TCP port in the range of 49152 – 65535. Just pick a number.
  4. Then you need to enter a password, and confirm it. Choose a password of at least 8 characters.
  5. A hidden directory is created in your Users folder, located here: /Users/username/.coreclrdbg – copy the “ConfigureWindowsCoreCLRDebugging.exe” file to the Vista box, in a destination of your choosing.
  6. Execute the ‘core_clr_proxy’ file on the Mac from the Terminal, using an absolute filepath like this: /MacIntel/coreclr_dbg_proxy

image image

That was all the set-up needed on the Mac for now. Next up is setting up the Vista box.

Setting up the Vista machine for Silverlight debugging

This is the easy part.

  1. From a command prompt, run the “ConfigureWindowsCoreCLRDebugging.exe” which you just copied from the Mac.
  2. Enter the password you created on the Mac in step 4, and hit Enter.

Starting the debugger

Now to the exciting part. Will it work, or not?

  1. Launch Safari on the Mac, and point the address to the URL of your Silverlight application you wish to debug.
  2. Launch Visual Studio 2008 on the Vista box, and open the Silverlight project that you wish to debug.
  3. Open up a source file, and set a breakpoint.
  4. From the Debug menu, click Attach to Process. (Or hit Ctrl + Alt + P)
  5. From the Transport drop down menu, select ‘CoreCLR Remote Cross-platform Debugging’.
  6. Enter the IP address or hostname of the Mac in the Qualifier box bellow and hit Enter.
  7. Now you should see a list of processes running on the Mac. Anyone that has CoreCLR Remote in the Type column can be attached.
  8. Select the Safari process and hit Attach.
  9. There you go. You’ve just attached the Safari process on the Mac to the Visual Studio debugger.

image image image

Now. Perform whatever action on the Mac that makes you hit the breakpoint you set before, and take a moment to enjoy real-time cross-platform remote debugging.

Screenshots of the Mac showing the webpage with the Silverlight app:

image image

The second picture above, has the SetDefaultView() Button highlighted as if I was holding down the mouse bottom. This is because the screenshot is taken when I hit the breakpoint you can see on the third picture of Visual Studio further above.

One thing I noticed while using the Silverlight charts from the Mac, was the speed. When I paste the serialized string in to the textbox and click LoadData() – the Silverlight loads the string and deserializes it to some custom classes I made. On Vista it takes less than a second. On the Mac it takes about two seconds or maybe a bit more. And it is not because of network latency. Silverlight runs in the browser, which means the app is downloaded to the Mac, and when I click the buttons, all the logic handling events and doing stuff runs locally. So Silverlight is lot slower on the Mac than on Windows. Maybe this will get better when Silverlight 1.1 is officially released.

kick it on DotNetKicks.com

Configuring IIS 7 default document from web.config

IIS 7 has a lot of changes regarding the configuration model. Using the Integrated Configuration System in IIS 7 you can set configuration of your server on different levels, compared to IIS 6, where the ASP.NET developer were more restricted. Configuring IIS 7 from an ASP.NET Web Application’s web.config file works from both ASP.NET 2.0 and ASP.NET 3.5. Note that the server can be restricted to lock certain configuration settings from above the application level, you might encounter this if your website runs in a shared hosting environment.

Setting up the website

To have a test website, I will setup a new website on my Vista machine running IIS 7. I don’t want the website to run under the Default Web Site, so first thing, I’ll add a hostname to my hosts file. This is located in the drivers\etc folder of your windows directory’s system32 folder. Add the following line:

127.0.0.1         iis7test

Open up Internet Information Services (IIS) Manager, and create a new Application Pool. Name it iis7test, and leave the settings as default:

image

Add a new website with the following settings:

image

This should get us started. Open up Visual Studio 2008 (2005 will also work). Open the website you just created inside IIS.

image

The only item in the website is a web.config. Add a new Web Form called Test.aspx.

Right-click the Test.aspx file and click View in browser. You could get an HTTP Error 500.00, like this:

image

To get rid of it, set impersonate to false in the web.config file by adding this line to the system.web section:

<identity impersonate=”false” />

Now your site should work fine. Edit the Test.aspx file, so it has some content. Just write Test IIS 7 or something in the HTML mark-up.

If you right-click the website icon in the Solution Explorer, and click View in browser, you will get an error like the one bellow:

image

That is because our website does not have any pages that match the name of the default documents on IIS. If you don’t want to be limited by the few default documents that comes with IIS out-of-the-box, you can add your own from web.config by adding these lines:

<system.webServer>
<defaultDocument>
<files>
<clear />
<add value=”Test.aspx” />
</files>
</defaultDocument>
</system.webServer>

Maybe the system.webServer section already existed in your web.config file. If so, just add the defaultDocument section. Here you can specify all the filenames that should act as a default document in IIS 7. The <clear /> line is optional. If you want to keep the default settings, and only add your own – just delete that line.

Now when we save the new web.config file, and refresh the browser we se our Test.aspx file:

image

This setting is just one of many that you can specify in your application’s web.config file. In the near future I’ll be blogging more about specific settings you can use to configure IIS 7 from ASP.NET.

Technorati Tags: ,

kick it on DotNetKicks.com

The Integrated Programming model in IIS 7

IIS 7 comes with a bunch of improvements for developers. You can do a whole lot of exciting things even from web.config, but also from code.

To take advantage of the powerful integrated programming model, you need to set your application pool to use the Integrated pipeline mode. There’s no limit to what you can do.

I found a lot of great stuff in the book called Professional IIS 7 and ASP.NET Integrated Programming and learned a lot of useful stuff.

IIS 7 (or 7.5) is still the preferred way to develop, test and deploy ASP.NET applications, and as a developer you must stay up-to-date on what your tools and framework has to offer!

Sending e-mails from your ASP.NET app and maintaining a list of recipients

Making your application send e-mails, is something you do almost in every application. It’s easy – all you need is an SMTP server to relay your mail through. Sending e-mail messages to several recipients at once can also be done, by adding multiple recipients to either of the MailMessage.To, MailMessage.Cc or MailMessage.Bcc properties in C#. But if you send a newsletter every month, week or day, it is very important to maintain your list of recipients, so that whenever people get a new e-mail address (and they do!) and the old one stop working – you avoid those undelivered mails everytime you send your newsletter.

I’ve made this simple class called BulkSender, that takes three parameters in the constructor:
mailMessage (System.Net.Mail.MailMessage), recipients (List<string>), mailSender (System.Net.Mail.SmtpClient).

It has one method: SendEmailMessage, and what it does is, that it adds all recipients to the Bcc collection on the MailMessage, and sends the mail in a try-catch block. Whenever the SmtpFailedRecipientsException or SmtpFailedRecipientException is handled, it adds the e-mail address to a local List<string> and returns the e-mail addresses with delivery failures as a List<string>.

Code snippet:
image

When you get the List<string> of failed recipients, you can add your own logic to take care of maintaining your list of recipients. Maybe an e-mail address has to fail 3 times, before it is deleted, or maybe you want to delete it the first time it fails.

Another good thing to have in mind when sending e-mails to multiple recipients at once, is to add the mail addresses to the Bcc collection, and NOT the To or Cc collection. This way the e-mail addresses is hidden, you only get to see ‘undisclosed-recipients’ in you mail client:
image

Note that the BulkSender class automatically clears the To, Cc and Bcc collections before adding the recipients to the Bcc collection. This way you know for sure, that you do not have any e-mail addresses publicly available when you send the e-mail.

You can download the code below. Feel free to tweak the class – and let me know if you have some interesting things regarding this topic.

Technorati Tags: ,

BulkSender.zip (818.00 bytes)

kick it on DotNetKicks.com

Optimizing Code Snippets

Code Snippets are a great productivity boost that was introduced in Visual Studio 2005, if I remember right. Code Snippets lets you type a shortcut for a piece of code. I use snippets for properties a lot. I hate writing properties “by hand” – it is much faster with Code Snippets. But since Visual Studio 2008, the default prop shortcut now uses Dynamic Properties – but I still work on some projects that does not support Dynamic Properties. So I changed my default Code Snippets, and added a few other.

First I changed the default prop snippet back to the old property with a backing field. Then I added snippets for a Dynamic Property, Business Object Property (to use with Rockford Lhotka’s CSLA architecture) and a ViewState Property. See the code they all produce here:

image This boosts productivity even more, and it is a great way to get rid of those lame things you do over and over again…

Download the snippets yourself bellow. Add them to your C:\Program Files\Microsoft Visual Studio 9.0\VC#\Snippets\1033\Visual C# directory, and replace the prop.snippet file when it prompts you.

Technorati Tags:

CodeSnippets.zip (2.29 kb)

How to handle IIS Event id 1009 (Event id 5011 on IIS 7)

Recently at work we had some serious production environment issues. Our web application basically made the IIS application pool terminate unexpectedly. And we didn’t get a single stack trace or a line of code. The only thing that was logged inside of the Windows Event Viewer, was event id 1009, which basically told that the application pool serving our app terminated unexpectedly. And that was it. All active user sessions were wiped, and the users had to login again.

The error started after we did a major upgrade. A lot of our code had changed since the previous version, so we set up an new website and application pool inside IIS 6.0 for the new version, so we could upload the new application, and then turn off the old one, to get as seamless an upgrade as possible. It worked fine, and we were happy. Until a few hours later, when we saw our users were logged off.

At first we thought it was IIS settings we had done wrong, so we did a complete comparison with the old website and application pool to see if we forgot anything. There was no difference at all. After a while, we realized that the only thing that could make the IIS crash like that, was our own code. But with no clue of where the danger in our code were – we were lost.

After some time, we got WinDbg attached to the worker process of IIS, serving our application. We caught a few memory dumps, but those were not of the exception we were looking for.

Later I found an HttpModule for ASP.NET. Basically the .Net framework 2.0 has changed the way it handles exceptions from other threads in IIS. In ASP.NET 1.1, unhandled exceptions from asynchronous threads inside IIS were ignored. But in ASP.NET 2.0, those unhandled exceptions makes the IIS application pool crash.

Make the IIS crash yourself

So try to do this. Create a new ASP.NET 2.0 website running on your local IIS. You only need a single page, so you’re fine with the default.aspx Visual Studio creates for you. Add a button to the page, and create an event handler for the buttons OnClick event.

Add this to your code-behind:

  /// <summary>
  /// Handles the Click event of the btnMakeCrash control.
  /// </summary>
  /// <param name="sender">The source of the event.</param>
  /// <param name="e">The EventArgs instance containing the event data.</param>
  protected void btnMakeCrash_Click(object sender, EventArgs e)
  {
    ThreadPool.QueueUserWorkItem(new WaitCallback(MakeIisCrash));
  }

  /// <summary>
  /// Makes the IIS crash.
  /// </summary>
  /// <param name="stateInfo">The state info.</param>
  private void MakeIisCrash(object stateInfo)
  {
    // Instantiate the DataSet to null
    DataSet ds = null;

    // Make an unhandled NullReferenceException
    ds.CaseSensitive = true;
  }

The buttons click event handler uses the ThreadPool to execute the MakeIisCrash() method. This method instantiates a DataSet as null, and the sets a property. Since the DataSet is null, this throws a NullReferenceException which is not handled, as you can see.

Click the button, and see how IIS will crash.

You can sense that your computer is working harder – that is because IIS terminates the application pool. If you go and check the Windows Application log, you can see that is has added an error:

image

Now this doesn’t tell you much. Imagine if you had hundreds of thousands line of code – how would you find the cause of the error?

Inside Visual Studio, add a new class to the website – call it UnhandledExceptionModule, and apply this code:

#region Using

using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Web;

#endregion

/// <summary>
/// Handles all unhandled exceptions from in the current AppDomain. 
/// 
/// Works great to catch unhandled exceptions thrown by IIS's child threads, /// which will make the application pool terminate unexpectedly 

/// without logging. This makes sure your Exception /// is logged to the Application event log.
/// </summary>
public class UnhandledExceptionModule : IHttpModule
{
  #region Fields

  private static int _UnhandledExceptionCount = 0;
  private static string _SourceName = null;
  private static object _InitLock = new object();
  private static bool _Initialized = false;

  #endregion

  #region IHttpModule members

  public void Init(HttpApplication app)
  {

    // Do this one time for each AppDomain.
    if (!_Initialized)
    {
      lock (_InitLock)
      {
        if (!_Initialized)
        {
          string webenginePath = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "webengine.dll");

          if (!File.Exists(webenginePath))
          {
            throw new Exception(String.Format(CultureInfo.InvariantCulture,                 "Failed to locate webengine.dll at '{0}'.  This module requires .NET Framework 2.0.", webenginePath));
          }

          FileVersionInfo ver = FileVersionInfo.GetVersionInfo(webenginePath);
          _SourceName = string.Format(CultureInfo.InvariantCulture, "ASP.NET {0}.{1}.{2}.0", ver.FileMajorPart,                 ver.FileMinorPart, ver.FileBuildPart);

          if (!EventLog.SourceExists(_SourceName))
          {
            throw new Exception(String.Format(CultureInfo.InvariantCulture,                 "There is no EventLog source named '{0}'. This module requires .NET Framework 2.0.", _SourceName));
          }

          AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException);

          _Initialized = true;
        }
      }
    }
  }

  public void Dispose()
  {
  }

  #endregion

  #region UnhandledException event handler

  public void OnUnhandledException(object o, UnhandledExceptionEventArgs e)
  {
    // Let this occur one time for each AppDomain.
    if (Interlocked.Exchange(ref _UnhandledExceptionCount, 1) != 0)
      return;

    StringBuilder message = new StringBuilder("\r\n\r\nUnhandledException logged by UnhandledExceptionModule:\r\n\r\nappId=");

    string appId = (string)AppDomain.CurrentDomain.GetData(".appId");
    if (appId != null)
    {
      message.Append(appId);
    }

    Exception currentException = null;
    for (currentException = (Exception)e.ExceptionObject; currentException != null; currentException = currentException.InnerException)
    {
      message.AppendFormat("\r\n\r\ntype={0}\r\n\r\nmessage={1}\r\n\r\nstack=\r\n{2}\r\n\r\n",
                           currentException.GetType().FullName,
                           currentException.Message,
                           currentException.StackTrace);
    }

    EventLog Log = new EventLog();
    Log.Source = _SourceName;
    Log.WriteEntry(message.ToString(), EventLogEntryType.Error);
  }

  #endregion
}

Modify the httpModules section inside web.config to look lige this:

        <httpModules>            <add type="UnhandledExceptionModule" name="UnhandledExceptionModule"/>        </httpModules>

This is your new friend. It is a must for any ASP.NET 2.0 application running in production environment. This will catch your exception, and write the message and the stack trace to the Windows Application Event log, and now you can see what caused the crash:

image

So after we applied this HttpModule to our production environment, we get a nice entry in our Application event log from ASP.NET. It includes a stack trace, which makes us able to find the problem, and fix it!

Further reading regarding ASP.NET production environment issues:

Hope this will help someone.

Technorati Tags: , , ,

kick it on DotNetKicks.com

Recommended listening: .NET Rocks with Brad Abrams

If you haven't heard .NET Rocks before, now is a good time to do it. In their last show, they interviewed Brad Abrams during Remix Boston where he did a keynote. So who is Brad Abrams.

Quote from his own blog:

Brad Abrams was a founding member of both the Common Language Runtime, and .NET Framework teams at Microsoft Corporation where he is currently the Group Program Manager for the UI Framework and Services team which is responsible for delivering the developer platform that spans both clients and web based applications as well as the common services that are available to all applications. Specific technologies owned by this team include ASP.NET and ASP.NET AJAX, parts of Silverlight, and Windows Forms.

In the interview, they talk a lot about Silverlight, what they are trying to do and how open the technology actually is. And they talk a lot about that openness Microsoft has recently approached, and how the Silverlight technology could be adapted by a developer of any of the three major platforms. (Windows, Mac & Linux). I really like that approach, and the result is clear. Already – even though Silverlight just hit the 1.0 RTM recently, there's a huge amount of applications running live from notable companies.

They also talk a lot about Brad Abrams' keynote at Remix Boston, where he did a demo on debugging a Silverlight 1.1 app.

And he didn't do it the easy way! He had a Linux box with a small PHP page, hosting the Silverlight 1.1 app. That worked great. The he fired up a Mac, and hit that page from Safari. And to achieve the debugging experience of Visual Studio, he attached the VS debugger to the Safari process on the Mac, set a breakpoint in the code, and refreshed the page on the Mac, to hit the breakpoint. And there you go. A Mac hitting a breakpoint on a Vista box, and the website being hosted on a Linux box – how cool is that?

During the show Richard Campbell said that he didn't believe it would work. I don't know – but I want to try the same thing, and se if it really works.

Technorati Tags: , ,

Silverlight 1.0 officially released

slpenguin-thumb This morning, I just read over at Scott Hanselmans blog, that Silverlight 1.0 was released and it support Linux. So that means Silverlight support all major platforms now, and it is out in the open so your apps can get going. To get some inspiration, you can have a look at these Silverlight apps that Scott posted on his blog: (posted from ScottGu’s blog)

Quote Scott Hanselman

  • Recreating ITunes in Silverlight: Jose Fajardo has an absolutely fantastic blog with a ton of Silverlight content on it.  One of the projects he has been working on has been recreating Apple’s ITunes Media Player using Silverlight.  Check out his multi-part blog series that discusses step-by-step how he built it.  Absolutely brilliant.

  • Sudoku for Silverlight: David Anson has built a cool online sample using Silverlight that helps you play the popular Sudoku game.  Useful for both Sudoku addicts and developers wanting to learn Silverlight.  

  • Font Embedding and RSS data in Silverlight: Tim Heuer has a cool blog post that shows how you can create your own font-type and embed it within your Silverlight 1.0 application.  He then has his application retrieve dynamic content from an RSS feed and use the custom font to display it.  You can run the finished application online here (all of the text here is dynamic – not a screen-shot).

  • Silverlight Drag and Drop JavaScript Framework: Roberto Hernandez-Pou has a nice article and sample that describes how to implement a drag/drop mechanism for Silverlight 1.0 (using JavaScript).  This article is in both Spanish and English – scroll down if you are looking for the English version.

  • Pascal Support for Silverlight: RemObjects Software now has a project template for VS 2008 that enables you to write Silverlight 1.1 .NET applications using Pascal.  It is kinda wild to see a screenshot of FireFox on the Mac, running a Silverlight application, written with a Pascal code-behind file built with VS 2008.

 Also, have a look at the official Silverlight community website, where you’ll frind quickstarts, forums and recent blogposts from leading Silverlight developers and Microsoft people.

Technorati Tags:

Web services and Silverlight 1.1 C# gotchas

As anyone must know by now, Silverlight is Microsoft's cross-browser, cross-platform RIA (Rich Internet Application) technology – like Adobe's Flash. With Silverlight, they say the sky is the limit, and it's only up to yourself what to invent. Silverlight offers you a big chunck of the .NET CLR in the browser, when using Silverlight 1.1 Alpha (Refresh). As always, there are do's and don'ts when you work with new technology and in this not-known-yet-part series, I'm going to recap my experience using Silverlight 1.1 Alpha and later Silverlight 1.1 Alpha Refresh to develop some sophisticated charting components.

Before you begin – general info

For the current release of Silverlight (Silverlight 1.1 Alpha Refresh) you don't have the System.Data namespace (that means no DataSets nor DataTables). Also the System.Xml namespace is very small, you don't get the XmlDocument which would have been useful. I haven't heard anything reliable about whether or not those namespaces and classes will make it into the final release of Silverlight, but it doesn't seem like it.

Maybe 3rd party components will come to help here, but that's a drawback because then the users have to install something new on their machines to be able to use your app.

Mark your webservice as a ScriptService

If you're going to use any kind of data in your Silverlight apps, and you probably are, then you have to use a webservice. Calling a webservice from Silverlight is a bit different from calling a webservice from another ASP.NET page.

First of all, you have to mark your webservice as Scriptable. The Scriptable attribute excists in the System.Web.Script.Services namespace, and is part of the ASP.NET AJAX framework (also included in the .NET Framework 3.5). If you are developing on ASP.NET 2.0, you have to make sure you have ASP.NET AJAX installed on the server, and reference the correct assemblies in your ASP.NET 2.0 application.

This is how your class definition will look like:

[WebService(Namespace = http://tempuri.org/)]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class SilverchartDataService : System.Web.Services.WebService{
} 


Now your webservice can be called from Silverlight – and also JavaScript / AJAX.

Don't call a webservice on another domain

The security model of Silverlight, and also other client-side technologies, deny calling a webservice on another domain. That is also called cross-domain webservice calls, and if you do, you will get this exception when #debugging your Silverlight app using Visual Studio 2008:

image

I've seen ways to get around this problem, but it is beyond the purpose of this blog post. If you need info on this topic, try this: Using a proxy to access remote APIs (The article is for AJAX – should work for Silverlight)

JSON Serialization compatibillity with .NET

Whenever you use a webservice, all the objects transfered gets serialized. (Remember to mark your own classes as Serializable if you want to use them in your webservice.) And Silverlight uses the JSON Serialization 'engine'. This can result in some nasty errors, yet difficult to debug. I've found out, that some .NET classes cannot be used – these include:

  • decimal
  • enum (So don't use enum's with Silverlight – at least not until it is supported)

And there are probably more than those two…

Technorati Tags: , , ,

Fiddler2 and the ASP.NET Development server (Cassini)

If you’re debugging ASP.NET apps, it can sometimes be an advantage to be able to see the actual requests, and analyze file sizes, run-time rendered code and being able to ‘fiddle’ with the code on run-time. Well. Fiddler2 provides extremely useful features for doing so, but for people using the ASP.NET development server (Cassini) you have to do a few workarounds…

I’m running IE7 on Windows Vista (a great OS). IE7 automatically bypasses proxies for localhost, which is our main problem. When using the ASP.NET development server (Cassini), the URL looks like this one: http://localhost:49950/app/Default.aspx. When you open Fiddler2, you see that it hasn’t monitored the traffic to the localhost address. This can be fixed by applying a period (.) after localhost. So change the URL to this:  http://localhost.:49950/app/Default.aspx

In my case, that wasn’t enough. I got an error from Fiddler2 in my browser. If I disabled Fiddler2, it worked just fine. Then I added a rule to Fiddler2. To do this, in Fiddler2 go to Rules > Customize rules. (or hit CTRL + R). Find the OnBeforeRequest event-handler, and add the following code:

if (oSession.host.substr(0, 10)==”localhost.”)
{
         oSession.host=oSession.host.replace(“localhost.”, “127.0.0.1″);
}

Now – when you want to use Fiddler, just add a dot right after localhost in the URL, and Fiddler will start working!

That worked for me – hope it works for you too, if you’re having problems.