Bomb Proof Http Cache Utility?

September 9, 2009 16:38 by Rob

I’d like to share this piece of code with you all.

Usually, when you use the System.Web.Cache classes, you do something like:

object x = Cache[blabla];
if(x == null) //not in cache
{
    x = …..;
   
    // add to cache
    Cache.Add(x, …);
}
// do something with x here.

Now this is not very thread-safe, because when 2 threads arrive at the ‘if’ at the same time, the object is constructed twice. The second one to complete will just overwrite the cached result of the first one (get it?).

So, in order to avoid this you can add a ‘lock’ statement around this to avoid filling the cache twice.

lock(typeof(ClassName))
{
   …

}

This will essentially avoid that 2 threads will enter the same code at the same time.

The problem with this approach is that there is a significant amount of code for every time that you want to read or write to the cache. The code is very error-prone but it is basically the same pattern over and over.

With generics and delegates you can develop a function that behaves like so:

object x = Cached.Get<object>(“cacheKey”, TimeSpan.FromSeconds(5),
                            () => new object()
                       );

The lambda expression ()=> new object is the fragment of code that is executed to populate the cache. The “cacheKey” is some sort of string that uniquely defines what information you want to retrieve. The key should in theory contain all the parameters for your population method.

Now there is a huge potential problem inside the Get() method. The lock statement (typeof(ClassName)) inside is essentially the same one over and over, so *all* calls through this method will be blocked and serialized, thus reducing concurrency to zero. If you have long-running or expensive population methods (you will, because that is why you are caching) you’ll be slowing the system to a halt.In effect, you’d want a separate lock for every 'cache key’ literal.

To overcome this problem, I developed an implementation that generates a new lock for every key. However, when reading and updating the HttpUtility Cache you should be very careful for race conditions.

CacheUtility.cs (7,11 kb)

This class provides strongly-typed access to the HttpCache. It also provides helper methods to flush a single or all elements that were cached using this method, and also a way to determine groups of cached elements. This way you can flush only a subsection of your cache.


Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: ASP.Net | C# | Software Engineering
Actions: E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

Large file uploading using Silverlight, ASP.Net and WCF Part 3

February 25, 2009 22:45 by Rob

Welcome to part 3 of my little series of creating an Asp.net component that allows to upload files of several megabytes without connection timeouts.

In part 1, I explained how the Silverlight component was built and in part 2 the backend service was discussed. In this third and last part I will explain the reusable ASP.Net server control that combines the features into a plug and play component.

The component will solve the following problems:

  • How do I host the SilverLight component?
  • How do I know when the upload has completed?
  • How do I retrieve the contents of the file?

Hosting the SilverLight component

The SilverLightUploader control overrides the CreateChildControls and embeds a System.Web.UI.SilverlightControls.Silverlight component to host the uploader. The control provides for a couple of properties and some are passed on to the silverlight component by providing some initialization parameters. These include:

  • The url of the webservice to be called
  • The location of the SilverLightUpload.xap package.
  • The filter that limits the extension of the files that can be uploaded.

image

I used a helper function to resolve the passed Url’s to absolute url’s because of some limitations I had in my library, but a simple ResolveUrl should be sufficient in most cases.

Also note the OnPluginLoaded hook. This hook is used to bind the event (that is raised when a file is uploaded) to JavaScript.

When a file upload is completed, the Silverlight component raises an event. This event is then catched by a JavaScript block which saves the token of the upload in a hidden field. The Silverlight component just displayed ‘Upload Completed’ and sits and waits until the page is submitted. (the script block is not shown here).

On postback of the page the control checks if the hidden field contains a valid token, and if this is the case, the asp.net component raises an event that can be caught by the page which contains the control.

The control implements IPostBackDataHandler, which means that on any postback the LoadPostData method of the control will be called.

image

The GUID of the upload is persisted in a ViewState-backed property. So even if a validation error occurs on postback, the upload is still safe. (Unfortunately, the Silverlight component does not reflect this yet). LoadPostData returns ‘true’ and the asp.net framework calls RaisePostDataChangedEvent after all the initialisation logic of the page have been completed:

image

 

 

The page that is subscribed to the FileUploadEvent can then call the UploadManager.GetUpload() with the ID that is provided in the event to retrieve the file.

Some tricks left

Instead of putting the SilverlightUpload.xap in /ClientBin, I have embedded the package in the web control by adding it as an embedded resource. I added this file to the project using ‘Add Existing Item’ and ‘Add as Link’ to the SilverlightUpload.xap from the web application. This last step saved me from manually copying the xap every time I created a new build.

image

In AssemblyInfo.cs I have added a declaration so that webresource.axd can be used to retrieve the xap:

image

Also, I moved the implemementation of the WCF UploadService.svc into the control DLL.

