Mocking an HttpClient using an HttpClientHandler

Recently, I wrote a .NET client for Open Exchange Rates, a service to get exchange rates for more than 100 currencies. You can find it on GitHub. The code is pretty simple, it simply calls the api of Open Exchange Rates using an HttpClient class and deserialize json using Json.NET. I don't want to show you this code in this post, but how you can add some tests to this kind of code. Yes, you must test your code 😃

To be able to test the code, you need to simulate the server response. You can create an interface and use a mock library to replace the HttpClient. But I prefer keeping the HttpClient in the code because it's the main part of the code. So, let's use another way. The HttpClient has a concept of handlers. An handler can modify the behavior of the HttpClient. For instance, you can add headers, change the body of the request, or change the result of the request. Here's a schema from the documentation:

HttpClient and HttpClientHandler explaination

Let's create the handler to enable mocking the server response. An handler only has one method: Task<HttpResponseMessage> SendAsync(HttpRequestMessage, CancellationToken). To easily mock the class, we need to add another method with 2 arguments, the verb and the url HttpResponseMessage SendAsync(HttpMethod method, string url). This method is more convenient to mock. Here's the class:

public abstract class MockHandler : HttpClientHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        return Task.FromResult(SendAsync(request.Method, request.RequestUri.PathAndQuery));
    }

    public abstract HttpResponseMessage SendAsync(HttpMethod method, string url);
}

Now you can easily create an handler with a mocking framework such as FakeItEasy.

[TestMethod]
public async Task Main()
{
    // Create an handler and give the response of the *server*
    var handler = A.Fake<MockHandler>(opt => opt.CallsBaseMethods());
    A.CallTo(() => handler.SendAsync(HttpMethod.Get, "http://sample/ping"))
        .ReturnsLazily(() => Success("pong"));

    // Initialize the client with the handler
    using (var client = new HttpClient(handler))
    {
        // Call the url, the response should be "pong"
        var response = await client.GetStringAsync("http://sample/ping");
        Assert.AreEqual("pong", response);
    }
}

private static HttpResponseMessage Success(string content)
{
    var response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
    response.Content = new StringContent(content);
    return response;
}

It's very easy to test a class that have an HttpClient using a custom HttpClientHandler. This way you don't need to change your code to enable testing it. Handlers also allow lot's of nice scenario, such as retrying requests, adding custom headers, caching, etc.

Reset Windows Password

Sometimes you get a computer without the user password or the administrator password. For example, when you get a colleague's former computer. Without a proper username and passord, you cannot log in. Instead of reinstalling Windows, you can just add a new user or reset the administrator password.

The idea is to be able to run a command prompt as administrator. In fact, you can do better and run it as System. The easiest way is to run Windows in recovery mode (before Windows actually run), so you get a command prompt and you can change everything in the system. In this case, you'll replace the accessibility tool (utilman.exe) by a command prompt. Why? Because you can run this tool from the log in screen by pressing 5 times the key shift, and the user that runs the tool is System. Another way is to replace replace EaseOfAccessDialog.exe. This one is more convenient as you can just press the accessibility button 😃

First, you need to restart the computer in recovery mode. One way is to start on the Windows10 setup (usb key or dvd-rom). Another way is to stop the machine during the boot (maybe twice). At the next boot, Windows will automatically start the recovery mode.

  1. Select you language

  1. Click "Repair your computer"

  1. Click "Troubleshoot"

  1. Click "Command Prompt"

  1. Run the following commands to backup Utilman.exe and replace it by cmd.exe
REM change disk
c:

REM Backup Utilman.exe (should be restored later)
xcopy \Windows\System32\Utilman.exe \

REM Replace Utilman.exe by cmd.exe
xcopy \Windows\System32\cmd.exe \Windows\System32\Utilman.exe /y

REM Reboot
wpeutil reboot

  1. Click the Ease of access button. Instead of starting the actual exe, it run cmd.exe. You can run the following commands:
REM check the current user. Should be `NT Authority\System`
whoami

REM list users
net user

