Creating a RESTful JSON API in a legacy .NET 3.5 application

Our online Directory has been around in essentially the same form since the early 2000s, though I’ve rewritten it as a PHP application, then as part of Microsoft Content Management Server 2003 as a .NET 1.0 application, then as a PHP application again, and then as a .NET 1.1 application, and then upgraded it in .NET a few times. Along the way, it acquired a SOAP web service, which is accessible at https://directory.middlebury.edu/WebDirectory.asmx and is the primary interface for Directory information displayed in our Drupal sites, including profiles.

This fall, we needed to add a RESTful web service that returned some public Directory information as a JSON string for use in a mobile app. If I were doing the Directory all over from scratch it would probably be some MVC application with some nice endpoints that returned this data already, if it was in .NET, but that’s not the situation we’re in right now, so I had to find a way to hack a REST API on top of this thing.

Apparently, that’s possible using a Web Service ASMX file, which looks like a SOAP service, but with a few tweaks can act like a REST service. The gist below ends in .cs, but that’s just so the syntax highlighting looks nice. It’s really a .asmx file.

The first key is to uncomment the “[ScriptService]” notation above the class so that it can act as an AJAX response service, if needed. Next, above the method for the service response, add the notation “[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]”, which allows the service to accept GET requests and return a JSON response. Change the return type of the method to “void”, since we’ll just be printing our response directly, rather than returning a value that gets send via an XML wrapper.

The inner part of my search method is mostly program logic that creates an object and populates it with information from the Directory application based on the input query and business logic about what data to return. I decided to use the JSON.NET NuGet package after trying .NET’s native JavaScriptSerializer class, which kept pegging the CPU t 100% trying to serialize the object.

The JSON.NET object serializer offers a few more advantages. You can tell it to indent the response, if you want (I chose not to), and you can tell it not to include any property in the response where the value is null. For instance, if a person doesn’t have a telephone number, rather than returning “{phone: null}”, that portion of their record will just be blank.

Lastly, I write the JSON string directly to the HTTP response, which is why I earlier changed the method return type to void. With this in place, the service is now available at http://directory.middlebury.edu/RESTfulDirectory.asmx/Search?q=

Displaying a date field in two formats in Drupal 8

Working on the conversion of our Museum of Art site, I ran into an issue with our “event” content type where we store the date and time of the event in a single datetime field, but want to display this information in two formats in different parts of the markup. In Drupal 7, we handled this using a preprocess function to access the data and set variables, but I wanted to find a more elegant solution in Drupal 8.

One option for this would be to have a, computed second field that stores the value again so it can be output twice in the node template and allow Drupal’s field API to format the output differently each time. I decided against this as it would require duplicating the data in the database.

Instead, I decided to format the date in the Twig template. Complicating this is that the date is stored as a string, rather than a timestamp in the database, so even if I tell the field API to format the output as a timestamp, there’s no way to directly access just that value without any of the markup.

To get around this, I set a variable in the Twig template to the value of the field piped to the date() function with the ‘U’ format, which will return an integer timestamp. This can then be passed into format_date() to have the date show up as desired.

Always showing a teaser for lists of content in Drupal

For the main Middlebury and MIIS websites, we run a module named Monster Menus that adds hierarchical pages and permissions on top of Drupal. One of the effects of this is that we have many pages that are lists of nodes some of which we want to display in a full view, others of which we want to display as teasers. A common example is a list of news articles with a simple node stickied at the top. We want the news items to show up as teasers, allowing you to click through to see one of them in full view mode, but we also want that basic node at the top of the page to show up fully.

In Drupal 6 we achieved this by creating a custom template file outside of Drupal’s normal theme hooks and adding it to the template files array in the node preprocess function 1 within template.php 2.

Then we could have node-newslist.tpl.php along with node.tpl.php and show different markup. This all worked quite well in Drupal 6 because the CCK module exposed all the field data to the preprocess functions and you could manipulate it however you liked before outputting it. But it runs into trouble with Drupal 7’s field API and render arrays. You can still do it in Drupal 7, and just need to change “template_files” to “theme_hook_suggestions” in the example shown above, but I decided to go a different direction.

With Drupal 7’s new entity API, you can update how the render array is built based on the node’s metadata in hook_entity_view_mode_alter(). This has the advantage that the node now is rendered as a teaser and the fields set for that display mode in the admin interface show up as you’d normally expect them to, in the order defined, with the wrapper elements specified, and using the standard theme hook suggestion of node__TYPE__teaser.tpl.php.

Notes:

  1. In order to make our preprocess functions a bit easier to read, we separate out the functionality for each content type into its own function using this method: [gist https://gist.github.com/imcbride/11ca63c4b2f17f089d46]
  2. arg(1) is normally the node id when viewing a Drupal URL ending in /node/123. In Monster Menus, the node id is actually arg(3) since its URLs are of the form /mm/123/node/456 where the first number is the page id. I’ve used arg(1) in the examples to keep them familiar to most Drupal developers.