Now, to use this control:

  • Add the WebResource.axd handler declaration to the web.config of your web application,
  • Append the service EndPoint to the web.config,
  • Add the SilverlightUpload.dll to the bin directory (or add a reference)
  • Create a file that is a stub for the WCF service (this is the almost-empty UploadService.svc file),
  • Create a page that uses the control,
  • Add an eventhandler to the FileUploaded event

For your uploading pleasure, I’ve added the project with all code to this post.

That should be it!

SilverlightUpload.zip (73.54 kb)


Currently rated 5.0 by 4 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Large file uploading using Silverlight, ASP.Net and WCF Part 2

February 24, 2009 19:27 by Rob

This is the second part of a multi-part article about implementing large file upload for ASP.Net In my previous post I explained the Silverlight bit and this part will be about the WCF backend.

Curious enough, the WCF backend is actually extremely simple. The are only 3 methods that are exposed as a webservice. There 3 methods cover the 3 phases of the file upload process I explained in the previous post. But before I show the service I need to explain some thing else first.

In summary:

  • The client request an upload token.
  • The client sends the binary file in small blocks using the token.
  • After the file is complete, the client confirms the upload.

We took care of those steps with the Silverlight client. On the server side, we need to respond to those steps.

To maintain a record of all the uploads that are in progress, we need to maintain some sort of ‘memory’.  When an upload starts, a new UploadSession object is created. The UploadSession has a couple of properties:

  1. The Filename of the file that is being submitted,
  2. The ID or token of the session,
  3. The State that the upload is currently in (Created, Streaming, Completed or Failed), and finally:
  4. The binary Data of the transmitted file.

UploadManager class

To access a session, a singleton class is implemented.It has 3 methods: CreateSession and GetSession, and finally GetUpload():

image 

CreateSession will create a new session, GetSession retrieves a session. Both are declared internal because they are used by the WCF service (we will get to that in a minute). Third, the public GetUpload() is similar to GetSession but is used to retrieve a completed transfer.

UploadSessions

The UploadSessions class is a helper collection class that is used to store the current uploads. In a first version I was keeping all the uploads in a collection that had Timer events to purge old uploads, but later I decided to use the HttpRuntime.Cache. Here’s the collection class:

image

In essence, it provides strongly-typed access to the cache using the indexer operator. These getter and setter forwards all calls to the HttpRuntime Cache. If you didn't know, this cache is exactly the same class as the HttpContext.Current.Cache, only shorter.

I set the sliding expiration to 5 minutes. This means that the session will be removed is no block is received within 5 minutes, or when the file is not ‘picked up’ by the consuming client after 5 minutes of the upload. This should be sufficient in most cases.

Also, I use the priority to CacheItemPriority.NotRemovable so the server does not expire the session within the timeout period is it low on resources.

(I just noticed that the Remove method is empty…)

Calling the UploadManager from WCF

The WCF service itself is extremely simple. I just forwards all methods to the UploadManager:

image

Last, but not least

The last step for the service side is UploadSession class itself:

image

Again, no rocket science. The UploadSession class is just a wrapper class for a MemoryStream. I intend to expand this class so it flushes the buffer to a temp-file if the file becomes too large, but for now it works perfectly.

The reason I am using a in-memory buffer is a) memory is cheap and fast and b) I’m using the uploaded data in combination with Linq. And Linq stored binary data as a Binary() class, which is just a wrapper class for a byte[]. Therefore it has no use in streaming the file to disk first, and then completely loading it back into memory. The disk buffer approach is only handy when lots of file are uploaded at the same time. If a lot of files are uploaded simultaneously, the total memory usage would have been lower during the time of the uploads, at the cost of requiring temporary files and a lot of disk I/O.

Hosting the Service

Now, to host this WCF service, a basic endpoint must be configured in the web.config of the hosting application:

image

This configuration was generated automatically when I added the service in my project, so it is completely standard. No magic here. No streaming, no large buffers, nothing fancy.

The Silverlight client needs the Url of the WCF service, but I think that was already covered in the previous post.

Wrapping it all up

This is it for the WCF side of it all. As I mentioned before, we are not finished yet. We still need a way to host the Silverlight application, and tell Asp.net that we have received a file. After that we need to pickup the file from the UploadManager. I’ll be showing you a custom server control that does all three of these steps in a simple, reusable Asp.Net control. But that topic will have to wait until the next episode.

Happy uploading!


Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: ASP.Net | C# | Silverlight | Visual Studio
Actions: E-mail | Permalink | Comments (1) | Comment RSSRSS comment feed

Postpone CreateChildControls on Postback

February 22, 2009 23:28 by Rob