REM Set the administrator password to "toto"
net user Administrator toto

REM Enable the administrator account
net user Administrator /active:yes

  1. You can now log in using the username Administrator and the password toto.
  2. Finally, you should restore Utilman.exe. Redo step 1 to 4. Then, execute the following commands:
REM change disk
c:

REM Restore Utilman.exe
xcopy \Utilman.exe \Windows\System32\Utilman.exe /y

REM Reboot
wpeutil reboot

You can now log in as administrator using toto as password.

Security

  1. If you care about security and you don't want this technique to work on your computer, you should harden your computer. The main step is to encrypt the disk using BitLocker or similar.

  2. I use the verb "reset" and not "change". These 2 mecanisms are differents. When you change a password, you need to provide the current password. This allow to decrypt and re-encrypt the sensible information stored by the user such as the passwords stored in the creadential manager. When you reset a password, the sensible information are not decryptable.

Using Dropbox File Picker in a website

In the previous post, We saw how to use drag & drop and copy/paste to upload files and directories. However, most users now store their files in the cloud (Microsoft OneDrive, Google Drive, Dropbox, etc.). So, it can be a great idea to allow users to select files directly from their cloud provider.

Let's see how to add the Dropbox File Picker to a website!

Dropbox File Picker

Registering the application

First, you need to register your application to get the Application key.

Navigate to https://www.dropbox.com/developers/apps/create and fill the form. You must select "Full Dropbox" access.

Create Dropbox application

Dropbox Application Key

Adding the file picker

The integration in your web application is very easy

<script type="text/javascript"
        src="https://www.dropbox.com/static/api/2/dropins.js"
        id="dropboxjs"
        data-app-key="INSERT YOUR APPLICATION KEY"></script>

<button id="OpenDropboxFilePicker">Dropbox file picker</button>
document.getElementById("OpenDropboxFilePicker").addEventListener("click", e => {
    var options: DropboxChooseOptions = {
        success: function (files) {
             for (const file of files) {
                    const name = file.name;
                    const url = file.link;
                    console.log({ name: name, url: url });
                }
        },
        cancel: function () {
        },
        linkType: "direct",
        multiselect: true,
        extensions: ['.pdf', '.doc', '.docx', '.html'],
    };

    Dropbox.choose(options);
});

// TypeScript definitions
declare var Dropbox: Dropbox;

interface Dropbox {
    choose(options: DropboxChooseOptions): void;
}

interface DropboxChooseOptions {
    success(files: DropboxFile[]);
    cancel?(): void;
    linkType: "direct" | "preview";
    multiselect: boolean;
    extensions?: string[];
}

interface DropboxFile {
    name: string;
    link: string;
    bytes: number;
    icon: string;
    thumbnailLink?: string;
    isDir: boolean;
}

Downloading the file

Once you get the file url, you can easily download the file in JavaScript:

fetch(url)
    .then(response => response.blob())
    .then(blob => {
        // TODO do something useful with the blob

        // For instance, display the image
        const url = URL.createObjectURL(blob);
        (<HTMLImageElement>document.getElementById("preview")).src = url;
    });

You can also send the link to the server and let the server download it.

Conclusion

The Dropbox FilePicker is very easy to use integrate in a web application, even more than the OneDrive File Picker. The user experience is different. OneDrive opens a new window, whereas Dropbox opens a new tab. While I prefer the Dropbox behavior, it may trouble some users.

The full documentation: https://www.dropbox.com/developers/chooser#chooser

Display toast notifications in a WPF application

Windows 8 has introduced toast notifications. This is very convenient to display an information message when something happens in your application.

Windows Toast Notification

However, this functionality is only available in the UWP api. This API is not available by default in a WPF application. But using a trick you can access it 😃

  1. Edit the csproj to add <TargetPlatformVersion>8.0</TargetPlatformVersion>
<PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetPlatformVersion>8.0</TargetPlatformVersion>
    ...
</PropertyGroup>
  1. Add a reference to Windows

Add reference

Or add the reference in the csproj:

