Tag Archives: .net4

Handling nullables efficiently

I earlier wrote about Handling null checks efficiently by using extension methods to make our code more terse, not cluttered by null check blocks. When we use nullables (Nullable<T>), we come across a similar construction in our code. We have to check if the nullable has a value before accessing the value. If we try to reference the value of a nullable, and it has no value, we get an InvalidOperationException. This is quite similar to getting an NullReferenceException if trying to access a reference which is null.

Let’s take the example code from my previous post, and add an enum for Nationality. Then, we add a Citizenship property with type Nullable<Nationality> to the Person class. Like so:

enum Nationality
{
    No,Se,Dk,Uk,Us
}
internal class Person
{
    public string Name { get; set; }
    public Address Address { get; set; }
    public Nationality? Citizenship { get; set; }
}

If we then create a Person object that has the Citizenship property not set, we get an exception if we try to dereference it:

var person = new Person {Name = "Jackie Chiles"};
Console.Write("Citizenship:");
Console.Write(person.Citizenship.Value);

Handling nullables efficiently

What we can do here, is that we can create an .IfHasValue and .DoIfHasValue extension methods that are analogous to the .IfNotNull and .DoIfNotNull extension methods in the previous blog post:

public static class FlowControlExtensions
{
    [DebuggerStepThrough]
    public static void DoIfHasValue<T>(this T? obj, 
        Action<T> action, bool doContinue = true) where T : struct
    {
        if (obj.HasValue)
        {
            action(obj.Value);
        }
        if (doContinue)
            return;
        ThrowInvalidOperationException<T, T>();
    }
    [DebuggerStepThrough]
    public static TResult IfHasValue<T, TResult>(this T? obj, 
        Func<T, TResult> func, bool doContinue = true, 
        TResult defaultValue = default(TResult)) where T : struct
    {
        if (obj.HasValue)
        {
            return func(obj.Value);
        }
        return doContinue ? defaultValue : 
            ThrowInvalidOperationException<T, TResult>();
    }
    [DebuggerStepThrough]
    private static TResult ThrowInvalidOperationException<T, TResult>()
    {
        throw new InvalidOperationException(string.Format(
            "Tried to access value of nullable of {0}, but it had no value",
                typeof(T).FullName));
    }
}

Now we can use this to prevent our code from throwing an exception, and return a default value instead:

 var person = new Person {Name = "Jackie Chiles" };
 Console.Write("Citizenship:");
 Console.Write(person.Citizenship.IfHasValue(c => c.ToString()));

If we wish to give it another default value, we can simply do this like so:

Console.Write(person.Citizenship
    .IfHasValue(c => c.ToString(), defaultValue: "(unknown)"));

You can find the code on GitHub

Running chocolatey behind an authenticating firewall

I long grappled with a problem installing applications using chocolatey. Specifically, all installations that required downloading an MSI (or similar) file outside the .nupkg caused the following error message:

The remote server returned an error: (407) Proxy Authentication Required.

Yes, I am behind a firewall that requires authentication. I found several references to this error message on the chocolatey forums, but they all seemed to be fixed in the latest chocolatey version.

Through some googling I was able to track down the problem. Acutally, it is a problem with the .NET 3.5 runtime that causes the System.Net.WebClient to give up on an NTLM authentication challenge from proxies. Chocolatey uses Powershell, and indeed the System.Net.WebClient to download installation packages (all though not the package manifest itself, where it uses NuGet). As you my or may not know, Powershell uses the .NET 3.5 runtime per default.

Hence, the fix was to make Powershell use the .NET 4.0 runtime, where this bug is fixed. I figured out how to do this based on this entry on stackoverflow.

I then wrote this little Powershell snippet which changes Powershell on my machine to use .NET 4.0 instead of .NET 3.5:

if ([Environment]::Version.Major -lt 4) {
	$configFile = Join-Path $PSHOME -ChildPath '.powershell.exe.config'
	if (-not(Test-Path $configFile)) {
		@'
<?xml version="1.0"?>
<configuration>
  <startup useLegacyV2RuntimeActivationPolicy="true">
    <supportedRuntime version="v4.0.30319" />
    <supportedRuntime version="v2.0.50727" />
  </startup>
</configuration>
'@ | Out-File -FilePath $configFile -Encoding UTF8
		"Created $configFile"
	}
	'Restart powershell in order to make it run in .NET 4'
}

Adding WCF REST services to existing ASP.NET web application

If you want to create a new WCF services application with REST support, the WCF REST Templates are brilliant. However, if you have an existing ASP.NET application from which you want to expose REST services, there are a few manual steps you need to take to get it up and running:

Add assembly references

Add references to the following assemblies in your existing web project:

  • System.ServiceModel
  • System.ServiceModel.Activation
  • System.ServiceModel.Web

Create service class

Create a new service class where you will implement the service:

[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class LetterService
{
    [WebGet(UriTemplate = "")]
    public List<string> GetList()
    {
        return new List<string>{"a", "b", "c"};
    }
}

Register service route

In Global.asax.cs, define a route to the service:

void Application_Start(object sender, EventArgs e)
{
    RouteTable.Routes.Add(new ServiceRoute("letter", new WebServiceHostFactory(), typeof(LetterService)));
}

Enable ASP.NET compatability

Add the following to web.config:

<configuration>
   <system.serviceModel>
      <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
   </system.serviceModel>
</configuration>

…and you are good to go! The service will be available on http://<server>/letter

Optional: enable help

In order to get a nice help page for clients connecting to the service, add the following under the system.serviceModel element in web.config:

<standardEndpoints>
   <webHttpEndpoint>
      <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true" />
   </webHttpEndpoint>
</standardEndpoints>

Then, help will be available on http://<server>/letter/help