NAV 2009 R2 .Net Interop: Using Enumerations (Part 1)

At the moment, i'm writing an article on how to use .Net Interop to connect to other database. When doing this, I noticed that it wasn't that easy to use enumerations, which are in fact quite common in .Net. That's why i'm first going to elaborate on enumerations .. and then I will blog about the database connections.. :-).

What are enumerations?

The idea is that instead of using an int to represent a set of values, a type with a restricted set of values is used instead. In other words: you use words instead of numbers :-). Simple programming .. I like that Smile.

For example "colors". Suppose you have a program, that uses certain colors, which you want to define. In C#, you can create your enum like this:

enum Color {White, Red, Blue, Green, Black};

I'm not going into details about all the different options to define enums .. but basically, it defines (in this case) "White" as integer 0, "Red" as 1 and so on.. . In code, it gives you the opportunity that you don't have to use an integer like this:

class Shape
{
 
public void Fill(Color mycolor) {
   
switch(mycolor) {
     
case 1:
       
...
       
break;
     
case 2:
       
...
       
break;
     
case 3:
       
...
       
break;
     
default:
       
break; 
   

  }
}

But you can actually use the enum like this:

class Shape
{
 
public void Fill(Color mycolor) {
   
switch(mycolor) {
      case Color.Red
       
... 
       
break;
     
case Color.Blue:
       
...
       
break;
     
case Color.Green:
       
...
       
break;
     
default:
       
break; 
    
}
 
}
}

That makes more sense, right?

The .Net Framework is full of enumerations .. which you would be able to use. However, in C/AL, it's not all THAT easy. There is a little bit more code involved. At least, I think so .. may be there is a smarter way to do this, but i don't think so. Not because I think I'm right Wink, but more so for the reason that Microsoft has written their own article about it on MSDN here. Why am I writing another article about it? Two reasons: I didn't realize until Jeff Landeen pointed me to that article (thanks Jeff :-)), plus the article just didn't do it for me.. .

How to use enumerations in C/AL

The MSDN article explains a custom enum in a custom .Net assembly. In my opinion .. The truth is out there .. so why not use what's out there? Let's take an example of something that's already there in the framework. In fact, let's go back to my first article I wrote about .Net Interop: "NAV 2009 R2 .Net Interop: Calling a Web Service". In that article, I wrote this code to connect to a web service:

navBinding := navBinding.BasicHttpBinding;

// Set security mode to BasicHttpSecurityMode.TransportCredentialOnly
navBinding.Security.Mode := 4;
address :=
'http://localhost:7047/DynamicsNAV/WS/Second Company/Page/Customers';

// Set client credential type to HttpClientCredentialType.Windows
navBinding.Security.Transport.ClientCredentialType := 4;
CustomerService := CustomerService.Customers_PortClient(navBinding, endpointAddress.EndpointAddress(address));

// Set impersonation level to System.Security.Principal.TokenImpersonationLevel.Delegation
CustomerService.ClientCredentials.Windows.AllowedImpersonationLevel := 4;

// Include the sales order ID to be read.
Customer := CustomerService.Read('10000');

MESSAGE(Customer.Name);

The lines in yellow, are the lines where I expect to be able to use an enumerator that is already out there. Why? Because the integers that are given, just doesn't mean bleep to me.. . Let's take the first one:

navBinding.Security.Mode := 4;

The navBinding-variable is a "System.ServiceModel.BasicHttpBinding", so what I do, is I google "msdn System.ServiceModel.BasicHttpBinding security.mode enum", because I search the enum-description of security.mode of the basicHttpBinding on msdn .. . The enumeration-one is the one I want.. . On the MSDN page, you get the list of options:

None

The SOAP message is not secured during transfer. This is the default behavior.

Transport

Security is provided using HTTPS. The service must be configured with SSL certificates. The SOAP message is protected as a whole using HTTPS. The service is authenticated by the client using the service's SSL certificate. The client authentication is controlled through the ClientCredentialType.

Message

Security is provided using SOAP message security. For the BasicHttpBinding, the system requires that the server certificate be provided to the client separately. The valid client credential types for this binding are UserName and Certificate.

TransportWithMessageCredential

Integrity, confidentiality and server authentication are provided by HTTPS. The service must be configured with a certificate. Client authentication is provided by means of SOAP message security. This mode is applicable when the user is authenticating with a UserName or Certificate credential and there is an existing HTTPS deployment for securing message transfer.

TransportCredentialOnly

This mode does not provide message integrity and confidentiality. It provides only HTTP-based client authentication. Use this mode with caution. It should be used in environments where the transfer security is being provided by other means (such as IPSec) and only client authentication is provided by the infrastructure.

In this case, I would have wanted to write something like:

navBinding.Security.Mode := navBinding.Security.Mode.TransportCredentialOnly;

But this is not possible, i'm afraid.. . It's c#-like, but it's just not possible in C/AL. In fact, the one that comes closest (and you can derive that from the MSDN article about C/AL and Enums) is this:

navBinding.Security.Mode := navBinding.Security.Mode.Parse(navBinding.Security.Mode.GetType(), 'TransportCredentialOnly');

I understand that this isn't really "readable", but you must admit: having the "TransportCredentialOnly" there in your statement, makes it more useful than having the corresponding integer "4", no?

Make it some more readable: attempt 1

Let's try to make it a little bit easier to read. Instead of reusing your entire statement "navBinding.Security.Mode", you could be adding one more variable of you enumerator. In this case, let's add a variable to the enumeration itself:

Name

DataType

Subtype

enumBasicHttpSecurityMode

DotNet

'System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.ServiceModel.BasicHttpSecurityMode

And use that in our code, by first instantiating it, and afterwards, using it.. .

enumBasicHttpSecurityMode := navBinding.Security.Mode;

navBinding.Security.Mode := enumBasicHttpSecurityMode.Parse(enumBasicHttpSecurityMode.GetType(), 'TransportCredentialOnly');

This case, you don't have an.endles.series.of.points.as.one.statement .. but you can use a variable .. . I agree, this still isn't as nice as we want it to be .. .

Make it some more readable: attempt 2

Because of the fact we're using a neat trick here (using someone's parent to get to the daughter..Smile) I will write a separate blogpost about it.

Stay tuned!

Comment List
Related
Recommended