<ItemGroup>
    <Reference Include="System" />
    // ...
    <Reference Include="Windows" />
</ItemGroup>
  1. Create a toast

To create a toast, you must create an xml document that describe the content of the toast. There are predifined templates that you must use. You'll find available template in MSDN: The toast template catalog (Windows Runtime apps)

The following code displays a simple toast with text only:

var message = "Sample message";
var xml = $"<?xml version=\"1.0\"?><toast><visual><binding template=\"ToastText01\"><text id=\"1\">{message}</text></binding></visual></toast>";
var toastXml  = new XmlDocument();
toastXml.LoadXml(xml);
var toast = new ToastNotification(toastXml);
ToastNotificationManager.CreateToastNotifier("Sample toast").Show(toast);

The following code displays a toast with an image and 3 lines of text:

var xml = @"<toast>
    <visual>
        <binding template=""ToastImageAndText04"">
            <image id=""1"" src=""file:///C:\meziantou.jpeg"" alt=""meziantou""/>
            <text id=""1"">Meziantou</text>
            <text id=""2"">Gérald Barré</text>
            <text id=""3"">https://www.meziantou.net</text>
        </binding>
    </visual>
</toast>";
var toastXml  = new XmlDocument();
toastXml.LoadXml(xml);
var toast = new ToastNotification(toastXml);
ToastNotificationManager.CreateToastNotifier("Sample toast").Show(toast);

You can now display toast notifications to your users 😃

Using OneDrive File Picker in a website

In the previous post, We saw how to use drag & drop and copy/paste to upload files and directories. However, most users now store their files in the cloud (Microsoft OneDrive, Google Drive, Dropbox, etc.). So, it can be a great idea to allow users to select files directly from their cloud provider.

Let's see how to add the OneDrive File Picker to a website!

OneDrive File Picker

Registering the application

First, you need to register your application to get the Application Id.

Navigate to https://apps.dev.microsoft.com and click the "Register App" button. Follow the steps, and you'll get your Application Id:

Adding the file picker

First, you must add the sdk and a button to open the file picker:

<script type="text/javascript" src="https://js.live.net/v7.0/OneDrive.js"></script>
<button id="OpenOneDrive" type="button">Open from OneDrive</button>

The SDK provides one function to open the file picker: OneDrive.open

const oneDriveApplicationId = "INSERT YOUR APPLICATION ID";

function launchOneDrivePicker() {
    return new Promise<OneDriveResult | null>((resolve, reject) => {
        var odOptions: OneDriveOpenOptions = {
            clientId: oneDriveApplicationId,
            action: "download",
            multiSelect: true,
            openInNewWindow: true,
            advanced: {
                //filter: "folder,.png" // Show only folders and png files
                //filter: "folder,photo" // Show only folders and photos
            },
            success: function (files) { resolve(files); },
            cancel: function () { resolve(null); },
            error: function (e) { reject(e); }
        };

        OneDrive.open(odOptions);
    });
}

Then, you can bind the click event of the button:

document.getElementById("OpenOneDrive").addEventListener("click", e => {
    e.preventDefault();
    launchOneDrivePicker()
        .then(result => {
            if (result) {
                for (const file of result.value) {
                    const name = file.name;
                    const url = file["@microsoft.graph.downloadUrl"];
                    console.log({ name: name, url: url });
                }
            }
        }).catch(reason => {
            console.error(reason);
        });
});

Note: You'll find type definitions for TypeScript in the following gist https://gist.github.com/meziantou/c7d86fd6be049257ef46984459fc8629

Downloading the file

Once you get the file url, you can easily download the file in JavaScript:

fetch(url)
    .then(response => response.blob())
    .then(blob => {
        // TODO do something useful with the blob

        // For instance, display the image
        const url = URL.createObjectURL(blob);
        (<HTMLImageElement>document.getElementById("preview")).src = url;
    });

You can also send the link to the server and let the server download it.

Conclusion

The OneDrive FilePicker is very easy to use integrate in a web application.

The full documentation: https://dev.onedrive.com/sdk/js-v72/js-picker-open.htm