The point of a HEAD request is to return a Content-Length header, but with an empty body. The WCF transport stack has the annoying ‘feature’ that it ‘corrects’ the Content-Length header based on the stream that is returned. With the aid of Carlos Figueira’s MyLengthOnlyStream i was able to workaround that ‘feature’
(I know, i know, a good old HttpHandler is so much easier to implement!)
Monthly Archives: May 2010
WCF REST: generate correct Content-Length header for HEAD request
Support both GET and HEAD requests on the same method with WCF REST
A while ago i had to modify an existing WCF REST service which was being consumed by BITS. Apparently the implementation has changed in Windows7 in such a way that the BITS client first makes a HEAD request to discover the file size.
The following attempts did not work:
// A method can not have both WebGet and WebInvoke attributes
[OperationContract]
[WebGet]
[WebInvoke(Method="HEAD")]
public Stream Download(string token) { }
// A method can not have multiple WebInvoke attributes
[OperationContract]
[WebInvoke(Method="GET")]
[WebInvoke("HEAD")]
public Stream Download(string token) { }
The trick is to use * as Method and handle the method related logic in your code:
[OperationContract]
[WebInvoke(Method="*")]
public Stream Download(string token)
{
var method = WebOperationContext.Current.IncomingRequest.Method;
if (method == "HEAD") return ProcessHead();
if (method == "GET") return ProcessGet();
throw new ArgumentException(method + " is not supported.");
}
Microsoft SQL Server 2008 Internals
Around new year i found out that i would be working with SQL Server 2008 so i needed a crash course. Microsoft SQL Server 2008 Internals is really not intended to be that, but it does cover the basics and then dives (way too) deep in detail. Although i stopped reading halfway the dives i found the book very interesting!
Windows Internals: Including Windows Server 2008 and Windows Vista, Fifth Edition
Given the fact that i have been developing software for MS-Windows the last couple of years i found it important to learn a bit more about the internals of the operating systems on which my applications run so i ordered a copy of Windows Internals: Including Windows Server 2008 and Windows Vista, Fifth Edition back in september and learned quite a bit from the chapters that i found interesting: security, authorization, networking and analyzing crashes. I skimmed through the chapters on memory management, scheduling and file systems because they reminded me too much of Tanenbaum’s excellent Modern Operating Systems.
97 Things Every Project Manager Should Know: Collective Wisdom from the Experts
Lately i felt the need to work on my management skills so apart from practicing each day i decided to search for some inspiration in 97 Things Every Project Manager Should Know: Collective Wisdom from the Experts. All i can say is that it’s yet another book in the series that is worth reading.
Enumerating SpecialFolders
Environment.SpecialFolder is a value-type that i always seem to forget about. Let’s try to do something about that by posting about it here
foreach (var name in Enum.GetNames(typeof(Environment.SpecialFolder)))
{
var specialFolder = (Environment.SpecialFolder)Enum.Parse(typeof(Environment.SpecialFolder), name);
Console.WriteLine("{0,25} => {1}", name, Environment.GetFolderPath(specialFolder));
}
| Desktop | C:\Users\timvw\Desktop |
| Programs | C:\Users\timvw\AppData\Roaming\Microsoft\Windows\Start Menu\Programs |
| Personal | C:\Users\timvw\Documents |
| MyDocuments | C:\Users\timvw\Documents |
| Favorites | C:\Users\timvw\Favorites |
| Startup | C:\Users\timvw\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup |
| Recent | C:\Users\timvw\AppData\Roaming\Microsoft\Windows\Recent |
| SendTo | C:\Users\timvw\AppData\Roaming\Microsoft\Windows\SendTo |
| StartMenu | C:\Users\timvw\AppData\Roaming\Microsoft\Windows\Start Menu |
| MyMusic | C:\Users\timvw\Music |
| DesktopDirectory | C:\Users\timvw\Desktop |
| MyComputer | |
| Templates | C:\Users\timvw\AppData\Roaming\Microsoft\Windows\Templates |
| ApplicationData | C:\Users\timvw\AppData\Roaming |
| LocalApplicationData | C:\Users\timvw\AppData\Local |
| InternetCache | C:\Users\timvw\AppData\Local\Microsoft\Windows\Temporary Internet Files |
| Cookies | C:\Users\timvw\AppData\Roaming\Microsoft\Windows\Cookies |
| History | C:\Users\timvw\AppData\Local\Microsoft\Windows\History |
| CommonApplicationData | C:\ProgramData |
| System | C:\Windows\system32 |
| ProgramFiles | C:\Program Files |
| MyPictures | C:\Users\timvw\Pictures |
| CommonProgramFiles | C:\Program Files\Common Files |
Get root directory for IsolatedStorageFiles
Sometimes you want to know the absolute path of a file that is persisted with IsolatedStorageFile. Apparently there is an internal property RootDirectory which contains this information:
public static class IsolatedStorageFileExtensions
{
public static string GetRootDirectory(this IsolatedStorageFile isf)
{
var property = isf.GetType().GetProperty("RootDirectory", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetProperty);
return (string)property.GetValue(isf, null);
}
}
Here is a real world example of using SharpBITS.NET to download a file to IsolatedStorage:
class Program
{
static void Main()
{
var mgr = new BitsManager();
mgr.OnJobError += mgr_OnJobError;
mgr.OnJobTransferred += mgr_OnJobTransferred;
var job = mgr.CreateJob("job@" + DateTime.Now, JobType.Download);
var src = @"http://localhost/";
var dst = Path.Combine(GetIsfRoot(), "test.html");
job.AddFile(src,dst);
job.Resume();
Console.WriteLine("running...");
Console.ReadKey();
}
static void mgr_OnJobTransferred(object sender, NotificationEventArgs e)
{
e.Job.Complete();
Console.WriteLine("completed: " + e.Job.DisplayName);
}
static void mgr_OnJobError(object sender, ErrorNotificationEventArgs e)
{
Console.WriteLine("error: " + e.Error.Description);
}
static string GetIsfRoot()
{
using (var f = IsolatedStorageFile.GetUserStoreForAssembly())
{
return f.GetRootDirectory();
}
}
}