How to create WordPress blog posts from C# with HttpClient and the WordPress REST API on Docker for Windows 10

 
 

To create WordPress blog posts from C# I will be using docker container on my Windows 10 Pro installation.

Before installing docker on Windows 10 make sure the Windows 10 feature “Hyper-V” is enabled:

 
 


 
 

Install docker on Windows 10

I followed this blog post to install docker on Windows 10

https://docs.docker.com/docker-for-windows/install/#about-windows-containers

 
 

Create WordPress docker container

To create a WordPress docker container I followed this post:

https://docs.docker.com/compose/wordpress/

 
 

How to read blog post information from C#

When the WordPress docker container is running, you should create your first blog post manually on http://localhost:8000.

Now reading all blog post data, is easy, because we can use an GET request without authentication, by using the C# code below.

 

 

 

Installing JWT Authentication for WP-API plugin

Now when you want to create a blog post from C# you will need to use a POST request with authentication.

I used JWT (JSON Web Tokens).

When you want to use JWT in WordPress you should first install the JWT Authentication for WP-API plugin.

After installing the plugin we must first edit two files before activating the plugin.

 
 

 
 

Edit .htaccess file on Windows

 
 

Get WordPress container name on windows:

  • Open PowerShell and enter:
  • docker ps –all

Copy .htaccess file from docker container to local Windows host:

  • docker cp wordpress_wordpress_1:/var/www/html/.htaccess .htaccess

Edit the file with your preferred editor (I used Visual Studio Code), add the rows in red:

 
 

# BEGIN WordPress

<IfModule mod_rewrite.c>

RewriteEngine On

RewriteBase /

RewriteRule ^index\.php$ – [L]

RewriteCond %{REQUEST_FILENAME} !-f

RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule . /index.php [L]

RewriteCond %{HTTP:Authorization} ^(.*)

RewriteRule ^(.*) – [E=HTTP_AUTHORIZATION:%1]

</IfModule>

SetEnvIf Authorization “(.*)” HTTP_AUTHORIZATION=$1

# END WordPress

 
 

 
 

Copy .htaccess file from local Windows host to Docker container:

  • docker cp .htaccess wordpress_wordpress_1:/var/www/html/.htaccess

 
 

 
 

Edit wp-config.php on Windows

 
 

Get WordPress container name on windows:

  • Open PowerShell and enter:
  • docker ps –all

Copy wp-config.php file from docker container to local Windows host:

  • docker cp wordpress_wordpress_1:/var/www/html/wp-config.php wp-config.php

Edit the file with your preferred editor (I used Visual Studio Code), add the rows in blue:

 
 

<?php

define(‘DB_NAME’, ‘wordpress’);

define(‘DB_USER’, ‘wordpress’);

define(‘DB_PASSWORD’, ‘bla bla bla’);

define(‘DB_HOST’, ‘db:3306’);

define(‘DB_CHARSET’, ‘utf8’);

define(‘DB_COLLATE’, );

define(‘AUTH_KEY’, ‘bla bla bla’);

define(‘SECURE_AUTH_KEY’, ‘bla bla bla’);

define(‘LOGGED_IN_KEY’, ‘bla bla bla’);

define(‘NONCE_KEY’, ‘bla bla bla’);

define(‘AUTH_SALT’, ‘bla bla bla’);

define(‘SECURE_AUTH_SALT’, ‘bla bla bla’);

define(‘LOGGED_IN_SALT’, ‘bla bla bla’);

define(‘NONCE_SALT’, ‘bla bla bla’);

define(‘JWT_AUTH_SECRET_KEY’, ‘bla bla bla’);

define(‘JWT_AUTH_CORS_ENABLE’, true);

$table_prefix = ‘wp_’;

define(‘WP_DEBUG’, false);

// If we’re behind a proxy server and using HTTPS, we need to alert WordPress of that fact

// see also http://codex.wordpress.org/Administration_Over_SSL#Using_a_Reverse_Proxy

