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

Silverlight ImageSourceConverter

November 19, 2008 13:54 by Rob

The Silverlight 2 converter below will convert from a string to a absolute uri in order to stream the images from the website instead of retrieving them from the XAP file.

One of the reasons to do this was a side-effect in Silverlight. For example, when you have a folder within your silverlight project named 'Controls', and you bind an image path to 'Images/Test.png', the resulting image will be loaded from 'Controls/Images/Test'. To overcome this behaviour, I trim the folder name from the request path and transform the relative images to an absolute url.

 

Here's the code:

[code]

using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media.Imaging;
using System.Windows.Interop;

namespace Silverlight.Controls.Converters
{
    /// <summary>  
    /// A type converter for changing any image url to the root of the web application
    /// </summary>  
    public class ImageSourceConverter : IValueConverter
    {
        public object Convert(
            object value,
            Type targetType,
            object parameter,
            CultureInfo culture)
        {
            Uri hostUri = Application.Current.Host.Source;

            //first, get the host,
            string host = hostUri.GetComponents(UriComponents.SchemeAndServer, UriFormat.UriEscaped);

            string path = hostUri.GetComponents(UriComponents.PathAndQuery, UriFormat.UriEscaped);

            //remove /clientbin/...
            path = path.Substring(0, path.IndexOf("/ClientBin"));
            path = System.IO.Path.Combine(path, (string)value);

            //now combine host and path.
            Uri newUri = new Uri(new Uri(host), path);

            return new BitmapImage(newUri);
        }

        public object ConvertBack(
            object value,
            Type targetType,
            object parameter,
            CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
}

[/code]


Be the first to rate this post

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

Repository base classes with LINQ to SQL and performance.

July 18, 2008 19:14 by Rob

I read an article on CodeProject about implementing the repository pattern with Linq To SQL.

I tried that approach because it sounded very nice. I did have some problems with performance and after a few debugging sessions (showing the SQL trace or the DataContext log) I found the problem.


By defining the virtual methods of the repository base class like this: public IEnumerable<T> FindAll(Func<T, bool> exp) the Func will not be (what I call) a delayed method, but it will be expanded immediately. I checked the log from the DataContext and it shows that the table is no longer queries using a where clause. Instead, a full table load is performed and the function is evaluated in memory.


However, the solution is very easy, although this mean you'll have to include the Linq assemblies to your testing bed:

protected T Single(System.Linq.Expressions.Expression<Func<T, bool>> exp)
{
    return Items.Single(exp);
}


The trick is to wrap your functions in a System.Linq expression. Client usage is exactly the same. The performance gain on my project was huge, If you consider that tables are no longer loaded completely into memory.

The full code for my repository base class is in the link below.

Repository.cs (4,64 kb)


Be the first to rate this post

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

Dynamic Data and Silverlight?

July 6, 2008 19:00 by Rob

Yesterday I saw a demo on the new Dynamic Data contribution to Asp.net 3.5. It literally blew me away (really) because that was what I've been doing for most of my time over the last couple of years.

The base

Basically, we develop custom data driven web sites with Asp.net. Most of the time this also involves some kind of back-end content management. What our mini-cms actually did was the following:

  • Inspect the database model
  • Enrich that model with metadata such as preferred input method, validation and comments and associations,
  • Generate a whole lot of Asp.Net controls from the aforementioned properties,
  • Inject a lot of role-based security-stuff,
  • Present those forms to the end-user to allow basic site management.

So, what we had to build was a configuration file with all the meta data, the database, and of course the web site that got driven by that data.

Not any more. I'm out of a job.

With Visual Studio 2008, Asp.Net 3.5 framework and Dynamic Data the generic application that we wrote can be thrown out of the window, because with the DataContext designer this is not longer something somebody else will pay us to do. As you can see in the demo, by binding your decorated data model to the starter solution, you have an interface in a matter of minutes.

Fortunately the Internet-facing site cannot be generated yet. And, we can embrace the DynamicData technology to our advantage and create sites even faster.

On to the subject of this post!

Silverlight and Dynamic Data

Now this is all nice, but there is a simple problem. If I wanted to use this technology with Silverlight, In the last couple of weeks, I was working on a Silverlight application for our content management concept, and I was wondering if the object model could be easily extracted with the new LINQ To SQL designer. I would have to transfer all meta data and content through a WCF service, right?

Lucky for me, the DynamicData layer isn't even finished and does not yet generate WCF services. So, in order to build a generic Silverlight application you would have to serialize a lot of unknown types into a Silverlight application that was unaware of those types. That is not really what I wanted. I wanted a pre-compiled application that can be configured with just a single configuration property: the data model.

I decided to give it a go, and here's what I came up with. I will try to explain it one step at a time.

Here's my very basic data model:

image

Just a news item for a particular category that can have zero or more attachments to it. Nothing fancy.

Using the designer, this stuff generates classes for me with the all the properties and data access methods (select, update, delete etc.) while maintaining all the relations.

Here comes the cool bit: Did you know that the DataContext class actually gives us all the meta data without having to use reflection?  Just drill down into DataContext.Mapping and see that you find there:

image

(edit: since GetTables is a method, it should be written as .GetTables())

Silverlight does not have this nice API, So I created my own WCF contract to serialize these properties in a separate class. Here's a sample of the type specification that I use to transfer to Silverlight (I left the part out that maps the MetaDataMember stuff to my own classes on purpose).

image

To serialize an item of a particular type I perform a generic LINQ select on the table, I read all the properties of a data item and put them in a dictionary so that Silverlight can read and display those items:

image

Notice that for this demo I used the Convert.ToString() method on the value to get a nice presentation of the value. In a future version I will need to put the basic values (int, string, DateTime etc.) in the Values collection.

Of course this is not finished by far. I needed a way to decorate the designed classes with validation, descriptions, etc. Because I do not yet have the DynamicData beta installed on my machine I decided to borrow their approach to decorate generated code. Here's a snippet for the NewsItem class:

image

Because the data context designer generates partial classes, we have the ability to add functionality to those classes. Since I only need to apply some attributes to the generated class I need to define the class again (as partial) and apply my attributes. Since I cannot redefine the properties of that class I have to create an extension class that shadows the properties of the generated class (very nice idea, DynamicData Team!). To use the attributes of the extension class I do need to use reflection, but that is only once. Here's a video of how it works and how it is used. I just copied the concept to there's little more to tell.

A lot of work still needs to be done but I hope you understand that the rest is just more along the same line.

Looks like I still have a job!


Currently rated 5.0 by 3 people

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

Silverlight 2.0 Modified WrapPanel

June 3, 2008 19:18 by Rob

Inspired by this article on Codeproject I decided to give reproduce the wrappanel so I could learn a little more about custom panels in SilverLight 2.0 beta 1. The code provided by Inear has some small problems, one of it not being able to behave properly in a scrollviewer. I made some small adjustments after scourging the internet and here is my solution:

Just before you pass on the ArrangeOverride to the base class, inject this code fragment:

[code:c#] 

if (this.Height != startPoint.Y + largestHeight)

{

this.SetValue(HeightProperty, startPoint.Y + largestHeight);

}

I did make some other small modifications to clean up the code a bit, and I didn't implement the Orientation=Vertical stuff, but check below for the full code.  

WrapPanel.zip (1,11 kb)


Be the first to rate this post

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

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