Common SSL/TLS errors with Windows.Web.Http.HttpClient

This blog moved to kiewic.com

The certificate authority is invalid or incorrect
0x80072F0D
Windows.Security.Cryptography.Certificates.ChainValidationResult.Untrusted

The host name in the certificate is invalid or does not match
0x80072F06
Windows.Security.Cryptography.Certificates.ChainValidationResult.InvalidName

The date in the certificate is invalid or has expired
0x80072F05
Windows.Security.Cryptography.Certificates.ChainValidationResult.Expired

How to send text, JSON or files using BackgroundTransfer.UploadOperation.

This blog moved to kiewic.com

This is a common question in StackOverflow and MSDN forums. So, let’s take a look at our three main options.

Plain Text, JSON string, Etc.

Windows.Networking.BackgroundTransfer is designed for doing large uploads or downloads in the background. So, first you need to persist the string in a file.

XX

XX

See here for examples of how to serialize or parse JSON strings.

Then, to upload the file do:

Uri uri = new Uri("http://localhost");
BackgroundUploader uploader = new BackgroundUploader();
uploader.SetRequestHeader("Content-Type", "application/json; charset=utf-8");
UploadOperation upload = uploader.CreateUpload(uri, file);
Task<UploadOperation> startTask = upload.StartAsync().AsTask();

Task ignore = startTask.ContinueWith((task) =>
 {
  // TODO: check task.Status
 });

The you see the raw HTTP request with Fiddler or Network Monitor, it looks like this:

POST / HTTP/1.1