if (isset($_SERVER[‘HTTP_X_FORWARDED_PROTO’]) && $_SERVER[‘HTTP_X_FORWARDED_PROTO’] === ‘https’) {

    $_SERVER[‘HTTPS’] = ‘on’;

}

/* That’s all, stop editing! Happy blogging. */

/** Absolute path to the WordPress directory. */

if ( !defined(‘ABSPATH’) )

    define(‘ABSPATH’, dirname(__FILE__) . ‘/’);

/** Sets up WordPress vars and included files. */

require_once(ABSPATH . ‘wp-settings.php’);

 
 

Copy wp-config.php file from local Windows host to Docker container:

  • docker cp wp-config.php wordpress_wordpress_1:/var/www/html/wp-config.php

 
 

 
 

How to create blog posts from C#

 
 

using System;

using System.Collections.Generic;

using System.Net.Http;

using System.Net.Http.Headers;

using System.Text;

using Newtonsoft.Json;

 
 

public
class
TokenInfo

{

    public
string token { get; set; }

public
string user_email { get; set; }

public
string user_nicename { get; set; }

public
string user_display_name { get; set; }

}

 
 

     using (var client = new HttpClient())

{

client.BaseAddress = new Uri(“http://localhost:8000”);

 
 

string loginInfo = @”{“”username””: “”your-wordpress-user””, “”password””:””your-wordpress-password””}”;

 
 

 
 

var tokenResponse = await client.PostAsync(

“/wp-json/jwt-auth/v1/token”,

new StringContent(loginInfo, Encoding.UTF8, “application/json”));

 
 

if (tokenResponse.IsSuccessStatusCode)

{

string tokenAsText = await tokenResponse.Content.ReadAsStringAsync();

TokenInfo tokenInfo = JsonConvert.DeserializeObject<TokenInfo>(tokenAsText);

 
 

string blogPost = @”{“”title””: “”Blog post from C# – v2″”, “”content””: “”<div>Just some content</div>””}”;

client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(“Bearer”, tokenInfo.token);

 
 

var createPostResponse = await client.PostAsync(

“/wp-json/wp/v2/posts”,

new StringContent(blogPost, Encoding.UTF8, “application/json”));

 
 

if (createPostResponse.IsSuccessStatusCode)

{

Console.WriteLine(“Success!”);

}

}

}

 
 

Now this new post will be created, but it will not directly be visible, because it is created as draft.

To publish the post you will have to set the status to publish

 
 

How to publish a draft post from C#

 
 

using System;

using System.Collections.Generic;

using System.Net.Http;

using System.Net.Http.Headers;

using System.Text;

using Newtonsoft.Json;

 
 

public
class
TokenInfo

{

    public
string token { get; set; }

public
string user_email { get; set; }

public
string user_nicename { get; set; }

public
string user_display_name { get; set; }

}

 
 

using (var client = new HttpClient())

{

client.BaseAddress = new Uri(“http://localhost:8000”);

 
 

string loginInfo = @”{“”username””: “”your-wordpress-user””, “”password””:””your-wordpress-password””}”;

 
 

 
 

var tokenResponse = await client.PostAsync(

“/wp-json/jwt-auth/v1/token”,

new StringContent(loginInfo, Encoding.UTF8, “application/json”));

 
 

if (tokenResponse.IsSuccessStatusCode)

{

string tokenAsText = await tokenResponse.Content.ReadAsStringAsync();

TokenInfo tokenInfo = JsonConvert.DeserializeObject<TokenInfo>(tokenAsText);

client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(“Bearer”, tokenInfo.token);

 
 

string blogPost = @”{“”status””: “”publish””}”;

int blogPostId = 8; // This is the ID for the draft blogpost you want to publish.

string blogPostUpdateUrl = $”/wp-json/wp/v2/posts/{blogPostId};

var createPostResponse = await client.PostAsync(

blogPostUpdateUrl,

new StringContent(blogPost, Encoding.UTF8, “application/json”));

 
 

if (createPostResponse.IsSuccessStatusCode)

{

Console.WriteLine(“Success!”);

}

}

Assert.AreEqual(true, true);

}

 
 

 
 

 
 

How to get all draft posts from C#

To get all draft posts from C# you must be authenticated so use the following code:

 
 

using System;

using System.Collections.Generic;

using System.Net.Http;

using System.Net.Http.Headers;

using System.Text;

using Newtonsoft.Json;

 
 

public
class
TokenInfo

{

    public
string token { get; set; }

public
string user_email { get; set; }

public
string user_nicename { get; set; }

public
string user_display_name { get; set; }

}

 
 

 
 

using (var client = new HttpClient())

{

client.BaseAddress = new Uri(“http://localhost:8000”);

 
 

string loginInfo = @”{“”username””: “”your-wordpress-user””, “”password””:””your-wordpress-password””}”;

 
 

 
 

var tokenResponse = await client.PostAsync(

“/wp-json/jwt-auth/v1/token”,

new StringContent(loginInfo, Encoding.UTF8, “application/json”));

 
 

if (tokenResponse.IsSuccessStatusCode)

{

string tokenAsText = await tokenResponse.Content.ReadAsStringAsync();

TokenInfo tokenInfo = JsonConvert.DeserializeObject<TokenInfo>(tokenAsText);

client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(“Bearer”, tokenInfo.token);

 
 

var response = await client.GetAsync(“/wp-json/wp/v2/posts?status=draft”);

 
 

if (response.IsSuccessStatusCode)

{

string postsAsText = await response.Content.ReadAsStringAsync();

List<WpPost> draftPosts = JsonConvert.DeserializeObject<List<WpPost>>(postsAsText);

foreach (WpPost post in draftPosts)

{

Console.WriteLine($”tile [{post.title}]”);

}

}

 
 

}

Assert.AreEqual(true, true);

}

 
 

Note : I used http://json2csharp.com to convert JSON to C# classes to get a type safe response from the server.

The following code is generated by http://json2csharp.com

 public
class
WpGuid

{

public
string rendered { get; set; }

}

 

public
class
Title

{

public
string rendered { get; set; }

}

 

public
class
Content

{

public
string rendered { get; set; }

public
bool @protected { get; set; }

}

 

public
class
Excerpt

{

public
string rendered { get; set; }

public
bool @protected { get; set; }

}

 

public
class
Self

{

public
string href { get; set; }

}

 

public
class
Collection

{

public
string href { get; set; }

}

 

public
class
About

{

public
string href { get; set; }

}

 

public
class
Author

{

public
bool embeddable { get; set; }

public
string href { get; set; }

}

 

public
class
Reply

{

public
bool embeddable { get; set; }

public
string href { get; set; }

}

 

public
class
VersionHistory

{

public
string href { get; set; }

}

 

public
class
WpAttachment

{

public
string href { get; set; }

}

 

public
class
WpTerm

{

public
string taxonomy { get; set; }

public
bool embeddable { get; set; }

public
string href { get; set; }

}

 

public
class
Cury

{

public
string name { get; set; }

public
string href { get; set; }

public
bool templated { get; set; }

}

 

public
class
Links

{

public List<Self> self { get; set; }

public List<Collection> collection { get; set; }

public List<About> about { get; set; }

public List<Author> author { get; set; }

public List<Reply> replies { get; set; }

public List<Cury> curies { get; set; }

}

 

public
class
WpPost

{

public
int id { get; set; }

public DateTime date { get; set; }

public DateTime date_gmt { get; set; }

public WpGuid guid { get; set; }

public DateTime modified { get; set; }

public DateTime modified_gmt { get; set; }

public
string slug { get; set; }

public
string status { get; set; }

public
string type { get; set; }

public
string link { get; set; }

public Title title { get; set; }

public Content content { get; set; }

public Excerpt excerpt { get; set; }

public
int author { get; set; }

public
int featured_media { get; set; }

public
string comment_status { get; set; }

public
string ping_status { get; set; }

public
bool sticky { get; set; }

public
string template { get; set; }

public
string format { get; set; }

public List<object> meta { get; set; }

public List<int> categories { get; set; }

public List<object> tags { get; set; }

public Links _links { get; set; }

}

 
 

 
 

 
 

 
 

  

Fingerprint bundles in path, not in query parameter with System.Web.Optimization and Visual Studio 2015

In my previous post (https://www.roelvanlisdonk.nl/?p=4550) I explained how to:

– create a new ASP .NET MVC 5 .NET 4.6 project in Visual Studio 2015

– add static caching, add url rewrites

– add fingerprinting to the “folder part” of each URL, to bust the client cache, when a new build is deployed to the website

 

Now if you don’t want to use the URL Rewrite approach, but you still want to fingerprint the “folder url part” of the bundels created with the System.Web.Optimization (instead of using the standard query parameter cache busting technique), you can use the following class:

 

image

 

Use this class, when the bundles are created and when they are used inside the *.cshtml:

 

image

 

Then inside a *.cshtml page:

 

image

 

In this way, only the “name” of the bundle is fingerprinted and bundeling will only take place in “release” build.

The System.Web.Optimization will take care of the “cache busting”, no need for “URL rewriting”.

 

The code uses the following extension method:

 

image

Cache busting / fingerprinting bundles with System.Web.Optimization and Visual Studio 2015

I like to use client build systems like grunt, gulp, webpack etc. to bundle and minify JavaScript and CSS files, but on a resent project I had to use the Microsoft Web optimization framework.

 

Note: All code used in this blog post  can be found at: https://github.com/roelvanlisdonk/POC/tree/master/ASP.NET/CacheBusting

 

In this I will describe how to create an MVC .NET 4.6 web application, that uses bundeling, minification and fingerprinting for cache busting all by using the System.Web.Optimization framework.

 

Start Visual Studio 2015, then click:

File> New > Project…

 

Choose: Installed\Templates\Visual C#\Web\ASP.NET Web Application

 

image

Choose: “ASP.NET 4.6 Templates”: “Empty” and “Add folders and core references for”: “MVC”

 

image

 

Add a “MVC 5 Layout Page (Razor)” called “_Layout” to the “Views” folder

 

image

 

 

 

Add a “Home” controller to the “Controllers” folder:

image

 

Choose: MVC 5 Controller – Empty

 

image

 

Add a “Index.cshtml” view to the /Views/Home folder:

 

image

 

Choose the “_Layout.cshtml” as “layout page”

 

image

 

Change html:

 

image

 

Add some TypeScript files and CSS files to the /Views/Home folder:

 

image

 

image

 

image

image

To allow static file content serving from the “/Views” folder adjust the Web.config inside the “/Views” folder, remove the “BlockViewHandler”:

image

Add the System.Web.Optimization NuGet package to your project:

 

image

 

Search for “Optimization” and choose: Microsoft.AspNet.Web.Optimization

 

image

 

This will install the following dependencies to your project:

 

image

 

After installing the package we will first upgrade some of the components, just change the filer to “Upgrade available”:

 

image

 

Upgrade all packages until all package are upgraded:

image

 

Add a NonOrderingBundleOrderer.cs class to the “/Common” folder.

This class will prevent automatic ordering of the files inside the bundle.

The files will be placed in the html in the order they are added to the bundle.

 

image

 

Add a BundleConfig.cs class to the “App_Start” folder

 

image

 

Change code like:

The “#if !DEBUG”, means:

In “debug” modus all files are rendered separately to the HTML in “release” modus all JavaScript files are combined to one JavaScript file and all CSS files are combined to one CSS file.

image

 

Change the global.asax

Add “BundleConfig.RegisterBundles(BundleTable.Bundles);”

image

 

Add a class “AssemblyExtensions.cs” to the “/Extensions” folder:

image

 

Edit code like:

image

 

 

Add a class “Bundle.cs” to the “/Common” folder:

image

 

Edit code like:

image

 

Change the “_Layout.cshtml” like:

The layout page contains the actual rendering of the CSS and JavaScript bundles.

image

 

When we run the application at this point we get 4 errors in the Browser console, because all JavasScript files and CSS files are fingerprinted with a version number and do not exist on disk:

 

image

 

To solve this error, we can add Url Rewriting to our Web.config file and start caching files:

 

To start caching files, add the following xml to the Web.config:

 

image

 

 

URL Rewrite extension

To start using Url Rewriting, first install the URL from http://www.iis.net/downloads/microsoft/url-rewrite or from the web platform installer inside IIS.

Note that URL Rewriting will work out of the box with IIS Express in Visual Studio 2015.

 

image

 

Then add the following to the Web.config:

 

image

 

All url’s that start with vx.x.x.x/ will be rewritten (the version number will be removed from the URL before passing it to the reset of ASP .NET. Only the part after the first “/” will be presented to the “match” rule.

So only the part “v1.0.0.0/View/Home/Test1.js” of the url http://localhost:4567/v1.0.0.0/View/Home/Test1.js will be passed to the match rule, that’s why the regex can start with a “^”.

 

Now when you run the application in debug modus you will see:

 

image

 

And when you run in “release mode” you will see:

image

 

As you can see the System.Web.Optimization framework automatically adds a “cache busting query parameter”, but in some browsers this is not enough, that’s why we added a version number inside the “folder” part of the url.

 

 

The final project structure should look like:

 

image

 

For more resources see: http://madskristensen.net/post/cache-busting-in-aspnet

 

 

NOTE

If you use “URLs” inside a CSS file, that is added to a bundle, e.g.

background-image: url(https://www.example.com/bck.png);

Then these URLs should also be fingerprinted.

To fingerprint these URLs you can write a custom BundleTransform:

http://blog.mirajavora.com/deep-dive-into-asp.net-bundling-and-minification/

 

Or use the https://bundletransformer.codeplex.com/.

This extension to the System.Web.Optimization framework, supports automatic transformation of relative paths to absolute paths in CSS-code (by using UrlRewritingCssPostProcessor).

How to send a free SMS from C#

I used the following code to send a free SMS from C#, by using the messagebird REST service.

 

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace DocumentenService.Client
{
public class Program
{
public static void Main(string[] args)
{
SendSms().Wait();
// Wait for the user to close this application.
Console.WriteLine("Press enter to close this application.");
string result = Console.ReadLine();
}
/// <summary>
/// Send a sms
/// </summary>
/// <returns></returns>
public static async Task SendSms()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://rest.messagebird.com/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("AccessKey", "live_...");
var message = new SmsMessage
{
body = "SMS send from C#, greetings Roel.",
originator = 31611111111, // Sender
recipients = new long[] { 31622222222 } // Receivers
};
HttpResponseMessage response = await client.PostAsJsonAsync("messages", message);
if (response.IsSuccessStatusCode)
{
Console.WriteLine("succes!");
}
}
}
}
public class SmsMessage
{
/// <summary>
/// Example: This is a test message.
/// </summary>
public string body { get; set; }
/// <summary>
/// Example: 31611111111
/// </summary>
public long originator { get; set; }
/// <summary>
/// Example: new long[] { 31622222222 } 
/// </summary>
public long[] recipients { get; set; }
}
}

One of the most important things to remember: In C# and JavaScript, object references are passed to functions by value not by reference

By default C# and JavaScript pass object references by value not by reference, but what does that mean?

Well if you assign an object to a variable, this variable is just a pointer to that object in memory.

(Examples in C#)

var person = new Person
{
Id = 2,
Name = "John"
};

The variable person is just a pointer to the object in memory, the memory contains the object { Id = 2, Name = “John”}

When passed to a function, a copy of this pointer is supplied to the function, not the object itself.

So when you update properties of the object in the function, the variable outside the function will get updated.

 

But when you set the object to NULL in the function, the variable outside the function will NOT be set to NULL.

 

In C# you can override this by adding the “ref” keyword before the parameter, in that case the pointer of the variable will be passed and thus setting the object to null in the function will set the variable outside the function to NULL.

 

Some unit test to explain this:

namespace Test
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;      
[TestClass]
public class Research
{
[TestMethod]
public void Update_object_properties_should_update_variable()
{
var person = new Person
{
Id = 2,
Name = "John"
};
UpdateObjectProperties(person);
Assert.IsTrue(person.Name == "Mike");
}
public void UpdateObjectProperties(Person person)
{
person.Name = "Mike";
}
[TestMethod]
public void Update_object_pointer_should_not_update_variable()
{
var person = new Person
{
Id = 2,
Name = "John"
};
UpdateObjectPointer(person);
Assert.IsTrue(person.Name == "John");
}
public void UpdateObjectPointer(Person person)
{
person = null;
}
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
}

 

image

 

More info can be found at:

http://stackoverflow.com/questions/9717057/c-sharp-passing-arguments-by-default-is-byref-instead-of-byval

http://jonskeet.uk/csharp/parameters.html

http://jonskeet.uk/csharp/references.html

How to rename an user in Active Directory with C#

 

If you want to rename an user in Active Directory by using C#, you can use the following code:

using System;
using System.Collections.Generic;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("This application will rename a user in active directory.");
Console.WriteLine(Environment.NewLine);
Console.WriteLine("Enter domain:");
string domain = Console.ReadLine();
Console.WriteLine("Connecting to domaincontroller.");
using (PrincipalContext context = new PrincipalContext(ContextType.Domain, domain))
{
if (context == null)
{
throw new ApplicationException("Domain not found.");
}
Console.WriteLine("Enter current username (e.g. john):");
string currentUserName = Console.ReadLine();
using (UserPrincipal user = UserPrincipal.FindByIdentity(context, currentUserName))
{
if (user == null)
{
throw new ApplicationException("User not found.");
}
Console.WriteLine("Enter new username (e.g. john2):");
string newUserName = Console.ReadLine();
using (DirectoryEntry entry = (DirectoryEntry)user.GetUnderlyingObject())
{
Console.WriteLine("Setting account properties in active directory.");
entry.InvokeSet("uid", newUserName);
entry.InvokeSet("sAMAccountName", newUserName);
entry.InvokeSet("userPrincipalName", string.Format("{0}@{1}", newUserName, domain));
entry.CommitChanges();
Console.WriteLine("Rename common-name (CN).");
entry.Rename("CN=" + newUserName);
entry.CommitChanges();
Console.WriteLine("User successfully renamed.");
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.WriteLine("Press enter to continue...");
Console.ReadLine();
}
}
}

Most developers say: code comments are evil, I agree and I don’t agree…

Most developers I know say: don’t write any comments, because they are evil and little puppies will dye if you do.

The arguments they give:

  • code comments will get out of date
  • code should be self explaining.

 

I totally agree, but there are counter arguments, to write comments:

 

Code comments out of date?

If you look at the AngularJS code, the comments are used to generate the documentation on the site, so when the comments are not updated, the documentation on the site will be outdated. This is one trick to keep your comments up to date.

 

Code should be self explaining

I totally agree, code should be self explaining!

But it’s not the problem, that code comments are written, but the way they are written.

The most comments explains what the code does, not why. I do not care, “what” the code does, I want to know “why” it is written and “why” it is written in the manner it is written.

 

I recently had to make changes to C# code that was written ages ago (13 months in this case). I red the code and the “WTF counts per minute” started to pile up. I red the code comments and they exactly explained what the code did, but I am an experienced C# developer, I know what the code does, because I can read C#, but I did not understand why the code was written and why it was written in the way it was written.

So I checked source control to find this “terrible” developer that had written this code to ask him, what on earth he was thinking and as you will probably expect it was me, myself and I, 13 months ago Smile.

 

So please, if you write inline comments, don’t write “what the code does”, write “why” the code is written and “why” you write it in the way it is written”.

Post arbitrary JSON data to a MVC controller action method

If you want to sent arbitrary JSON data to a MVC controller action method, you can use the following code:

[HttpPost]
public ActionResult HandleRequest()
{
// Read the RAW JSON from the request, 
// because MVC does not support a dynamic input parameter or an input parameter of type JObject.
// ASP .NET Web API does support a dynamic input parameter or an input parameter of type JObject.
string json = new StreamReader(this.Request.InputStream).ReadToEnd();
dynamic clientData = JObject.Parse(json);