Developing in React with an API hosted in IIS

The Problem

I’ve recently decided to embrace React for my front-end development, having previously used Sencha Ext JS for many years, but returning to jQuery this past year. The idea of using npm and webpack to build a web site once gave me the heebie-jeebies, but without it, you end up with the sprawling and unmanageable mess that I created with jQuery, which I did in haste to move away from Ext JS for a particular project. I still like Ext JS but, following some hefty price increases and uncertainty following a change of ownership, the wisdom of an exit strategy became apparent.

So, now that I’ve chosen React, how do I get the webpack-dev-server running on port 3000 to play nice with my existing .NET web service running in IIS on port 80? I searched but couldn’t find a way to get my React app — with hot module replacement — running within IIS. I once inherited a VB.Net web app (urgh!) that took 30 seconds to rebuild every time I had to test a change in the browser, and I wasn’t going to go through that nightmare again with “react-scripts build” (whose output, of course, does play nicely with my existing API when running from within IIS).

Instead of trying to get the webpack-dev-server (via “react-scripts start”) to talk to a “foreign” API (on a different port), why not try and approach things from the other end?

The Solution

The easiest way to make my c# .NET WCF web service play nicely with React on port 3000 is to:

  • Enable CORS
  • Use identity impersonation
  • Enable anonymous access

This way, I can take advantage of the hot module replacement updating my browser instantly whilst still using my API with its need for windows authentication retained (via impersonation). Here’s what you need to do…

Add the following three lines (in bold) to the web.config file at the root of your web service:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.web>
    <identity configSource="IdentitySecrets.config" />
  </system.web>
  <system.webServer>
    <security>
        <authentication>
            <anonymousAuthentication enabled="true" />
        </authentication>
    </security>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="http://localhost:3000" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>
</configuration>

If you’re happy to keep your password as plain text in the main web.config file, you could just use this line instead of the one above:

<identity impersonate="true" password="whatever" userName="domain\me" />

But because I don’t like that idea, I’m shifting the configuration of the identity impersonation to a separate file, firstly so that I can encrypt it without cluttering up my main web.config, but secondly so that I can exclude it from version control. In order to encrypt the identity tag, create the following file in a temporary directory and call it web.config:

<configuration>
  <system.web>
    <identity impersonate="true" password="whatever" userName="domain\me" />
  </system.web>
</configuration>

Now open a command-prompt as Administrator and navigate to that directory. Find the appropriate version of .NET for your web service then execute the following command to encrypt the file (the period at the end is important; it denotes the current directory where the web.config file is located):

C:\Windows\Microsoft.NET\Framework\v4.0.30319\apsnet_regiis.exe -pef system.web/identity .
Administrator command-prompt window

If you encounter any problems trying to encrypt the file, see if this article is of any help. You should now have an encrypted version of the web.config file, which will look similar to the picture below:

Web.config file showing encrypted values after running aspnet_regiis.exe

You will need to open the newly-encrypted web.config file in a text editor and remove the <configuration> and <system.web> tags, since the configSource attribute on the <identity> tag expects an <identity> tag to be the root element in the file (but aspnet_regiis.exe won’t encrypt it without the file looking like a proper web.config). After removing those tags, save it as IdentitySecrets.config in the same location as the web.config of your web service.

With identity impersonation and CORS now configured in your web service, you should be good to go. Rebuild the web service and then make a call to http://localhost/myapi from your http://localhost:3000 React app, and it should work nicely.

Minor Caveat

The only tiny problem with this approach is that you will get errors like this when navigating into the authentication node of the web service in the IIS Admin console:

IIS Admin console error message

When you dismiss the error message, the authentication section looks like this, with “Retrieving status…” in the status column for all authentication types:

IIS Admin console showing the Authentication section

The web service continues to operate just fine, but the admin console can’t handle the encrypted identity impersonation. If you need to make other changes to the authentication settings through the console, just remove the <identity> tag from the web.config, make the changes, then put the <identity> tag back when you’re done.