Accept: */*

UA-CPU: AMD64

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; Touch; LCJB; rv:11.0) like Gecko

Host: localhost

Content-Length: 23

Connection: Keep-Alive

Cache-Control: no-cache

{ “firstName”: “John” }

Read from infinite online stream using Windows.Web.Http.HttpClient.

This blog moved to kiewic.com

If  you have an infinite Transfer-Encoding: Chunked HTTP response, you can read it this way:

private async void Foo()
{
    // Example URI.
    Uri uri = new Uri("http://localhost/?chunked=1&length=10000000000&delay=500");

    HttpClient client = new HttpClient();
    HttpResponseMessage response = await client.GetAsync(
        uri,
        HttpCompletionOption.ResponseHeadersRead);
    IInputStream inputStream = await response.Content.ReadAsInputStreamAsync();

    ulong totalBytesRead = 0;
    IBuffer buffer = new Windows.Storage.Streams.Buffer(1000000);
    do
    {
        buffer = await inputStream.ReadAsync(
            buffer,
            buffer.Capacity,
            InputStreamOptions.Partial);

        // ...

        totalBytesRead += buffer.Length;
        Debug.WriteLine(buffer.Length + " " + totalBytesRead);
    } while (buffer.Length > 0);

    Debug.WriteLine(totalBytesRead);
}

You want to share a Windows folder with everybody, no password required, any user in the network should be able to access it.

This blog moved to kiewic.com

It turns out that making a folder completely public in Windows 8/8.1 is not an easy task. At least for me.

That is why I have created the following step by step illustrated guide.

1. Using Explorer, go to the folder that contains the folder you want to share.

Folder in Windows Explorer

2. Right click on the folder, select “Share with”, then select “Specific people …”

Share directory in Windows 8/8.1.

3. Open the drop down menu, select “Everyone” and click “Add”.

Share with everyone.

4. Select “Read” or “Read/Write” permissions, you decide, then click “Share”.

File sharing: Write and read permissions.

5. Next screen has the address other users in the network need to type to get access to the folder.

File sharing: address to access shared resource.

6. Go to “Control Panel” and open “Network and Sharing Center”.

Contol panel share settings.

7. Click “Change advanced sharing settings”.

Windows 8/8.1 Network and sharing center.

8. In the “current profile”, select “Turn on network discovery” and “Turn on file and printer sharing”. Depending on the network you are connected to, the “current profile” could be the “Private” network or the “Guest or Public” network.

Advanced sharing options: current profile.

9. In the “All Networks” section, select “Turn off password protected sharing”. Otherwise, users trying to access the machine will require to have an account on the machine. Then click “Save changes”.

Advanced sharing settings: Turn off password protected sharing.

That is all. Now you can access your folder from other devices using the address mentioned above!

 

 

Write a file to the SD card on Windows Phone 8.1.

This blog moved to kiewic.com

Use *Windows.Storage.KnownFolders.RemovableDevices*.

Configure SD card emulator

  1. Click *Tools* button, it looks like this: *>>*
  2. Click *SD Card* tab.
  3. On *Local folder* type a local folder path, e.g., *C:\SDCard*
  4. Click *Insert SD Card*

Set capabilities

  1. 1. Double click *Package.appxmanifest*
  2. Click *Capabilities* tab
  3. Check *Removable Storage*

Set declarations

  1. 1. Double click *Package.appxmanifest*
  2. Click *Declaratons* tab
  3. In *Available Declarations* select *File Type Associations*
  4. Click *Add*
  5. In *Display name* write *txt*
  6. In *Name* write *txt*
  7. In *File type* write *.txt*

C# code

// Enumerate removable devices.
IReadOnlyList folders = await KnownFolders.RemovableDevices.GetFoldersAsync();
foreach (StorageFolder folder in folders)
{
    Debug.WriteLine(folder.Path); // E.g.: D:\
}

if (folders.Count > 0)
{
    StorageFile resultfile = await folders.FirstOrDefault().CreateFileAsync(
        "foo.txt",
        CreationCollisionOption.GenerateUniqueName);

    await FileIO.WriteTextAsync(resultfile, "Hello World");
}

How to know if my Windows computer is compatible with Microsoft Wireless Display Adapter?

This blog moved to kiewic.com

Everybody is excited about the Microsoft Band, but I am more excited about the Microsoft Wireless Display Adapter.

When the Wireless Display Adapter was announced, the first question I had was: “Will this adapter be compatible with my Windows PC?” and “Do I need compatible hardware?”

So, I went with my skip manager and he pointed me that this is easy to know: If you see the “Add a wireless display” link in the Devices > Project charm, then your device is Miracast enabled and therefore it is compatible with the Wireless Display Adapter.

Wireless Display Adapter Windows Devices Charm

Wireless Display Adapter Windows Project Charm

Wireless Display Adapter Widnows Add A Wireless Display

Wireless Display Adapter Windows AddDevices

Wireless Display Adapter Widnows Connecting To MicrosoftDisplayAdapter_78

Today, I received my Wireless Display Adapter! This is how cool it looks:

Wireless Display Adapter Windows Unboxing

Wireless Display Adapter Inside The Box

Wireless Display Adapter TV On HDMI Input

Wireless Display Adapter TV And Windows 8 Laptop

Wireless Display Adapter Connected To USB And HDMI TV Inputs

Of course, not every Windows computer supports Miracast, but because this technology is so awesome, OEMs should make it clear what devices support Miracast (aka Wireless Display)!

Wireless Display Adapter This PC Is Miracast Compatible

Cons?

The name! Microsoft Wireless Display Adapter is not an attractive name, better names could be “Windows Cast”, “Win Mirror”, etc. …

How to get the response content of a DownloadOperation or UploadOperation when the result is not 200 OK?

This blog moved to kiewic.com

It is common that REST APIs return useful information for developers in the response content when the request is not successful.

For example, lets say you want to access the following URL from the Facebook API:

http://graph.facebook.com/v2.2/803370993032579

But you forget to set the authentication parameters in the request, so you make a request to the URL without setting the OAuth token. By inspecting DownloadOperation.Progress.Status, you see the response was 400 Bad Request. But that is not enough information to fix the problem!

The actual Facebook server response contains more information, look at the raw HTTP response:

Access-Control-Allow-Origin: *
Cache-Control: no-store
Connection: keep-alive
Content-Length: 146
Content-Type: application/json; charset=UTF-8
Date: Tue, 04 Nov 2014 03:25:14 GMT
Expires: Sat, 01 Jan 2000 00:00:00 GMT
Facebook-API-Version: v2.2
Pragma: no-cache
WWW-Authenticate: OAuth "Facebook Platform" "invalid_token" "An access token is required to request this resource."
X-FB-Debug: MUJRrIP4wQYZWjXwzGkjsvt8+QaLFJlfAX3w9CRaAXdcSQt5Zs6X8/bd1zWfQzMQBu60XbBF//LpRFR3i2Ejwg==
X-FB-Rev: 1479988

{
  "error": {
    "message": "An access token is required to request this resource.",
    "type": "OAuthException",
    "code": 104
  }
}

You can access the rest of the error information using DownloadOperation.GetResultStreamAt() or UploadOperation.GetResultStreamAt(). You have to get the IInputStream, create a DataReader, load the DataReader and finally read the response content as string.

Here is the example:

// using Windows.Networking.BackgroundTransfer
// using System.Diagnostics;

IStorageFile resultFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(
    "blah.txt",
    CreationCollisionOption.ReplaceExisting);
BackgroundDownloader downloader = new BackgroundDownloader();
Uri uri = new Uri("http://graph.facebook.com/v2.2/803370993032579");
DownloadOperation download = downloader.CreateDownload(uri, resultFile);

await download.StartAsync();

Debug.WriteLine(download.Progress.Status); // 400 Bad Request

IInputStream inputStream = download.GetResultStreamAt(0);
DataReader reader = new DataReader(inputStream);
reader.InputStreamOptions = InputStreamOptions.Partial;

var bytesLoaded = await reader.LoadAsync(1000000);

// Useful error information:
Debug.WriteLine(reader.ReadString(reader.UnconsumedBufferLength));

How to send text, JSON or files using HttpClient.PostAsync().

This post has been moved to: http://kiewic.com/2014-10-23/how-to-send-text-json-or-files-using-httpclient-postasync

This is a common question in StackOverflow and MSDN forums. So, let’s take a look at our three main options.

HttpStringContent

Send a string:

// E.g. a JSON string.
HttpStringContent stringContent = new HttpStringContent(
    "{ \"firstName\": \"John\" }",
    UnicodeEncoding.Utf8,
    "application/json");

HttpClient client = new HttpClient();
HttpResponseMessage response = await client.PostAsync(
    uri,
    stringContent);

This sends a POST request like this:

POST / HTTP/1.1
Accept-Encoding: gzip, deflate
Content-Length: 23
Content-Type: application/json; charset=UTF-8
Host: kiewic.com
Connection: Keep-Alive
Cache-Control: no-cache

{ "firstName": "John" }

See here for examples of how to serialize or parse JSON.

HttpFormUrlEncodedContent

Send a list of key-value pairs, better known as x-www-form-urlencoded:

Dictionary<string, string> pairs = new Dictionary<string,string>();
pairs.Add("Name", "Bob");
pairs.Add("Age", "18");
pairs.Add("Gender", "Male");
HttpFormUrlEncodedContent formContent =
    new HttpFormUrlEncodedContent(pairs);
 
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.PostAsync(uri, formContent);

This sends a POST request like this:

POST / HTTP/1.1
Accept-Encoding: gzip, deflate
Content-Length: 27
Content-Type: application/x-www-form-urlencoded
Host: kiewic.com
Connection: Keep-Alive
Cache-Control: no-cache

Name=Bob&Age=18&Gender=Male

This is equivalent to submit the following HTML form from a web browser:

 <form action="http://kiewic.com" method="post">
  <input name="Name" type="text" value="Bob" />
  <input name="Age" type="text" value="18" />
  <input name="Gender" type="text" value="Male" />
  <input type="submit" />
 </form>

These values can be easily accessed from PHP using the $_POST array. Or from ASP.NET using Request.Form property.

HttpMultipartFormDataContent

Send files, or text and files mixed, better known as multipart/form-data.

First, create a sample file:

IStorageFolder folder = ApplicationData.Current.LocalFolder;
IStorageFile file = await folder.CreateFileAsync(
    "foo.txt",
    CreationCollisionOption.ReplaceExisting);
await FileIO.WriteTextAsync(
    file,
    "The quick brown fox jumps ...");

Then, send a request like this:

IInputStream inputStream = await file.OpenAsync(FileAccessMode.Read);
HttpMultipartFormDataContent multipartContent =
    new HttpMultipartFormDataContent();
multipartContent.Add(
    new HttpStreamContent(inputStream),
    "myFile",
    file.Name);
multipartContent.Add(
    new HttpStringContent("Hello World"),
    "myText");
 
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.PostAsync(
    uri,
    multipartContent);

The raw POST request looks like this:

POST / HTTP/1.1
Accept-Encoding: gzip, deflate
Content-Length: 371
Content-Type: multipart/form-data; boundary=c9b47f5b-ca6c-43bd-a953-6ea78b2ee24b
Host: kiewic.com
Connection: Keep-Alive
Cache-Control: no-cache

--c9b47f5b-ca6c-43bd-a953-6ea78b2ee24b
Content-Disposition: form-data; name="myFile"; filename="foo.txt"; filename*=UTF-8''foo.txt

The quick brown fox jumps ...
--c9b47f5b-ca6c-43bd-a953-6ea78b2ee24b
Content-Length: 11
Content-Type: text/plain; charset=UTF-8
Content-Disposition: form-data; name="myText"

Hello World
--c9b47f5b-ca6c-43bd-a953-6ea78b2ee24b--

These values can be accessed from PHP using the $_FILES array. Or from ASP.NET using the Request.Files property.

Notice that HttpClient encodes attachment file names using RFC 2047 to support file names with non-ASCII characters.

When traveling to Mexico, what forms do I need to fill out?

This blog moved to kiewic.com

As a foreigner, you should fill out two forms before passing immigration when arriving at a Mexican airport:

  1. Customs declaration.
  2. Entry registration form.

The customs declaration looks like this:

Mexico Customs Declaration

Official form is here.

The entry registration card (FMM migration form) looks like this:

Mexico Entry Registration

Mexico Entry Registration Back 2

Mexico Entry Registration Stamp

The entry registration (immigration form) can be split into two. You have to fill out both parts of the form before seeing the immigration agent when arriving to Mexico. The immigration agent will keep the top part, and it will put a stamp to the bottom part, which you must keep and give to the airline when departing from Mexico.

Another picture of the form is here.

It would be better if you fill out the forms in the airplane. Ask for both to your air attendant🙂

Official information here.