Sunday, August 7, 2016

Handling Whitespace

In this post I want to offer some tips for a very simply issue, but one that can cause you a lot of headaches if you don’t deal with it.

Let’s say we are validating user input and we need to be sure the user has entered something in a specific field. This data may be coming from a form, or XML file, etc., so for demonstration purposes I will just use string.

  string s1 = "";
  string s2 = null;
  string s3 = " ";
  string s4 = "\t";

  if (s1 == "") Console.WriteLine("s1 not entered");
  if (s2 == "") Console.WriteLine("s2 not entered");
  if (s3 == "") Console.WriteLine("s3 not entered");
  if (s4 == "") Console.WriteLine("s4 not entered");

If I am checking for user input in a field I would want all four of these to be considered invalid, but if I run the program, only the first one will be found, the other three will look ok. This happens because we are comparing against a literal empty string which is not the same as a null, a space, or a tab.

 
  if (string.IsNullOrEmpty(s1)) Console.WriteLine("s1 not entered");
  if (string.IsNullOrEmpty(s2)) Console.WriteLine("s2 not entered");
  if (string.IsNullOrEmpty(s3)) Console.WriteLine("s3 not entered");
  if (string.IsNullOrEmpty(s4)) Console.WriteLine("s4 not entered");

The string class provides a function call IsNullOrEmpty that can help with the second case. This function will return true if the the string is empty or it’s a null. This is very useful when you are about to call a function on a string, for example SubString(), because this would throw an exception if the string is null. This is a step in the right direction, but it still doesn’t help with the last two cases since a string with a space or tab aren’t considered empty.  Let’s look at another function on the string class:

 
if (string.IsNullOrWhiteSpace(s1)) Console.WriteLine("s1 not entered");
if (string.IsNullOrWhiteSpace(s2)) Console.WriteLine("s2 not entered");
if (string.IsNullOrWhiteSpace(s3)) Console.WriteLine("s3 not entered");
if (string.IsNullOrWhiteSpace(s4)) Console.WriteLine("s4 not entered");

If you run this code it will recognize all four strings as invalid. IsNullOrWhiteSpace works similar to IsNullOrEmpty but it also looks for any combination of white space, spaces, tabs, carriage returns, etc.

It’s a good idea to avoid comparing a string to and empty string, and better to use one of these functions instead.

Even when you are not just looking for whitespace or not it can give you trouble. Let’s look at this example:

  
string s1 = "";
string s1 = "OK";
string s2 = " OK ";
string s3 = "\tOK\t";

if (s1 == "OK") Console.WriteLine("s1 is OK");
if (s2 == "OK") Console.WriteLine("s2 is OK");
if (s3 == "OK") Console.WriteLine("s3 is OK");

If you run this, only the first case if found to be OK because the others two have whitespace before and after the string. We can solve this by using the Trim function:

  
if (!string.IsNullOrEmpty(s1) && s1.Trim() == "OK") Console.WriteLine("s1 not entered");
if (!string.IsNullOrEmpty(s2) && s2.Trim() == "OK") Console.WriteLine("s2 not entered");
if (!string.IsNullOrEmpty(s3) && s3.Trim() == "OK") Console.WriteLine("s3 not entered");

Since Trim is an instance method we need to first be sure s1 isn’t null so I use the IsNullOrEmpty function for this. Now that we know the string isn’t null we can call Trim() on it which removes any leading or trailing whitespace. Now all three of these will find OK.

Thursday, May 19, 2016

ASP.NET Core 1 - Blank Template Part 2

 

In my last post I walked through the code of the blank template that is created for an ASP.NET Core 1 RC1 application. In this post we will take a closer look at the how this application works.

First let’s run the application by clicking the IIS Express button in Visual Studio.

image

Your browser should open and display the message “Hello World!”. If you look in your system tray you will find IIS Express serving up WebApplication1 so you application is running on IIS. If you now go into your browser’s debugging tools (for example, press F12 in Internet Explorer), go to network monitor and refresh the page you will be able to view response header:

image

You can see that even though we are running on IIS, the web server is reported as Kestrel since that is the actual server we are running on, IIS is just serving as a reverse proxy passing the requests to Kestrel.

Next click the down arrow next to IIS Express:

image

In the list below IIS Express you will see all the commands that have been declared in the project.json file. In the blank template there is only one command “web”. Click on web to start the application using this command. This time instead of a web browser opening you will see a window like this:

image

In this case we are running directly on Kestrel instead of Kestrel running behind IIS. To view the output of the application use the URL that is being listened on shown in the window, in this case http://localhost:5000. You will not see IIS Express in the system tray and if you look at the network monitor it will still show the server as Kestrel.

Now let’s look at the IISPlatformHandler. This piece of middleware allows Windows Integrated Authentication and TLS Authentication to pass through to Kestrel. In Startup.cs change the line that displays “Hello World” to this:

await context.Response.WriteAsync("Hello " + context.User.Identity.Name);

Just like previous versions of ASP.NET you can use the User property of the HttpContext to get authentication information. To run your app in IISExpress using Windows Authentication go to the project properties, go to the Debug tab, make sure the IISExpress profile is selected and then uncheck Enable Anonymous Authentication, and check Enable Windows Authentication.

If you run this using IISExpress you will see your account name if you are on a Windows domain, or you will be prompted to enter your username and password and again the name will be displayed. In this scenario the IISPlatformHandler is handling the authentication and passing their information along to Kestrel in the context.

Now run the application use the web command. When you browse to the page this time you will just get “Hello”. In this scenario we are connecting directly to Kestrel and not going through IISExpress so the IISPlatformHandler doesn’t have an effect.

With the web page displayed try adding a file to the end of the URL, for example http://localhost:63694/test.html. When your browse to this URL the page will still return “Hello”. How about adding a path, http://localhost:63694/test/test.html. Again you will only get “Hello” as a response. As I mentioned in my introductory article ASP.NET Core 1 applications have no functionality by default, not even the ability to server files. Every URL we use just runs the same middleware to display the hello message. In the a future post I will show how to enable various pieces of stock middleware to enable these features.

I hope the demonstrations in this article give you a better idea of some of the differences between the new ASP.NET and previous versions.