Finishing Up

One last thing that you should probably do is make some changes to your web.config transformation files (if you have them) so that the identity impersonation, anonymous access, and CORS changes are not deployed to your test and production servers (which will use the built version of your React app):

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <system.web>
    <compilation xdt:Transform="RemoveAttributes(debug)" />
    <identity xdt:Transform="Remove" />
  </system.web>
  <system.webServer>
    <security>
        <authentication>
            <anonymousAuthentication xdt:Transform="Remove" />
        </authentication>
    </security>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" xdt:Locator="Match(name)" xdt:Transform="Remove" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>
</configuration>

If you’re in a team of developers and they don’t wish to use identity impersonation in their development copies of the web service (and also don’t want to keep commenting out the <identity> tag each time they do a git pull or svn update), they can just create an IdentitySecrets.config file as follows:

<identity impersonate="false" password="whatever" userName="nobody" />

Enabling anonymous authentication (so that React can access the API unhindered) may also mean you have to change the way you’re identifying users in your web service. Instead of using System.Web.HttpContext.Current.User I had to change to using System.Security.Principal.WindowsIdentity.GetCurrent() (which seems to identify the current user correctly, whether I’m using anonymous+impersonation or Windows authentication by itself).

Enjoy.

Oracle SQL Developer’s Laziness

Come on, Oracle. Is it that hard to scan a directory to look for one of your own products?

Oracle SQL Developer first-run screen asking for path to JDK

The path I gave it was “C:\Program Files\Java\jdk1.8.0_152”.

Was that so hard? If you’d like some help in looping through a directory, give me a call.

This is why Java gets such a poor reputation with some people. Its developers are just bone idle and couldn’t be bothered to take care of something so fundamentally basic.

Java could be so much better than this.

Ext JS 6 Formulae to Combine Date and Time fields

My brother has been on my case to blog something about web development; he blogs at the drop of a hat whereas my offerings are usually spread years apart. I develop using Ext JS for a living (among other things) and its lack of a combined date/time field is very annoying. Previously I would copy the time onto the selected date before saving the record, but that’s a bit nasty. So I’ve written some ViewModel formulae to do it instantly.

Here is the result:

Specifying the date first will default to 9:00 AM, and specifying a time first (without having entered a date already) will default to the current day. I am using the ViewModel.links property to create a new DateAndTime model instance (which I’ve named ‘rec’). The Date and Time fields are bound to ‘{Date}’ and ‘{Time}’ and the get and set methods on their respective formulae take care of changing the shared datetime field on the model. There is a display field bound to the ‘{DateAndTime}’ formula which shows the current value the moment it changes.

It’s quite likely that anybody not versed in the many intricacies of Ext JS won’t have a clue what I’m talking about here. This post is not for you :-) But it might help some poor sod dealing with the inconvenience of not having one field to take care of both the date and the time in Ext JS. Perhaps an override might be better but I try to come up with solutions that don’t involve any extra jiggery pokery (I also use Sencha Architect, where it’s very easy to see what I’ve done if I happen to work on my old code one day; it does happen from time to time!).

Coding on Apple is still a love/hate relationship

So, it’s been almost two years since I posted anything here, and it’s just over two years (almost to the day), since I last had a good whinge about XCode. It has only been laziness that has kept me from spewing much guts here about all kinds of annoyances.

So, I’ve been learning Swift for the past year, and whilst it was long overdue, it’s only the language part of the equation. The Cocoa API is still a nasty piece of work; give me the .NET Framework and C# ANY DAY (except if that means I have to use Windows at home; sorry, but I can use it at work writing web services and such like, but I’m not letting that operating system near my computer at home).

So, here’s what drove me mad about XCode/Swift/Cocoa today:

I used to have a drag/drop connection between a combobox and a class to handle the selection change event. That worked fine, however, when I modified it to also handle updating something as the user typed each letter in the combobox, the handling of selection changes failed. You can only handle one or the other when doing the drag/drop connection crap between the combobox and the IBAction.

So, I found a delegate method, which means that I modified the relevant view controller to implement the NSComboBoxDelegate protocol so that it suddenly receives all of the methods in that protocol, whether I implement them or not; the ones I care to implement actually do get called, and the others are ignored. This seems strange to a .NET programmer, and takes a bit of getting used to, but it can also be very powerful (and a time saver in some cases).

This delegate method is the comboBoxSelectionDidChange notification. Being a “did change” event you’d think that it would only call the method when I have actually finished selecting an item from the drop-down list portion of the combobox. You would be mistaken. Past tense apparently isn’t past tense in Cocoa.

Only one problem: if I use “combo.stringValue” inside that method it still returns the previous value in the text part of the combobox. If I want to get the text of the item that the user selected, I’ve got to do this:

dateCombo.itemObjectValueAtIndex(dateCombo.indexOfSelectedItem) as! String

I do not have the words to describe my disappointment.

Come on Apple, the Cocoa framework needs a decent upgrade.

Please.

Self Flagellation with Objective-C and XCode

This post is called Self Flagellation with Objective-C and XCode because I think that is an apt description of what I’m doing. In case you don’t know what flagellation is, this wikipedia article will provide the full story, but suffice it to say that it comes from Latin and means whipping, and that’s exactly what I’m doing to myself every time I try to use XCode.