Let me explain the problem. A have a server control that really needs to serious context before it can render or process postback events. The context is set using a public property mysteriously called TypeToShow. The value of the property is a complex structure and cannot be persisted in ViewState. This all works fine when I do the initial load of the page, because the CreateChildControls of the control does not occur until I call DataBind() from the containing page.

However, when a postback occurs, the CreateChildControls() method is invoked before I get a chance to inject the meta data.

I know that Asp.Net delayes all events with child controls that are dynamically added using Controls.Add(…), so my work-around was to actually use a Placeholder and create the control until Page_Load was invoked.

There is a workaround, and here it is.:

First, you need to add a couple of statements to the beginning of CreateChildControls like so:

image

This will case CreateChildControls to fail if the property ‘_typeToShow’ was not set. Note that in my case, my control inherits from the 2.0 CompositeDataBoundControl class that does not require you to override CreateChildControls to create your controls. Instead you need to override an overload of this method. Check the SDK on the CompositeDataBoundControl for more info.

Next, you need to give the framework another chance to fire any events. The framework calls OnLoad of the child controls after the parent has been created. This includes Page_Load. To do this, override the OnLoad of the server control like so:

image

The framework detects that the controls have been created and starts raising any events you may have defined.

PS. I don’t know I anyone is reading this blog (except GoogleBot). Gimme a comment!


Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: C# | ASP.Net | Tricks of the Trade
Actions: E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

Large file upload using Silverlight, ASP.Net and WCF, Part 1

February 14, 2009 16:53 by Rob

In this article I would like to show you how I created a reusable ASP.Net component to handle large uploads using Silverlight 2.

The solution contains of 3 components:

  • A Silverlight control that allows the user to browse for files (this page)
  • A WCF service that receives the file data
  • An ASP.Net control that raises an event when the file has been uploaded.

I will discuss them one at a time. The code blocks are screenshots, but don’t worry because I attached the file below.

Edit: After posting this, somebody pointed out that Tim Heuer has a surprisingly similar screencast called Silverlight 2: OpenFileDialog and File Upload. The big difference is that Tim doesn’t support very large uploads.

The Silverlight Control

Using Visual Studio 2008, create a new Silverlight application,delete the standard Page, and add a control named ‘UploadControl’.

image

The control will look like this.

image

This control contains 2 buttons, a progress bar and a display message. The buttons are on top of each other and so are the progress bar and the message.

The magic of this control is in its code behind though. When the upload button is clicked i show a file selection dialog. After a file is selected, some housekeeping is done and a new instance of an UploadState class is initialized.

image

You will notice that 3 events are wired up:

  • One event is raised when the upload is completed
  • Another event is raised each time a block of data is transferred
  • And finally one event may be raised when the user has clicked the cancel button.

The rest of the event handling in this class is rather trivial. The UploadState class is where all the magic happens.

After creation and initialization of the UploadState instance I will start the upload:

image

This section of code needs some explanation, but before I do that, I need to tell you how to achieve large uploads.

Large Upload Intermezzo

IIS, Web services and pages don’t like large requests. Requests tend to time out and no progress can be shown. There have been lots and lots of solutions using ISAPI handlers, background processes and other weird solutions that all have their pros and cons.On Asp.Net forums there is actually a thread about large uploads which at time of writing consists of a massive 182 posts.

The approach presented here may not be unique, but I think it is a great alternative. The steps for large uploads in this solution are as follows:

  • The client requests an upload token from the server. I like Guid’s, to a Guid it is.
  • After the client has received the upload token (or handle as I call it), i can begin to send chunks of data to the server, 8kb at a time. Every chunk is a new http request so timeouts aren’t likely to occur.
  • The server will collect the chunks.The token is sent with the data chunk to the server knows what file the data belongs to.Since the chunks are numbered it can reassemble the entire file.
  • After the last chunk is sent, the client informs that all chunks have been sent.
  • The server receives the completion signal and will assemble all the chunks back into a single file.The server then sends an ‘All Ok’ back to the client.
  • The client has received word that the file has been stored on the server. The file can now be retrieved using all sorts of methods.

Back to Silverlight…

The Silverlight Control, continued

Here’s the ‘StartUpload’ method again.

image

Of course you know that all WCF communication in Silverlight must be asynchronous. This is what happens here. A WCF client is obtained, and a service call to ‘GetHandle’ is executed. The anonymous delegate is fired when a handle is obtained. After the block number and progress values are initialized, the first block is pushed.

Blocks are pushed using the PushBlock method. This method will read a chunk of data from the client’s file and send it asynchronously to the WCF service:

image

Problem with asynchronous calls is that it is impossible to use a standard while loop to enumerate all the blocks. But we can make another call to ‘PushBlock’ when this block is sent, using the anonymous method: (sender, e) => { PushBlock(); }