I should probably number my grievances because there are probably going to be many, and they’re not in any particular order. I should also point out that it’s early days for me with XCode, but after buying several ebooks on Objective-C and Mac/iOS development, and reading two so far and doing all the exercises therein, I’ve had more than just a cursory glance at XCode, and I feel as though I’ve given it quite some time for it to prove its worth before giving up and curling up into a ball, crying like a baby (which is an appealing prospect at the moment!).

  1. XCode is full of annoying control-dragging of things to other things, for example, simply in order to wire up an event for a button or an outlet for same if you want to be able to talk to said button programmatically.

     

  2. Clicking on a file to work on it overlaps the previous file you had in the main editor area in the middle. If you double-click on the file, it opens in an entirely separate window, not in a tab as one might expect of any normal IDE. You can open files in a new tab, providing you open the new tab first, then click on the other file you want to open in that new tab. There is no right-clicking on said file to open in a new tab, that would be too useful!

     

  3. This is more to do with Objective-C than XCode but all classes are really split across two files, the header file (.h) and the implementation file (.m). As someone who is used to storing everything for one class in a whatever.cs file in my day job, having to toggle between .h and .m at home is a major pain. The logic (as far as I can tell) is that the .h describes the public interface that other objects get to see, and you could theoretically let the world see these .h files without giving away your trade secrets, which are kept safely hidden in the .m files. Maybe this makes sense to people who are in the business of writing third-party libraries or open source developers, but I don’t care about all that; I simply want to have one god-damned file for the lot, but it seems it’s a very bad idea to try to do this anyway. Having to switch between these two all the time is just a major pain in the you-know-what!

     

  4. As someone how was brought up with Windows 95 to Windows XP then various Linux distributions for the roughly five years to December 2012, I’ve come to consider certain keys on my keyboard as being “normal”. For example, pressing the Home button jumps the cursor to be beginning of the line. Not so on a Mac, it goes to the beginning of the entire document! How many times do you think somebody might want to start typing at the beginning of the document? No much, hey! Anyway, XCode does let you map the Home key to move to the beginning of the line (unlike the rest of Mac OS X, unfortunately), however it does exactly what it says, moves to the beginning of the entire line, and not to the first actual character of code after the white space used to indent your code properly. This is just another one of those things that makes me wonder whether anybody at Apple actually uses XCode, and that perhaps they’ve got some secret in-house IDE they keep to themselves because when I press the Home key, I expect it to go to the beginning of the “if” statement or whatever it is. I’m sure any other normal developer who might read this would expect the same behaviour, also. Thankfully, I found the XCode4_beginning_of_line plugin on github that corrects this shocking oversight on Apple’s part.

     

  5. Just tonight I tried to debug some code (for the first time), and after remapping the “step over” key from F6 to F10 (I’m so used to the Visual Studio key that I cannot change this old habit!), I discovered that stepping over code doesn’t always mean step over in XCode. It quite often means “step into a massive page of assembly code”, which, I’m sure you might agree, isn’t particularly useful, especially if you’re like me and don’t know squat about assembly! Here’s a picture showing what I’m talking about, and no, I’m not using a release configuration. There’s also a Show Disassembly When Debugging option which I do not have ticked, either. Encountering this major annoyance is what prompted me to write this blog posting, so perhaps I’ll find the answer tomorrow, but for now, I’ve tried the obvious things and got nowhere. If this is Apple’s idea of “stepping over” whilst debugging, then perhaps I should just go back to Linux. I wonder if Ubuntu is usable again? Have they junked Unity and is GNOME 3 not stupid anymore?

     

  6. What made me give up and walk away from the computer yesterday was discovering that concatenating strings in Objective-C isn’t as simple as doing this:
  7. NSString *string = @”hello ” + @”world”;

    The correct way is this:

    NSString *string = [@”hello” stringByAppendingString:@”world”];

    Which brings me to another thing, Objective-C’s “message expressions”. I sure do miss being able to type object.method()! Having to type an at-symbol before every Objective-C string is very annoying, but without it, I’m using C strings, which Objective-C doesn’t like. I’m sure Apple could do something here to deprecate this unfortunate requirement.

     

  8. Given that XCode has really rubbed me the wrong way these past couple of days, I fell like being petty now :-) In .NET if you want to add a .ToMyString() method to the String class for use on any string, you add what’s called an extension method. Sounds logical, you’re adding a method to a system class, effectively “extending” the functionality of .NET itself. Now in Objective-C, an extension method is called a “category“. Beats me why they chose this name because it’s utterly illogical. Category of what? Anyway, “class extension” might be a logical name, but apparently such beasts were added in Objective-C 2.0 and are simply a way to allow a class to have private methods as far as I can tell right now (strange that a language would have no “private” method support until only recently). Objective-C is basically plain old C with Smalltalk-style object messaging syntax. Since then it has had various things done to it, such as Automatic Reference Counting and other afterthoughts. It’s now at a point where I seriously think Apple could do well to invest in a complete overhaul of the language and give it the ability to use another syntax scheme, much like .NET has c# and VB. I know I’m just dreaming, and that Apple would probably only make any such syntax bizarre in their own special way, so I suppose I’m just going to have to learn to live with Objective-C as it is, and embrace the joys that self-whipping can offer.

     

I suppose there’s always Xamarin.Mac, but I so wanted to really give Objective-C and XCode a try, but Apple are not making it easy for anybody with exposure to what I regard as “normal” development experiences, such as Java, C#, Perl, PHP, JavaScript, etc, and “normal” IDEs. I knew very well that Apple had their own special way of doing just about everything, and so far, since switching to Mac in December 2012, I’ve managed to cope well enough. It’s a very reliable platform, but it seems that if you want to do more than be just a passive consumer and internet surfer, you’re in for a bumpy ride. If I had only ever known the Apple way of doing everything, I’m sure I’d be right as rain, but having come from a different background, the transition for a developer is extremely unpleasant indeed.

They say that moving house and changing jobs are two of life’s most stressful events. I suppose switching from PC to Mac is another one, especially if you’re a developer! So far I’m determined not to be beaten, but I seriously needed to get all this off my chest. Only by venting will I be able to get past it and force myself into another whipping session tomorrow. Wish me luck!