After every chunk is sent, the remote server is informed:

image

When the server has acknowledged the Complete method, the Completed event is raised from the UploadState class to the control in this method:

image

Again, more housekeeping. The final bit is at the end, where the FileID property is set and the FileUploaded event is raised. The FileUploaded event is a top-level event written for the client of the upload control. You can use this upload control in another Silverlight control, or you can expose it to the Html object model. In my project, i did it using the following code in  App.Xaml

image

The RegisterScriptableObject essentially exposes the UploadControl instance as an object named ‘uploadControl’ in JavaScript. We’ll come back to that later when I wrap the control into and ASP.Net component.

On the next part, I will dive into the implementation of the WCF service.

That’s it for now, keep tight. I need a break.

Rob.


Currently rated 5.0 by 3 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Adding errors to a ValidationSummary

April 24, 2008 14:31 by Rob

Instead of having a custom <asp:Label> with the exception from the backend, you can inject a custom error message to the validationsummary of an asp.net page.

Of course, you could use a server-side validator, but that fires everytime you submit the page, and not only after a succesful post. A Custom Validator is therefore in the wrong place.

Here's what I came up with:

public class CustomValidationError : IValidator

{

private string _message;

public CustomValidationError(string message)

{

_message = message;

}

public string ErrorMessage

{

get { return _message; }set {}

}

public bool IsValid

{

get{ return false; }

set

{

}

}

public void Validate()

{

}

}

To add a custom message to the summary, just do this:

this.Validators.Add(new CustomValidationError("There is no backend!"));


Currently rated 3.5 by 2 people

  • Currently 3.5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: ASP.Net | C#
Actions: E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

Three times a column

March 26, 2008 17:09 by Rob

For a client i needed a ASP.Net control that showed its contents in multiple columns. The CSS requirements forced me to develop a custom repeater for it, since the normal ASP.Net controls didn't suit me. I decided to share it with you, so here it is:

This templated databound control will collect items in multiple css div's when rendering. Provide a collection of css classes to indicate the columns (in this example, 3 divs). Rendering will be done from left to right, top to bottom while iterating over the div's.

+------++-------++-------+
| one  || two   || three |
| four || five  ||       |
+------++-------++-------+

[code] public class MultiColumnRepeater : Repeater
    {
        private string _columnClasses;

        /// <summary>
        /// Specifies the amount of columns and their css classes
        /// </summary>
        /// <example>
        /// To create 2 columns, specify "column_left,column_right".
        /// </example>
        public string ColumnClasses
        {
            get { return _columnClasses;  }
            set { _columnClasses = value;  }
        }

        protected override void RenderChildren(HtmlTextWriter writer)
        {
            //iterate over the different items.
            string[] classes = _columnClasses.Split(',');
            for (int column = 0; column < classes.Length; column++)
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Class, classes[column]);
                writer.RenderBeginTag(HtmlTextWriterTag.Div);
               
                //iterate over all children, and only write the ones for the current columns.
                int index = 0;
                foreach (Control control in this.Controls)
                {
                    if (index % classes.Length == column)
                    {
                        control.RenderControl(writer);
                    }
                    index++;
                }

                writer.RenderEndTag();
                writer.Write(writer.NewLine);
            }
        }
    } [/code]


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: ASP.Net | C#
Actions: E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

Why don't you use those expressions regularly?

January 21, 2008 15:45 by Rob
I found a very nice tutorial on Regular Expressions. If you're still a bit uncertain how it al works, or want to brush up on your RegEx skillz, check it out.

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: ASP.Net | C# | Software Engineering
Actions: E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

Boxing problems?

November 15, 2007 14:38 by Rob
Checkout this link which explains all your boxing needs. I especially like the Doctype list which shows what box model is used in IE6 and above. Yeah, I know, it's been in there for years, but why didn't anybody tell me sooner?

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: General | ASP.Net
Actions: E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

Health Monitoring in ASP.NET 2.0

October 12, 2007 16:22 by Rob

Now here's something interesting I didn't notice before: ASP.Net has health monitoring features built in. In Asp.net 1.1 I used to roll out our own code to catch web application errors and log them, but now they seem to be built in into the framework.

Since I don't like typing very much, here's the link to the full article on 4GuysFromRolla:

  • Health Monitoring Basics - explores the concepts and advantages of the Health Monitoring system and looks at logging events to a Microsoft SQL Server database.
  • Notifications via Email - looks at security-related events and shows how to alert an administrator to failed authentication attempts by "logging" events to email.
  • Raising Custom Events - learn how to create and raise custom Health Monitoring events.

  • Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5
    Tags:
    Categories: ASP.Net | C#
    Actions: E-mail | Permalink | Comments (2) | Comment RSSRSS comment feed