Diving into OOP (Day 8): Indexers in C# (A Practical Approach)


Introduction

In my last article of this series we learnt about properties in c#. This article of the series “Diving into OOP” will explain all about indexers in C#, its uses and practical implementation. We’ll follow the same way of learning i.e. less theory and more practical. I’ll try to explain the concept in-depth.

Indexers in C# (The definition)

Indexers allow instances of a class or struct to be indexed just like arrays. Indexers resemble properties except that their accessors take parameters.”

Roadmap

Let’s recall our road map,

  1. Diving in OOP (Day 1): Polymorphism and Inheritance(Early Binding/Compile Time Polymorphism)
  2. Diving in OOP (Day 2): Polymorphism and Inheritance (Inheritance)
  3. Diving in OOP (Day 3): Polymorphism and Inheritance (Dynamic Binding/Run Time Polymorphism)
  4. Diving in OOP (Day 4): Polymorphism and Inheritance (All about Abstarct classes in C#)
  5. Diving in OOP (Day 5): All about access modifiers in C# (Public/Private/Protected/Internal/Sealed/Constants/Readonly Fields)
  6. Diving in OOP (Day 6): Understanding Enum in C# (A Practical Approach)
  7. Diving into OOP (Day 7): Properties in C# (A Practical Approach)
  8. Diving into OOP (Day 8): Indexers in C# (A Practical Approach)
  9. Diving into OOP (Day 9): Understanding Events in C# (An Insight)

 

Indexers (The explanation)

Like definition says, indexers allow us to leverage the capability of accessing the class objects as an array.
For better understanding, create a console application named Indexers and add a class to it named Indexer. We’ll use this class and project to learn Indexers. Make the class public, do not add any code for now and inProgram.cs add following code,

Lab 1

namespace Indexers
{
    class Program
    {
        static void Main(string[] args)
        {
            Indexer indexer=new Indexer();
            indexer[1] = 50;
        }
    }
}
Compile the code. We get,
Error Cannot apply indexing with [] to an expression of type ‘Indexers.Indexer’
I just created an object of Indexer class and tried to use that object as an array. Since actually it was not an array, it resulted as a compile time error.

Lab 2

Indexer.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Indexers
{
public class Indexer
{
public int this[int indexValue]
{
set
{
Console.WriteLine(I am in set : Value is “ + value + and indexValue is “ + indexValue);
Console.ReadLine();
}
}
}
}

Program.cs

namespace Indexers
{
    class Program
    {
        static void Main(string[] args)
        {
            Indexer indexer=new Indexer();
            indexer[1] = 50;
        }
    }
}

Output

Here we just made a use of indexer to index my object of the class Indexer. Now my object can be used as an array to access different object values.
Implementation of indexers is derived from a property known as “this”. It takes an integer parameter indexValue. Indexers are different from properties. In properties when we want to initialize or assign a value, the “set” accessor if defined automatically gets called. And the keyword “value” in “set” accessor was used to hold or keep track of the assigned value to our property. In above example, indexer[1] = 50;
calls the “set” accessor of “this” property i.e. an indexer therefore 50 becomes value and 1 becomes index of that value.

Lab 3

Indexer.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Indexers
{
public class Indexer
{
public int this[int indexValue]
{
set
{
Console.WriteLine(I am in set : Value is “ + value + and indexValue is “ + indexValue);
}
get
{
Console.WriteLine(I am in get and indexValue is “ + indexValue);
return 30;
}
}
}
}

Program.cs

using System;

namespace Indexers
{
class Program
{
static void Main(string[] args)
{
Indexer indexer=new Indexer();
Console.WriteLine(indexer[1]);
Console.ReadKey();
}
}
}

Output

In the above code snippet, I used get as well, to access the value of indexer. Properties and Indexers work on same set of rules. There is a bit difference on how we use them. When we do indexer[1] that means “get” accessor is called, and when we assign some value to indexer[1] that means “set” accessor is called. While implementing indexer code we have to take care that when we access indexer it is accessed in the form of a variable and that too an array parameter.

Data-Types in Indexers

Lab 1

Indexer.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Indexers
{
public class Indexer
{
public int Index;
public int this[string indexValue]
{
set
{
Console.WriteLine(I am in set : Value is “ + value + and indexValue is “ + indexValue);
Index = value;
}
get
{
Console.WriteLine(I am in get and indexValue is “ + indexValue);
return Index;
}
}
}
}

Program.cs

using System;

namespace Indexers
{
class Program
{
static void Main(string[] args)
{
Indexer indexer=new Indexer();
indexer[name”]=20;
Console.WriteLine(indexer[name”]);
Console.ReadKey();
}
}
}

Output

The “this” property i.e. indexers have return value. In our example the return value was integer. The square brackets along with “this” can also hold other data types and not only integer in the above mentioned example I tried to explain this using string parameter type for “this” : public int this[string indexValue],
The string parameter “indexValue” has a value “name”, like we passed in Main method of Program.cs. So one can have more than one indexers in a class deciding what should be the data type of the parameter value of array. An indexer, like properties follow same rules of inheritance and polymorphism.

Indexers in interfaces

Like Properties and Methods, Indexers can also be declared in Interfaces.
For practical implementation, just create an interface named IIndexers having following code,
namespace Indexers
{
    interface IIndexers
    {
        string this[int indexerValue] { get; set; }
    }
}
Here, an indexer is declared with an empty get and set accessor, that returns string values.
Now we need a class that implements this interface. You can define a class of your choice and implement that through IIndexers interface,

Indexer.cs

using System;

namespace Indexers
{
public class IndexerClass:IIndexers
{
readonly string[] _nameList = { AKhil”,Bob”,Shawn”,Sandra” };

public string this[int indexerValue]
{
get
{
return _nameList[indexerValue];
}
set
{
_nameList[indexerValue] = value;
}
}
}
}

The class has a default array of strings that hold names. Now we can implement interface defined indexer in this class to write our custom logic to fetch names on the base of indexerValue. Let’s call this in our main method,

Program.cs

using System;

namespace Indexers
{
class Program
{
static void Main(string[] args)
{
IIndexers iIndexer=new IndexerClass();
Console.WriteLine(iIndexer[0]);
Console.WriteLine(iIndexer[1]);
Console.WriteLine(iIndexer[2]);
Console.WriteLine(iIndexer[3]);
Console.ReadLine();

}
}
}

Run the application. Output,
In main method, we took Interface reference to create an object of IndexerClass, and we accessed that object array through indexer values like an array. It gives the names one by one.
Now if I want to access “set” accessor as well, I can easily do that. To check this, just add two more lines where you set the value in indexer,
            iIndexer[2] = "Akhil Mittal";
            Console.WriteLine(iIndexer[2]);
I set the value of 2nd element as a new name, let’s see the output,

Indexers in Abstract class

Like we used indexers in Interfaces, we can also use indexers in abstract class. I’ll use the same logic of source code that we used in interfaces, so that you can relate how it works in abstract class as well. Just define a new class that should be abstract and should contain an abstract indexer with empty get and set,

AbstractBaseClass

namespace Indexers
{
    public abstract class AbstractBaseClass
    {
        public abstract string this[int indexerValue] { get; set; }
    }
}
Define derived class, inheriting from abstract class,

IndexerClass

We here use override in indexer to override the abstract indexer declared in abstract class.
using System;

namespace Indexers
{
public class IndexerClass:AbstractBaseClass
{
readonly string[] _nameList = { AKhil”,Bob”,Shawn”,Sandra” };

public override string this[int indexerValue]
{
get
{
return _nameList[indexerValue];
}
set
{
_nameList[indexerValue] = value;
}
}
}
}

Program.cs

We’ll use reference of abstract class to create an object of Indexer class.
using System;

namespace Indexers
{
class Program
{
static void Main(string[] args)
{
AbstractBaseClass absIndexer=new IndexerClass();
Console.WriteLine(absIndexer[0]);
Console.WriteLine(absIndexer[1]);
Console.WriteLine(absIndexer[2]);
Console.WriteLine(absIndexer[3]);
absIndexer[2] = Akhil Mittal”;
Console.WriteLine(absIndexer[2]);

Console.ReadLine();

}
}
}

Output:
All of the above code is self-explanatory. You can explore more scenarios by yourself for more detailed understanding.

Indexer Overloading

Indexer.cs

using System;

namespace Indexers
{
public class Indexer
{
public int this[int indexerValue]
{
set
{
Console.WriteLine(Integer value “ + indexerValue + + value);
}
}

public int this[string indexerValue]
{
set
{
Console.WriteLine(String value “ + indexerValue + + value);
}
}

public int this[string indexerValue, int indexerintValue]
{
set
{
Console.WriteLine(String and integer value “ + indexerValue + + indexerintValue + + value);
}
}
}
}

Program.cs

using System;

namespace Indexers
{
class Program
{
static void Main(string[] args)
{
Indexer indexer=new Indexer();
indexer[1] = 30;
indexer[name”]=20;
indexer[address”,2] = 40;
Console.ReadLine();
}
}
}

Output

In above example, we see that an indexer’s signature in actually count of actual parameters and data types irresepective of the names of the arguments/parameters or return value of the indexers. This allows us to overload indexers like we do in method overloading. You can read more about method over loading inhttp://www.codeproject.com/Articles/771455/Diving-in-OOP-Day-Polymorphism-and-Inheritance-Ear. Here now we have overloaded indexers that takes integer, string integer and string combined as actual parameters. Like methods cannot be overloaded on the base of return types, so indexers follow the same methodology of overload like methods do.

Point to remember

Like indexers, we cannot overload properties. Properties are more like knowing by name and indexers on the other hand is more like knowing by signature.

Static Indexers?

In the example that we discussed in last section, just add a static keyword to the indexer signature,
      public static int this[int indexerValue]
        {
            set
            {
                Console.WriteLine("Integer value " + indexerValue + " " + value);
            }
        }
Compile the program; we get a compile time error,
Error The modifier ‘static’ is not valid for this item
The error clearly indicates that an indexer cannot be marked static. An indexer can only be a class instance member but not static, on the other hane a property can be static too.

Point to remember

Properties can be static but indexers cannot be.

Inheritance/Polymorphism in Indexers

Indexer.cs

using System;

namespace Indexers
{
public class IndexerBaseClass
{
public virtual int this[int indexerValue]
{
get
{
Console.WriteLine(Get of IndexerBaseClass; indexer value: “ + indexerValue);
return 100;
}
set
{
Console.WriteLine(Set of IndexerBaseClass; indexer value: “ + indexerValue + set value “ + value);
}

}
}
public class IndexerDerivedClass:IndexerBaseClass
{
public override int this[int indexerValue]
{
get
{
int dValue = base[indexerValue];
Console.WriteLine(Get of IndexerDerivedClass; indexer value: “ + indexerValue + dValue from base class indexer: “ + dValue);
return 500;
}
set
{
Console.WriteLine(Set of IndexerDerivedClass; indexer value: “ + indexerValue + set value “ + value);
base[indexerValue] = value;
}

}
}
}

Program.cs

using System;

namespace Indexers
{
class Program
{
static void Main(string[] args)
{
IndexerDerivedClass indexDerived=new IndexerDerivedClass();
indexDerived[2] = 300;
Console.WriteLine(indexDerived[2]);
Console.ReadLine();

}
}
}

Output

The example code taken above explains run time polymorphism and inheritance in indexers. I created a base class named IndexerBaseClass having an indexer with its own get and set like we discussed in prior examples. There after a derived class is created named IndexerDerivedClass, this derives from IndexerBaseClass and overrides “this” indexer from base class, note that base class indexer is marked virtual, so we can override it in derived class by marking it “override” in derived class.The example makes call to indexer of base class. Sometimes when we need to override code in derived class in the derived class, we may require the base class indexer should be called first. This is just a situation. The same rule of run time polymorphism applies here , we declare base class indexer and virtual and derived class one as override. In “set” accessor of derived class, we can call base class indexer as base[indexerValue]. Also this value is used to initialize the derived class indexer as well. So the value is stored in “value” keyword too. So, indexDerived[2] in Main() method of Program.cs gets replaced to base[2] in “set” accessor. Whereas In “get” accessor it is vice versa, we require to putbase[indexerValue] to right hand side of equal sign. The “get” accessor in base class returns a value, i.e. 100, which we get in dValue variable.

.NET Framework and Indexers

Indexers play a crucial role in .NET framework. Indexers are widely used in .NET Framework inbuilt classes, libraries such as collections and enumerable. Indexers are used in collections that are searchable like Dictionary, Hashtable, List, Arraylist etc.

Point to remember

Dictionary in C# largely uses indexers to have a staring parameter as an indexer argument.
Classes like ArrayList and List use indexers internally to provide functionality of arrays for fetching and using the elements.

Properties vs Indexers

I have already explained a lot about properties and indexers, to summarize, let me point to an MSDN link for better understanding,
Property Indexer
Allows methods to be called as if they were public data members. Allows elements of an internal collection of an object to be accessed by using array notation on the object itself.
Accessed through a simple name. Accessed through an index.
Can be a static or an instance member. Must be an instance member.
get accessor of a property has no parameters. A get accessor of an indexer has the same formal parameter list as the indexer.
set accessor of a property contains the implicit value parameter. A set accessor of an indexer has the same formal parameter list as the indexer, and also to the value parameter.
Supports shortened syntax with Auto-Implemented Properties (C# Programming Guide). Does not support shortened syntax.

Conclusion

With this article we completed almost all the scenarios related to an indexer. We did a lot of hands-on lab to clear our concepts. I hope my readers now know by heart about these basic concepts and will never forget them. These may also help you in cracking C# interviews.
Keep coding and enjoy reading
Also do not forget to rate/comment/like my article if it helped you by any means, this helps me to get motivated and encourages me to write more and more.

Read more:

Other Series

My other series of articles:

For more informative articles visit my Blog.

For more technical articles you can reach out to CodeTeddy.
Advertisements

Diving into OOP (Day 7): Properties in C# (A Practical Approach)


Introduction:

My article of the series “Diving into OOP” will explain all about properties, its uses and indexers in C#. We’ll follow the same way of learning i.e. less theory and more practical. I’ll try to explain the concept in-depth.

Properties (The definition):

Let’s start with the definition taken from MSDN
A property is a member that provides a flexible mechanism to read, write, or compute the value of a private field. Properties can be used as if they are public data members, but they are actually special methods called accessors. This enables data to be accessed easily and still helps promote the safety and flexibility of methods.
 

Roadmap:

Let’s recall our road map,
  1. Diving in OOP (Day 1): Polymorphism and Inheritance(Early Binding/Compile Time Polymorphism)
  2. Diving in OOP (Day 2): Polymorphism and Inheritance (Inheritance)
  3. Diving in OOP (Day 3): Polymorphism and Inheritance (Dynamic Binding/Run Time Polymorphism)
  4. Diving in OOP (Day 4): Polymorphism and Inheritance (All about Abstarct classes in C#)
  5. Diving in OOP (Day 5): All about access modifiers in C# (Public/Private/Protected/Internal/Sealed/Constants/Readonly Fields)
  6. Diving in OOP (Day 6): Understanding Enum in C# (A Practical Approach)
  7. Diving into OOP (Day 7): Properties in C# (A Practical Approach)
  8. Diving into OOP (Day 8): Indexers in C# (A Practical Approach)
  9. Diving into OOP (Day 9): Understanding Events in C# (An Insight)

Properties (The explanation):

Being a C# programmer, I must say that properties are something a C# programmer is blessed to use in his code. If we analyze properties internals, they are very different from normal variables; properties are internally methods that do not have their own memory like variables have. We can leverage property to write our custom code whenever we access a property. We can access the code when we call/execute properties or at the time of declaration too, but this is not possible with variables. A property in easy language is a class member and is encapsulated and abstracted from the end developer who is accessing the property. A property can contain lots of code that an end user does not know. An end user only cares to use that property like a variable.
Let’s start with some coding now.
Note: Each and every code snippet in this article is tried and tested.

Lab1

Create a simple console application and name it “Properties”. Add a class named “Properties” to it. You can choose the names of project and class as per your wish. Now try to create a property in that class like shown below,

Properties.cs

namespace Properties
{
    public class Properties
    {
        public string Name{}
    }
}
Try to run/build the application, what do we get?

Output

Error ‘Properties.Properties.Name’: property or indexer must have at least one accessor
In above example, we created a property named Name of type string. The error we got is very self-explanatory; it says a property must have an accessor, i.e. a get or a set. This means we need something in our property that gets accessed, whether to set the property value or get the property value, unlike variables, properties cannot be declared without an accessor.

Lab2

Let’s assign a get accessor to our property and try to access that property in Main method of program.cs file.

Properties.cs

Properties.cs:

namespace Properties
{
public class Properties
{
public string Name
{
get
{
return I am a Name property”;
}
}
}
}

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Properties
{
class Program
{
static void Main(string[] args)
{
Properties properties=new Properties();
Console.WriteLine(properties.Name);
Console.ReadLine();
}
}
}

Try to run/build the application, what do we get?

Output

It says “I am a Name property”. This signifies that our get successor got called when I tried to access the property or tried to fetch the value of a Property.

Get accessor

Now declare one more property in Properties.cs class, and name it Age that returns an integer. It calculates the age of a person by calculating the difference between his date of birth and current date,

Properties.cs

using System;

namespace Properties
{
public class Properties
{
public string Name
{
get
{
return I am a Name property”;
}
}

public int Age
{
get
{
DateTime dateOfBirth=new DateTime(1984,01,20);
DateTime currentDate = DateTime.Now;
int age = currentDate.Year – dateOfBirth.Year;
return age;
}
}
}
}

Call the “Age” property in the same way as done for Name.

Program.cs

using System;

namespace Properties
{
class Program
{
static void Main(string[] args)
{
Properties properties=new Properties();
Console.WriteLine(properties.Name);
Console.WriteLine(My age is “ + properties.Age);
Console.ReadLine();
}
}
}

Try to run/build the application, what do we get?

Output

It returns the correct age subjective to date of birth provided. Did you notince something here? Our property contains some code and logic to calculate age, but the caller i.e. Program.cs is not aware of the logic it only cares about using that Property. Therefore, we see that a property encapsulates and abstracts its functionality from the end user, in our case it’s a developer.

Point to remember

Get accessor is only used to read a property value. A property having only “get” cannot be set with any value from the caller.
This means a caller/end user can only access that property in read mode.

Set accessor

Let’s start with a simple example.

Lab1

Properties.cs

using System;
namespace Properties
{
    public class Properties
    {
        public string Name
        {
            get { return "I am a Name property"; }
        }

public int Age
{
get
{
DateTime dateOfBirth = new DateTime(1984, 01, 20);
DateTime currentDate = DateTime.Now;
int age = currentDate.Year – dateOfBirth.Year;
Console.WriteLine(Get Age called”);
return age;
}
set
{
Console.WriteLine(Set Age called “ + value);
}
}
}
}

Call the “Age” property in the same way as done for Name.

Program.cs

using System;

namespace Properties
{
class Program
{
static void Main(string[] args)
{
Properties properties=new Properties();
Console.WriteLine(properties.Name);
properties.Age = 40;
Console.WriteLine(My age is “ + properties.Age);
Console.ReadLine();
}
}
}

Run the application,

Output

In the above given example, I made few minor changes in get accessor, i.e. just printing that control is in “Get accessor” and introduced a “Set” in Age property too. Everything else remains same. Now when I call Name property, it works as was working earlier.Since we used “Set” so now we are allowed to set the value of a property. When I do properties.Age = 40; that means I am setting value 40 to that property. We can say a property can also be used to assign some value.In this case Set accessor is called, as soon as we set a value to property. Later on when we access that same property, again our get accessor gets called which returns value with some custom logic. We have a drawback here, as we see, whenever we call get we get the same vale and not the value that we assigned to that property i.e. because get has its custom fixed logic. Let’s try to overcome this situation.

Lab2

The example I am about to explain makes use of a private variable. But you can also use Automatic Properties to achieve same. I’ll purposely make use of variable to have a better understanding.

Properties.cs

using System;
namespace Properties
{
    public class Properties
    {
        private string name;
        private int age;

public string Name
{
get { return name; }
set
{
Console.WriteLine(Set Name called “);
name = value;
}
}

public int Age
{
get { return age; }
set
{
Console.WriteLine(Set Age called “);
age = value;
}
}
}
}

Program.cs

using System;

namespace Properties
{
class Program
{
static void Main(string[] args)
{
Properties properties=new Properties();
properties.Name = Akhil”;
Console.WriteLine(properties.Name);
properties.Age = 40;
Console.WriteLine(My age is “ + properties.Age);
Console.ReadLine();
}
}
}

Run the application,

Output

Now you see, we get the same value that we assigned to Name and Age property .When we access these properties get accessor is called and it returns the same vale as we set them for. Here properties internally make use of local variable to hold and sustain the value.
In day to day programming, we normally create a Public property that can be accessed outside the class. However the variable it is using internally could be a private.

Point to remember

The variable used for property should be of same data type as the data type of the property.
In our case we used variables, name and age, they share same datatype as their respective properties do. We don’t use variables as there might be scenarios in which we do not have control over those variables, end user can change them at any point of code without maintaining the change stack. Moreover one major use of properties is user can associate some logic or action when some change on the variable occurs, therefore when we use properties, we can easily track the value changes in variable.
When using Automatic Properties, they do this internally, i.e. we don’t have to define an extra variable to do so,like shown below,

Lab3

Properties.cs

using System;
namespace Properties
{
    public class Properties
    {
        private string name;
        private int age;

public string Name { get; set; }

public int Age { get; set; }
}
}

Program.cs

using System;

namespace Properties
{
class Program
{
static void Main(string[] args)
{
Properties properties=new Properties();
properties.Name = Akhil”;
Console.WriteLine(properties.Name);
properties.Age = 40;
Console.WriteLine(My age is “ + properties.Age);
Console.ReadLine();
}
}
}

Run the application,

Output

Here
    public string Name { get; set; }
    public int Age { get; set; }
are automatic properties.
I hope now you know how to define a property and use it.

Readonly

A property can be made read-only by only providing the get accessor. We do not provide a set accessor, if we do not want our property to be initialized or to be set from outside the scope of class.

Properties.cs

using System;
namespace Properties
{
    public class Properties
    {
        private string name="Akhil";
        private int age=32;

public string Name
{
get { return name; }
}

public int Age { get { return age; } }
}
}

Program.cs

using System;

namespace Properties
{
class Program
{
static void Main(string[] args)
{
Properties properties=new Properties();
properties.Name = Akhil”;
Console.WriteLine(properties.Name);
properties.Age = 40;
Console.WriteLine(My age is “ + properties.Age);
Console.ReadLine();
}
}
}

Build the application, we get following output
Error Property or indexer ‘Properties.Properties.Age‘ cannot be assigned to — it is read only
Error Property or indexer ‘Properties.Properties.Name‘ cannot be assigned to — it is read only
In main method of Program class, we tried to set the value of Age and Name property by,
            properties.Name = "Akhil";
            properties.Age = 40;
But since they were marked read-only i.e. only with get accessor, we encountered a compile time error.

Write-Only

A property can also be made write-only i.e. vice versa to read-only. In this case you’ll be only allowed to set the value of the property but can’t access it because we don’t have get accessor in it.

Properties.cs

using System;
namespace Properties
{
    public class Properties
    {
        private string name;
        private int age;

public string Name
{
set { name=value; }
}

public int Age { set { age = value; } }
}
}

Program.cs

using System;

namespace Properties
{
class Program
{
static void Main(string[] args)
{
Properties properties=new Properties();
properties.Name = Akhil”;
Console.WriteLine(properties.Name);
properties.Age = 40;
Console.WriteLine(My age is “ + properties.Age);
Console.ReadLine();
}
}
}

Build the application, we get following output
Error The property or indexer ‘Properties.Properties.Age’ cannot be used in this context because it lacks the get accessor
Error The property or indexer ‘Properties.Properties.Name’ cannot be used in this context because it lacks the get accessor
In the above mentioned example, our property is marked only with set accessor, but we tried to access those properties in our main program with,
            Console.WriteLine(properties.Name);
            Console.WriteLine("My age is " + properties.Age);
That means we tried to call get accessor of property which is not defined, so we again ended up in a compile time error.

Insight of Properties in C#

Lab1

Can we define properties as two different set of pieces? The answer is NO.

Properties.cs

using System;
namespace Properties
{
    public class Properties
    {
        private string name;

public string Name
{
set { name=value; }
}

public string Name
{
get { return name; }
}
}
}

Build the project, we get compile time error,
Error The type ‘Properties.Properties’ already contains a definition for ‘Name’
Here I tried to create a single property segregated in two different accessor. Compile treats a property name as a single separate property, so we cannot define a property with two names having different accessor.

Lab2

Can we define properties same as an already defined variable? The answer is NO.

Properties.cs

using System;
namespace Properties
{
    public class Properties
    {
        private string name;

public string name
{
set { name=value; }
get { return name; }
}
}
}

Build the project; we get compile time error,
Error The type ‘Properties.Properties’ already contains a definition for ‘name’
Again, we cannot have a variable and a property with the same name. They may differ on the grounds of case sensitivity, but they cannot share a same common name with the same case because at the time of accessing them, compiler may get confused that whether you are trying to access a property or a variable.

Properties vs Variables

It is a conception that variables are faster in execution that properties. I do not deny about this but this may not be true ion every case or can vary case to case. A property, like I explained internally executes a function/method whereas a variable uses/initializes memory when used. At times properties are not slower than variables as the property code is internally rewritten to memory access.
To summarize, MSDN explains this theory better than me,
Point of difference Variable Property
Declaration Single declaration statement Series of statements in a code block
Implementation Single storage location Executable code (property procedures)
Storage Directly associated with variable’s value Typically has internal storage not available outside the property’s containing class or moduleProperty’s value might or might not exist as a stored element 1
Executable code None Must have at least one procedure
Read and write access Read/write or read-only Read/write, read-only, or write-only
Custom actions (in addition to accepting or returning value) Not possible Can be performed as part of setting or retrieving property value

Static Properties

Like variables and methods, a property can also be marked static,

Properties.cs

using System;
namespace Properties
{
    public class Properties
    {
        public static int Age
        {
            set
            {
                Console.WriteLine("In set static property; value is " + value);
            }
            get
            {
                Console.WriteLine("In get static property");
                return 10;
            }
        }
    }
}

Program.cs

using System;

namespace Properties
{
class Program
{
static void Main(string[] args)
{
Properties.Age = 40;
Console.WriteLine(Properties.Age);
Console.ReadLine();
}
}
}

Output

In above example, I created a static Age property. When I tried to access it, you can see it is accessed via class name, like all static members are subjected to. So properties also inherit the static functionality like all c# members, no matter it is variable or a method. They’ll be accessed via class name only.

Properties return type

Lab1

Properties.cs

using System;

namespace Properties
{
public class Properties
{
public void AbsProperty
{
get
{
Console.WriteLine(Get called”);
}
}
}
}

Compile the program.
Output is a compile time error,
Error ‘AbsProperty’: property or indexer cannot have void type

Point to remember

A property cannot have a void return type.

Lab2

Just try to return a value from “set” accessor,

Properties.cs

using System;

namespace Properties
{
public class Properties
{
public int Age
{
set { return 5; }
}
}
}

Compile the program,
Error Since ‘Properties.Properties.Age.set’ returns void, a return keyword must not be followed by an object expression
Here compiler understands “set” accessor as a method that returns void and takes a parameter to initialize the value. So set cannot be expected to return a value.
If we just leave return statement empty, and remove 5, we do not get any error and code compiles,
using System;

namespace Properties
{
public class Properties
{
public int Age
{
set { return ; }
}
}
}

Value Keyword

We have a reserved keyword named value.
using System;

namespace Properties
{
public class Properties
{
public string Name
{
set { string value; }
}
}
}

Just compile the above given code, we get a compile time error as follows,
Error A local variable named ‘value’ cannot be declared in this scope because it would give a different meaning to ‘value’, which is already used in a ‘parent or current’ scope to denote something else
This signifies that “value” is a reserved keyword here. So one cannot declare a variable named value in “set” accessor as it may give different meaning to already reserved keyword value.

Abstract Properties

Lab1

Yes, we can also have abstract properties; let’s see how it works,

Properties.cs

using System;

namespace Properties
{
public abstract class BaseClass
{
public abstract int AbsProperty { get; set; }
}

public class Properties : BaseClass
{
public override int AbsProperty
{
get
{
Console.WriteLine(Get called”);
return 10;
}
set { Console.WriteLine(set called,value is “ + value); }
}
}
}

Program.cs

using System;

namespace Properties
{
class Program
{
static void Main(string[] args)
{
Properties prop=new Properties();
prop.AbsProperty = 40;
Console.WriteLine(prop.AbsProperty);
Console.ReadLine();
}
}
}

Output

In above example, I just created a base class named “BaseClass” and defined an abstract property namedAbsproperty. Since the property is abstract it follows the rules of being abstract as well. I inherited my “Properties” class from BaseClass and given the body to that abstract property. Since the property was abstract I have to override it in my derived class to add functionality to it. So I used override keyword in my derived class.
In base class, abstract property has no body at all, neither for “get” and nor for “set”, so we have to implement both the accessor in our derived class, like shown in “Properties” class.

Point to remember

If one do not mark property defined in derived class as override, it will by default be considered as new.

Lab2

Properties.cs

using System;

namespace Properties
{
public abstract class BaseClass
{
public abstract int AbsProperty { get; }
}

public class Properties : BaseClass
{
public override int AbsProperty
{
get
{
Console.WriteLine(Get called”);
return 10;
}
set { Console.WriteLine(set called,value is “ + value); }
}
}
}

Program.cs

using System;

namespace Properties
{
class Program
{
static void Main(string[] args)
{
Properties prop=new Properties();
prop.AbsProperty = 40;
Console.WriteLine(prop.AbsProperty);
Console.ReadLine();
}
}
}

Output

Compile time error,
Error ‘Properties.Properties.AbsProperty.set’: cannot override because ‘Properties.BaseClass.AbsProperty’ does not have an overridable set accessor
In above lab example, I just removed “set” from AbsProperty in Base class. All the code remains same. Now here we are trying to override the set accessor too in derived class, that is missing in base class, therefore compiler will not allow you to override a successor that is not declared in base class, hence resulted into a compile time error.

Point to remember

You cannot override an accessor that is not defined in a base class abstract property.

Properties in Inheritance

Just follow the given code,

Properties.cs

using System;

namespace Properties
{
public class PropertiesBaseClass
{
public int Age
{
set {}
}
}

public class PropertiesDerivedClass:PropertiesBaseClass
{
public int Age
{
get { return 32; }
}
}
}

Program.cs

namespace Properties
{
    class Program
    {
        static void Main(string[] args)
        {
            PropertiesBaseClass pBaseClass=new PropertiesBaseClass();
            pBaseClass.Age = 10;
            PropertiesDerivedClass pDerivedClass=new PropertiesDerivedClass();
            ((PropertiesBaseClass) pDerivedClass).Age = 15;
            pDerivedClass.Age = 10;
        }
    }
}
As you can see in above given code, in Properties.cs file I created two classes one is Base i.e.PropertiesBaseClass and second in Derived i.e. PropertiesDerivedClass. I purposely declared set accessor in Base class and get in Derived class for the same property name i.e. Age. Now this case may give you the feeling that when compiled, our code of property Age will become one, i.e. it will take set from Base class and get from derived class and combine it into a single entity of Age property.But this is practically not the case. The compiler treats both these properties differently, and does not consider them to be same. In this case the property in derived class actually hides the property in base class , they are not the same but independent properties.The same concept of method hiding applies here too. You can read about hiding inhttp://www.codeproject.com/Articles/774578/Diving-in-OOP-Day-Polymorphism-and-Inheritance-Dyn.
To use the property of base class from a derived class object, you need to cast it to base class and then use it.
When you compile the above code, you get a compile time error as follows,
Error Property or indexer ‘Properties.PropertiesDerivedClass.Age’ cannot be assigned to — it is read only
i.e. we can do ((PropertiesBaseClass) pDerivedClass).Age = 15;
but we cannot do pDerivedClass.Age = 10; because derived class property has no “set” accessor.

Summary

Let’s recall all the points that we have to remember,
  • The variable used for property should be of same data type as the data type of the property.
  • A property cannot have a void return type.
  • If one do not mark property defined in derived class as override, it will by default be considered as new.
  • You cannot override an accessor that is not defined in a base class abstract property.
  • Get accessor is only used to read a property value. A property having only get cannot be set with any value from the caller.

Conclusion

In this article we learnt a lot about properties in c#. I hope you now understand properties well. In my next article I’ll explain all about indexers in C#.
Keep coding and enjoy reading
Also do not forget to rate/comment/like my article if it helped you by any means, this helps me to get motivated and encourages me to write more and more.

Read more:

Other Series

My other series of articles:

For more informative articles visit my Blog.

For more technical articles you can reach out to CodeTeddy.

RESTful Day #5: Security in Web APIs-Basic Authentication and Token based custom Authorization in Web APIs using Action Filters


Introduction

Security has always been a major concern we talk about enterprise level applications, especially when we talk about exposing our business through services. I have already explained a lot on WebAPI in my earlier articles of the series. I explained, how do we create a WebAPI, how to resolve dependencies to make it a loosely coupled design, defining custom routes, making use of attribute routing. My article will explain how we can achieve security in a WebAPI. This article will explain how to make WebAPI secure using Basic Authentication and Token based authorization. I’ll also explain how we can leverage token based authorization and Basic authentication in WebAPI to maintain sessions in WebAPI. There is no standard way of achieving security in WebAPI. We can design our own security technique and structure which suits best to our application.

Roadmap

Following is the roadmap I have setup to learn WebAPI step by step,

I’ll purposely use Visual Studio 2010 and .NET Framework 4.0 because there are few implementations that are very hard to find in .NET Framework 4.0, but I’ll make it easy by showing how we can do it.

Security in WebAPI

Security in itself is very complicated and tricky topic. I’ll try to explain how we can achieve it in WebAPI in my own way.
When we plan to create an enterprise level application, we especially want to take care of authentication and authorization. These are two techniques if used well makes our application secure, in our case makes our WebAPI more secure.

Authentication

Authentication is all about the identity of an end user. It’s about validating the identity of a user who is accessing our system, that he is authenticated enough to use our resources or not. Does that end user have valid credentials to log in our system? Credentials can be in the form of a user name and password. We’ll use Basic Authentication technique to understand how we can achieve authentication in WebAPI.

Authorization

Authorization should be considered as a second step after authentication to achieve security. Authorization means what all permissions the authenticated user has to access web resources. Is allowed to access/ perform action on that resource? This could be achieved by setting roles and permissions for an end user who is authenticated, or can be achieved through providing a secure token, using which an end user can have access to other services or resources.

Maintaining Session

RESTful services work on a stateless protocol i.e. HTTP. We can achieve maintaining session in Web API through token based authorization technique. An authenticated user will be allowed to access resources for a particular period of time, and can re-instantiate the request with an increased session time delta to access other resource or the same resource. Websites using WebAPIs as RESTful services may need to implement login/logout for a user, to maintain sessions for the user, to provide roles and permissions to their user, all these features could be achieved using basic authentication and token based authorization. I’ll explain this step by step.

Basic Authentication

Basic authentication is a mechanism, where an end user gets authenticated through our service i.e. RESTful service with the help of plain credentials such as user name and password. An end user makes a request to the service for authentication with user name and password embedded in request header. Service receives the request and checks if the credentials are valid or not, and returns the response accordingly, in case of invalid credentials, service responds with 401 error code i.e. unauthorized. The actual credentials through which comparison is don may lie in database , any config file like web.config or in the code itself.

Pros and Cons of Basic Authentication

Basic authentication has its own pros and cons. It is advantageous when it comes to implementation, it is very easy to implement, it is nearly supported by all modern browsers and has become an authentication standard in RESTful / Web APIs. It has disadvantages like sending user credentials in plain text, sending user credentials inside request header, i.e. prone to hack. One have to send credentials each time a service is called. No session is maintained and a user cannot logout once logged in through basic authentication. It is very prone to CSRF (Cross Site Request Forgery).

Token Based Authorization

Authorization part comes just after authentication, once authenticated a service can send a token to an end user through which user can access other resources. The token could be any encrypted key, which only server/service understands and when it fetches the token from the request made by end user, it validates the token and authorizes user into the system. Token generated could be stored in a database or an external file as well i.e. we need to persist the token for future references. Token can have its own lifetime, and may expire accordingly. In that case user will again have to be authenticated into the system.

WebAPI with Basic Authentication and Token Based Authorization

Creating User Service

Just open your WebAPI project or the WebAPI project that we discussed in the last part of learning WebAPI.
We have BusinessEntities, BusinessServices, DataModel, DependencyResolver and a WebApi project as well.
We already have a User table in database, or you can create your own database with a table like User Table as shown below,
I am using WebAPI database, scripts I have attached for download.

UserServices

Go to BusinessServices project and add a new interface IUserService and a service named UserServices implementing that interface,
Just define one method named Authenticate in the interface.
namespace BusinessServices
{
    public interface IUserServices
    {
        int Authenticate(string userName, string password);
    }
}
This method takes username and password as a parameter and returns particular userId if the user is authenticated successfully.
Just implement this method in UserServices.cs class, just like we created services earlier in the series,
using DataModel.UnitOfWork;

namespace BusinessServices
{
    /// <summary>
    /// Offers services for user specific operations
    /// </summary>
    public class UserServices : IUserServices
    {
        private readonly UnitOfWork _unitOfWork;

        /// <summary>
        /// Public constructor.
        /// </summary>
        public UserServices(UnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
        }

        /// <summary>
        /// Public method to authenticate user by user name and password.
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public int Authenticate(string userName, string password)
        {
            var user = _unitOfWork.UserRepository.Get(u => u.UserName == userName && u.Password == password);
            if (user != null && user.UserId > 0)
            {
                return user.UserId;
            }
            return 0;
        }
    }
}
You can clearly see that Authenticate method just checks user credentials from UserRepository and returns the values accordingly. The code is very much self-explanatory.

Resolve dependency of UserService

Just open DependencyResolver class in BusinessServices project itself and add its dependency type so that we get UserServices dependency resolved at run time,so add
registerComponent.RegisterType();
line to SetUP method. Our class becomes,
using System.ComponentModel.Composition;
using DataModel;
using DataModel.UnitOfWork;
using Resolver;

namespace BusinessServices
{
    [Export(typeof(IComponent))]
    public class DependencyResolver : IComponent
    {
        public void SetUp(IRegisterComponent registerComponent)
        {
            registerComponent.RegisterType();
            registerComponent.RegisterType();
        }
    }
}

Implementing Basic Authentication

Step 1: Create generic Authentication Filter

Add a folder named Filters to the WebAPI project and add a class named GenericAuthenticationFilter under that folder.
Derive that class from AuthorizationFilterAttribute, this is a class under System.Web.Http.Filters.
I have created the generic authentication filter will be like,
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
    public class GenericAuthenticationFilter : AuthorizationFilterAttribute
    {
      
        /// <summary>
        /// Public default Constructor
        /// </summary>
        public GenericAuthenticationFilter()
        {
        }

        private readonly bool _isActive = true;

        /// <summary>
        /// parameter isActive explicitly enables/disables this filetr.
        /// </summary>
        /// <param name="isActive"></param>
        public GenericAuthenticationFilter(bool isActive)
        {
            _isActive = isActive;
        }

        /// <summary>
        /// Checks basic authentication request
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnAuthorization(HttpActionContext filterContext)
        {
            if (!_isActive) return;
            var identity = FetchAuthHeader(filterContext);
            if (identity == null)
            {
                ChallengeAuthRequest(filterContext);
                return;
            }
            var genericPrincipal = new GenericPrincipal(identity, null);
            Thread.CurrentPrincipal = genericPrincipal;
            if (!OnAuthorizeUser(identity.Name, identity.Password, filterContext))
            {
                ChallengeAuthRequest(filterContext);
                return;
            }
            base.OnAuthorization(filterContext);
        }

        /// <summary>
        /// Virtual method.Can be overriden with the custom Authorization.
        /// </summary>
        /// <param name="user"></param>
        /// <param name="pass"></param>
        /// <param name="filterContext"></param>
        /// <returns></returns>
        protected virtual bool OnAuthorizeUser(string user, string pass, HttpActionContext filterContext)
        {
            if (string.IsNullOrEmpty(user) || string.IsNullOrEmpty(pass))
                return false;
            return true;
        }

        /// <summary>
        /// Checks for autrhorization header in the request and parses it, creates user credentials and returns as BasicAuthenticationIdentity
        /// </summary>
        /// <param name="filterContext"></param>
        protected virtual BasicAuthenticationIdentity FetchAuthHeader(HttpActionContext filterContext)
        {
            string authHeaderValue = null;
            var authRequest = filterContext.Request.Headers.Authorization;
            if (authRequest != null && !String.IsNullOrEmpty(authRequest.Scheme) && authRequest.Scheme == "Basic")
                authHeaderValue = authRequest.Parameter;
            if (string.IsNullOrEmpty(authHeaderValue))
                return null;
            authHeaderValue = Encoding.Default.GetString(Convert.FromBase64String(authHeaderValue));
            var credentials = authHeaderValue.Split(':');
            return credentials.Length < 2 ? null : new BasicAuthenticationIdentity(credentials[0], credentials[1]);
        }


        /// <summary>
        /// Send the Authentication Challenge request
        /// </summary>
        /// <param name="filterContext"></param>
        private static void ChallengeAuthRequest(HttpActionContext filterContext)
        {
            var dnsHost = filterContext.Request.RequestUri.DnsSafeHost;
            filterContext.Response = filterContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
            filterContext.Response.Headers.Add("WWW-Authenticate", string.Format("Basic realm=\"{0}\"", dnsHost));
        }
    }
Since this is an AuthorizationFilter derived class, we need to override its methods to add our custom logic. Here “OnAuthorization” method is overridden to add a custom logic. Whenever we get ActionContext onOnAuthorization, we’ll check for its header, since we are pushing our service to followBasicAuthentication, the request headers should contain this information. I have used FetchAuthHeader to check the scheme, if it comes to be “Basic” and thereafter store the credentials i.e. user name and password in a form of an object of class BasicAuthenticationIdentity, therefore creating an identity out of valid credentials.
        protected virtual BasicAuthenticationIdentity FetchAuthHeader(HttpActionContext filterContext)
        {
            string authHeaderValue = null;
            var authRequest = filterContext.Request.Headers.Authorization;
            if (authRequest != null && !String.IsNullOrEmpty(authRequest.Scheme) && authRequest.Scheme == "Basic")
                authHeaderValue = authRequest.Parameter;
            if (string.IsNullOrEmpty(authHeaderValue))
                return null;
            authHeaderValue = Encoding.Default.GetString(Convert.FromBase64String(authHeaderValue));
            var credentials = authHeaderValue.Split(':');
            return credentials.Length < 2 ? null : new BasicAuthenticationIdentity(credentials[0], credentials[1]);
        }
I am expecting values to be encrypted using Base64 string; You can use your own encryption mechanism as well.
Later on in OnAuthorization method we create a genericPrincipal with the created identity and assign it to current Thread principal,
            var genericPrincipal = new GenericPrincipal(identity, null);
            Thread.CurrentPrincipal = genericPrincipal;
            if (!OnAuthorizeUser(identity.Name, identity.Password, filterContext))
            {
                ChallengeAuthRequest(filterContext);
                return;
            }
            base.OnAuthorization(filterContext);
Once done, a challenge to that request is added, where we add response and tell the Basic realm,
filterContext.Response.Headers.Add("WWW-Authenticate", string.Format("Basic
realm=\"{0}\"", dnsHost));
in ChallengeAuthRequest method.
If no credentials is provided in the request, this generic authentication filter sets generic authentication principal to the current thread principal.
Since we know the drawback that in basic authentication credentials are passed in a plain text, so it would be good if our service uses SSL for communication or message passing.
We have an overridden constructor as well that allows to stop the default behavior of the filter by just passing in a parameter i.e. true or false.
  public GenericAuthenticationFilter(bool isActive)
        {
            _isActive = isActive;
        }
We can use OnAuthorizeUser for custom authorization purposes.

Step 2: Create Basic Authentication Identity

Before we proceed further, we also need the BasicIdentity class, that takes hold of credentials and assigns it to Generic Principal. So just add one more class named BasicAuthenticationIdentity deriving fromGenericIdentity.
This class contains three properties i.e. UserNamePassword and UserId. I purposely added UserId because we’ll need that in future. So our class will be like,
using System.Security.Principal;

namespace WebApi.Filters
{
    /// <summary>
    /// Basic Authentication identity
    /// </summary>
    public class BasicAuthenticationIdentity : GenericIdentity
    {
        /// <summary>
        /// Get/Set for password
        /// </summary>
        public string Password { get; set; }
        /// <summary>
        /// Get/Set for UserName
        /// </summary>
        public string UserName { get; set; }
        /// <summary>
        /// Get/Set for UserId
        /// </summary>
        public int UserId { get; set; }

        /// <summary>
        /// Basic Authentication Identity Constructor
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        public BasicAuthenticationIdentity(string userName, string password)
            : base(userName, "Basic")
        {
            Password = password;
            UserName = userName;
        }
    }
}

Step 3: Create a Custom Authentication Filter

Now you are ready to use your own Custom Authentication filter. Just add one more class under that Filters project and call it ApiAuthenticationFilter, this class will derive from GenericAuthenticationFilter, that we created in first step. This class overrider OnAuthorizeUser method to add custom logic for authenticating a request it makes use of UserService that we created earlier to check the user,
protected override bool OnAuthorizeUser(string username, string password, HttpActionContext actionContext)
        {
            var provider = actionContext.ControllerContext.Configuration
                               .DependencyResolver.GetService(typeof(IUserServices)) as IUserServices;
            if (provider != null)
            {
                var userId = provider.Authenticate(username, password);
                if (userId>0)
                {
                    var basicAuthenticationIdentity = Thread.CurrentPrincipal.Identity as BasicAuthenticationIdentity;
                    if (basicAuthenticationIdentity != null)
                        basicAuthenticationIdentity.UserId = userId;
                    return true;
                }
            }
            return false;
        }
Complete class
using System.Threading;
using System.Web.Http.Controllers;
using BusinessServices;

namespace WebApi.Filters
{
    /// <summary>
    /// Custom Authentication Filter Extending basic Authentication
    /// </summary>
    public class ApiAuthenticationFilter : GenericAuthenticationFilter
    {
        /// <summary>
        /// Default Authentication Constructor
        /// </summary>
        public ApiAuthenticationFilter()
        {
        }

        /// <summary>
        /// AuthenticationFilter constructor with isActive parameter
        /// </summary>
        /// <param name="isActive"></param>
        public ApiAuthenticationFilter(bool isActive)
            : base(isActive)
        {
        }

        /// <summary>
        /// Protected overriden method for authorizing user
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <param name="actionContext"></param>
        /// <returns></returns>
        protected override bool OnAuthorizeUser(string username, string password, HttpActionContext actionContext)
        {
            var provider = actionContext.ControllerContext.Configuration
                               .DependencyResolver.GetService(typeof(IUserServices)) as IUserServices;
            if (provider != null)
            {
                var userId = provider.Authenticate(username, password);
                if (userId>0)
                {
                    var basicAuthenticationIdentity = Thread.CurrentPrincipal.Identity as BasicAuthenticationIdentity;
                    if (basicAuthenticationIdentity != null)
                        basicAuthenticationIdentity.UserId = userId;
                    return true;
                }
            }
            return false;
        }
    }
}

Step 4: Basic Authentication on Controller

Since we already have our products controller,
   public class ProductController : ApiController
    {
        #region Private variable.

        private readonly IProductServices _productServices;

        #endregion

        #region Public Constructor

        /// <summary>
        /// Public constructor to initialize product service instance
        /// </summary>
        public ProductController(IProductServices productServices)
        {
            _productServices = productServices;
        }

        #endregion

        // GET api/product
        [GET("allproducts")]
        [GET("all")]
        public HttpResponseMessage Get()
        {
            var products = _productServices.GetAllProducts();
            var productEntities = products as List ?? products.ToList();
            if (productEntities.Any())
                return Request.CreateResponse(HttpStatusCode.OK, productEntities);
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Products not found");
        }

        // GET api/product/5
        [GET("productid/{id?}")]
        [GET("particularproduct/{id?}")]
        [GET("myproduct/{id:range(1, 3)}")]
        public HttpResponseMessage Get(int id)
        {
            var product = _productServices.GetProductById(id);
            if (product != null)
                return Request.CreateResponse(HttpStatusCode.OK, product);
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No product found for this id");
        }

        // POST api/product
        [POST("Create")]
        [POST("Register")]
        public int Post([FromBody] ProductEntity productEntity)
        {
            return _productServices.CreateProduct(productEntity);
        }

        // PUT api/product/5
        [PUT("Update/productid/{id}")]
        [PUT("Modify/productid/{id}")]
        public bool Put(int id, [FromBody] ProductEntity productEntity)
        {
            if (id > 0)
            {
                return _productServices.UpdateProduct(id, productEntity);
            }
            return false;
        }

        // DELETE api/product/5
        [DELETE("remove/productid/{id}")]
        [DELETE("clear/productid/{id}")]
        [PUT("delete/productid/{id}")]
        public bool Delete(int id)
        {
            if (id > 0)
                return _productServices.DeleteProduct(id);
            return false;
        }
    }
There are three ways in which you can use this authentication filter.
Just apply this filer to ProductController. You can add this filter at the top of the controller, for all API requests to be validated,
    [ApiAuthenticationFilter]
    [RoutePrefix("v1/Products/Product")]
    public class ProductController : ApiController
You can also globally add this in Web API configuration file , so that filter applies to all the controllers and all the actions associated to it,
GlobalConfiguration.Configuration.Filters.Add(new ApiAuthenticationFilter());
You can also apply it to Action level too by your wish to apply or not apply authentication to that action,
       // GET api/product
        [ApiAuthenticationFilter(true)]
        [GET("allproducts")]
        [GET("all")]
        public HttpResponseMessage Get()
        {
             …………………
        }
        // GET api/product/5
         [ApiAuthenticationFilter(false)]
        [GET("productid/{id?}")]
        [GET("particularproduct/{id?}")]
        [GET("myproduct/{id:range(1, 3)}")]
        public HttpResponseMessage Get(int id)
        {
             ……………………..
        }

Running the application

We have already implemented Basic Authentication, just try to run the application to test if it is working
Just run the application, we get,
We already have our test client added, but for new readers, just go to Manage Nuget Packages, by right clicking WebAPI project and type WebAPITestClient in searchbox in online packages,
You’ll get “A simple Test Client for ASP.NET Web API”, just add it. You’ll get a help controller in Areas-> HelpPage like shown below,
I have already provided the database scripts and data in my previous article, you can use the same.
Append “/help” in the application url, and you’ll get the test client,
GET:
POST:
PUT:
DELETE:
You can test each service by clicking on it. Once you click on the service link, you’ll be redirected to test the service page of that particular service. On that page there is a button Test API in the right bottom corner, just press that button to test your service,
Service for Get All products,
When you click on Send request, a popup will come asking Authentication required. Just cancel that popup and let request go without credentials. You’ll get a response of Unauthorized i.e. 401,
This means our authentication mechanism is working.
Just to double sure it, let’s send the request with credentials now. Just add a header too with the request. Header should be like ,
Authorization : Basic YWtoaWw6YWtoaWw=
Here “YWtoaWw6YWtoaWw=” is my Base64 encoded user name and password i.e. akhil:akhil
Click on Send and we get the response as desired,
Likewise you can test all the service endpoints.
This means our service is working with Basic Authentication.

Design discrepancy

This design when running on SSL is very good for implementing Basic Authentication. But there are few scenarios in which, along with Basic Authentication I would like to leverage authorization too and not even authorization but sessions too. When we talk about creating an enterprise application, it just does not limit to securing our endpoint with authentication only.
In this design, each time I’ll have to send user name and password with every request. Suppose I want to create such application, where authentication only occurs only once as my login is done and after successfully authenticated i.e. logging in I must be able to use other services of that application i.e. I am authorized now to use those services. Our application should be that robust that it restricts even authenticated user to use other services until he is not authorized. Yes I am talking about Token based authorization.
I’ll expose only one endpoint for authentication and that will be my login service .So client only knows about that login service that needs credentials to get logged in to system.
After client successfully logs in I’ll send a token that could be a GUID or an encrypted key by any xyz algorithm that I want when user makes request for any other services after login, should provide this token along with that request.
And to maintain sessions, our token will have an expiry too, that will last for 15 minutes, can be made configurable with the help of web.config file. After session is expired, user will be logged out, and will again have to use login service with credentials to get a new token. Seems exciting to me, let’s implement this Smile | :)

Implementing Token-based Authorization

To overcome above mentioned scenarios, let’s start developing and giving our application a shape of thick client enterprise architecture.

Set Database

Let’s start with setting up a database. When we see our already created database that we had set up in first part of the series, we have a token table. We require this token table for token persistence. Our token will persist in database with an expiry time. If you are using your own database, you can create token table as,

Set Business Services

Just navigate to BusinessServices and create one more Interface named ITokenServices for token based operations,
using BusinessEntities;

namespace BusinessServices
{
    public interface ITokenServices
    {
        #region Interface member methods.
        /// <summary>
        ///  Function to generate unique token with expiry against the provided userId.
        ///  Also add a record in database for generated token.
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        TokenEntity GenerateToken(int userId);

        /// <summary>
        /// Function to validate token againt expiry and existance in database.
        /// </summary>
        /// <param name="tokenId"></param>
        /// <returns></returns>
        bool ValidateToken(string tokenId);

        /// <summary>
        /// Method to kill the provided token id.
        /// </summary>
        /// <param name="tokenId"></param>
        bool Kill(string tokenId);

        /// <summary>
        /// Delete tokens for the specific deleted user
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        bool DeleteByUserId(int userId);
        #endregion
    }
}
We have four methods defined in this interface. Let’s create TokenServices class which implementsITokenServices and understand each method.
GenerateToken method takes userId as a parameter and generates a token, encapsulates that token in a token entity with Token expiry time and returns it to caller.
  public TokenEntity GenerateToken(int userId)
        {
            string token = Guid.NewGuid().ToString();
            DateTime issuedOn = DateTime.Now;
            DateTime expiredOn = DateTime.Now.AddSeconds(
                                              Convert.ToDouble(ConfigurationManager.AppSettings["AuthTokenExpiry"]));
            var tokendomain = new Token
                                  {
                                      UserId = userId,
                                      AuthToken = token,
                                      IssuedOn = issuedOn,
                                      ExpiresOn = expiredOn
                                  };

            _unitOfWork.TokenRepository.Insert(tokendomain);
            _unitOfWork.Save();
            var tokenModel = new TokenEntity()
                                 {
                                     UserId = userId,
                                     IssuedOn = issuedOn,
                                     ExpiresOn = expiredOn,
                                     AuthToken = token
                                 };

            return tokenModel;
        }
While generating token, it names a database entry into Token table.
ValidateToken method just validates that the token associated with the request is valid or not i.e. it exists in the database within its expiry time limit.
  public bool ValidateToken(string tokenId)
        {
            var token = _unitOfWork.TokenRepository.Get(t => t.AuthToken == tokenId && t.ExpiresOn > DateTime.Now);
            if (token != null && !(DateTime.Now > token.ExpiresOn))
            {
                token.ExpiresOn = token.ExpiresOn.AddSeconds(
                                              Convert.ToDouble(ConfigurationManager.AppSettings["AuthTokenExpiry"]));
                _unitOfWork.TokenRepository.Update(token);
                _unitOfWork.Save();
                return true;
            }
            return false;
        }
It just takes token Id supplied in the request.
Kill Token just kills the token i.e. removes the token from database.
  public bool Kill(string tokenId)
        {
            _unitOfWork.TokenRepository.Delete(x => x.AuthToken == tokenId);
            _unitOfWork.Save();
            var isNotDeleted = _unitOfWork.TokenRepository.GetMany(x => x.AuthToken == tokenId).Any();
            if (isNotDeleted) { return false; }
            return true;
        }
DeleteByUserId method deletes all token entries from the database w.r.t particular userId associated with those tokens.
public bool DeleteByUserId(int userId)
{
_unitOfWork.TokenRepository.Delete(x => x.UserId == userId);
_unitOfWork.Save();

var isNotDeleted = _unitOfWork.TokenRepository.GetMany(x => x.UserId == userId).Any();
return !isNotDeleted;
}
So with _unitOfWork and along with Constructor our class becomes,
using System;
using System.Configuration;
using System.Linq;
using BusinessEntities;
using DataModel;
using DataModel.UnitOfWork;

namespace BusinessServices
{
public class TokenServices:ITokenServices
{
#region Private member variables.
private readonly UnitOfWork _unitOfWork;
#endregion

#region Public constructor.
/// <summary>
/// Public constructor.
/// </summary>
public TokenServices(UnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
#endregion


#region Public member methods.

/// <summary>
///  Function to generate unique token with expiry against the provided userId.
///  Also add a record in database for generated token.
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public TokenEntity GenerateToken(int userId)
{
string token = Guid.NewGuid().ToString();
DateTime issuedOn = DateTime.Now;
DateTime expiredOn = DateTime.Now.AddSeconds(
Convert.ToDouble(ConfigurationManager.AppSettings["AuthTokenExpiry"]));
var tokendomain = new Token
{
UserId = userId,
AuthToken = token,
IssuedOn = issuedOn,
ExpiresOn = expiredOn
};

_unitOfWork.TokenRepository.Insert(tokendomain);
_unitOfWork.Save();
var tokenModel = new TokenEntity()
{
UserId = userId,
IssuedOn = issuedOn,
ExpiresOn = expiredOn,
AuthToken = token
};

return tokenModel;
}

/// <summary>
/// Method to validate token against expiry and existence in database.
/// </summary>
/// <param name="tokenId"></param>
/// <returns></returns>
public bool ValidateToken(string tokenId)
{
var token = _unitOfWork.TokenRepository.Get(t => t.AuthToken == tokenId && t.ExpiresOn > DateTime.Now);
if (token != null && !(DateTime.Now > token.ExpiresOn))
{
token.ExpiresOn = token.ExpiresOn.AddSeconds(
Convert.ToDouble(ConfigurationManager.AppSettings["AuthTokenExpiry"]));
_unitOfWork.TokenRepository.Update(token);
_unitOfWork.Save();
return true;
}
return false;
}

/// <summary>
/// Method to kill the provided token id.
/// </summary>
/// <param name="tokenId">true for successful delete</param>
public bool Kill(string tokenId)
{
_unitOfWork.TokenRepository.Delete(x => x.AuthToken == tokenId);
_unitOfWork.Save();
var isNotDeleted = _unitOfWork.TokenRepository.GetMany(x => x.AuthToken == tokenId).Any();
if (isNotDeleted) { return false; }
return true;
}

/// <summary>
/// Delete tokens for the specific deleted user
/// </summary>
/// <param name="userId"></param>
/// <returns>true for successful delete</returns>
public bool DeleteByUserId(int userId)
{
_unitOfWork.TokenRepository.Delete(x => x.UserId == userId);
_unitOfWork.Save();

var isNotDeleted = _unitOfWork.TokenRepository.GetMany(x => x.UserId == userId).Any();
return !isNotDeleted;
}

#endregion
}
}

Do not forget to resolve the dependency of this Token service in DependencyResolver class.  Add  registerComponent.RegisterType();  to the SetUp method of DependencyResolver class in BusinessServices project.

  [Export(typeof(IComponent))]
    public class DependencyResolver : IComponent
    {
        public void SetUp(IRegisterComponent registerComponent)
        {
            registerComponent.RegisterType();
            registerComponent.RegisterType();
            registerComponent.RegisterType();

        }
    }
Do not forget to resolve the dependency of this Token service in DependencyResolver class. AddregisterComponent.RegisterType(); to the SetUp method ofDependencyResolver class in BusinessServices project.
  [Export(typeof(IComponent))]
    public class DependencyResolver : IComponent
    {
        public void SetUp(IRegisterComponent registerComponent)
        {
            registerComponent.RegisterType();
            registerComponent.RegisterType();
            registerComponent.RegisterType();

        }
    }

Setup WebAPI/Controller

Now since we decided, that we don’t want authentication to be applied on each and every API exposed, I’ll create a single Controller/API endpoint that takes authentication or login request and makes use of Token Service to generate token and respond client/caller with a token that persists in database with expiry details.
Add a new Controller under Controllers folder in WebAPI with a name Authenticate,

AuthenticateController

using System.Configuration;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using AttributeRouting.Web.Http;
using BusinessServices;
using WebApi.Filters;

namespace WebApi.Controllers
{
    [ApiAuthenticationFilter]
    public class AuthenticateController : ApiController
    {
        #region Private variable.

        private readonly ITokenServices _tokenServices;

        #endregion

        #region Public Constructor

        /// <summary>
        /// Public constructor to initialize product service instance
        /// </summary>
        public AuthenticateController(ITokenServices tokenServices)
        {
            _tokenServices = tokenServices;
        }

        #endregion

       /// <summary>
       /// Authenticates user and returns token with expiry.
       /// </summary>
       /// <returns></returns>
        [POST("login")]
        [POST("authenticate")]
        [POST("get/token")]
        public HttpResponseMessage Authenticate()
        {
            if (System.Threading.Thread.CurrentPrincipal!=null && System.Threading.Thread.CurrentPrincipal.Identity.IsAuthenticated)
            {
                var basicAuthenticationIdentity = System.Threading.Thread.CurrentPrincipal.Identity as BasicAuthenticationIdentity;
                if (basicAuthenticationIdentity != null)
                {
                    var userId = basicAuthenticationIdentity.UserId;
                    return GetAuthToken(userId);
                }
            }
           return null;
        }

        /// <summary>
        /// Returns auth token for the validated user.
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        private HttpResponseMessage GetAuthToken(int userId)
        {
            var token = _tokenServices.GenerateToken(userId);
            var response = Request.CreateResponse(HttpStatusCode.OK, "Authorized");
            response.Headers.Add("Token", token.AuthToken);
            response.Headers.Add("TokenExpiry", ConfigurationManager.AppSettings["AuthTokenExpiry"]);
            response.Headers.Add("Access-Control-Expose-Headers", "Token,TokenExpiry" );
            return response;
        }
    }
}
The controller is decorated with our authentication filter,
[ApiAuthenticationFilter]
public class AuthenticateController : ApiController
So, each and every request coming through this controller will have to pass through this authentication filter, that check for BasicAuthentication header and credentials.Authentication filter sets CurrentThreadprincipal to the authenticated Identity.
There is a single Authenticate method / action in this controller. You can decorate it with multiple endpoints like we discussed in fourth part of the series,
        [POST("login")]
        [POST("authenticate")]
        [POST("get/token")]
Authenticate method first checks for CurrentThreadPrincipal and if the user is authenticated or not i.e job done by authentication filter,
if (System.Threading.Thread.CurrentPrincipal!=null && 
    System.Threading.Thread.CurrentPrincipal.Identity.IsAuthenticated)
When it finds that the user is authenticated, it generates an auth token with the help of TokenServices and returns user with Token and its expiry,
response.Headers.Add("Token", token.AuthToken);
response.Headers.Add("TokenExpiry", ConfigurationManager.AppSettings["AuthTokenExpiry"]);
response.Headers.Add("Access-Control-Expose-Headers", "Token,TokenExpiry" );
return response;
In our BasicAuthenticationIdentity class, I purposely used userId property so that we can make use of this property when we try to generate token, that we are doing in this controller’s Authenticate method,
var basicAuthenticationIdentity = System.Threading.Thread.CurrentPrincipal.Identity as BasicAuthenticationIdentity;
if (basicAuthenticationIdentity != null)
{
var userId = basicAuthenticationIdentity.UserId;
return GetAuthToken(userId);
}
Now when you run this application, You’ll see Authenticate api as well, just invoke this api with Baisc Authentication and User credentials, you’ll get the token with expiry,let’s do this step by step.
  1. Run the application.
  2. Click on first api link i.e. POST authenticate. You’ll get the page to test the api,
  3. Press the TestAPI button in the right corner.In the test console, provide Header information with Authorization as Basic and user credentials in Base64 format, like we did earlier. Click on Send.
  4. Now since we have provided valid credentials, we’ll get a token from the Authenticate controller, with its expiry time,
In database,
Here we get response 200, i.e. our user is authenticated and logged into system. TokenExpiry in 900 i.e. 15 minutes. Note that the time difference between IssuedOn and ExpiresOn is 15 minutes, this we did in TokenServices class method GenerateToken, you can set the time as per your need. Token is 604653d8-eb21-495c-8efd-da50ef4e56d3. Now for 15 minutes we can use this token to call our other services. But before that we should mark our other services to understand this token and respond accordingly. Keep the generated token saved so that we can use it further in calling other services that I am about to explain. So let’s setup authorization on other services.

Setup Authorization Action Filter

We already have our Authentication filter in place and we don’t want to use it for authorization purposes. So we have to create a new Action Filter for authorization. This action filter will only recognize Token coming in requests. It assumes that, requests are already authenticated through our login channel, and now user is authorized/not authorized to use other services like Products in our case, there could be n number of other services too, which can use this authorization action filter. For request to get authorized, nbow we don’t have to pass user credentials. Only token(received from Authenticate controller after successful validation) needs to be passed through request.
Add a folder named ActionFilters in WebAPI project. And add a class named AuthorizationRequiredAttribute
Deriving from ActionFilterAttribute,
Override the OnActionExecuting method of ActionFilterAttribute, this is the way we define an action filter in API project.
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using BusinessServices;

namespace WebApi.ActionFilters
{
public class AuthorizationRequiredAttribute : ActionFilterAttribute
{
private const string Token = "Token";

public override void OnActionExecuting(HttpActionContext filterContext)
{
//  Get API key provider
var provider = filterContext.ControllerContext.Configuration
.DependencyResolver.GetService(typeof(ITokenServices)) as ITokenServices;

if (filterContext.Request.Headers.Contains(Token))
{
var tokenValue = filterContext.Request.Headers.GetValues(Token).First();

// Validate Token
if (provider != null && !provider.ValidateToken(tokenValue))
{
var responseMessage = new HttpResponseMessage(HttpStatusCode.Unauthorized) { ReasonPhrase = "Invalid Request" };
filterContext.Response = responseMessage;
}
}
else
{
filterContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
}

base.OnActionExecuting(filterContext);

}
}
}
The overridden method checks for “Token” attribute in the Header of every request, if token is present, it callsValidateToken method from TokenServices to check if the token exists in the database. If token is valid, our request is navigated to the actual controller and action that we requested, else you’ll get an error message saying unauthorized.

Mark Controllers with Authorization filter

We have our action filter ready. Now let’s mark our controller ProductController with this attribute. Just open Product controller class and at the top just decorate that class with this ActionFilter attribute,
    [AuthorizationRequired]
    [RoutePrefix("v1/Products/Product")]
    public class ProductController : ApiController
    {
We have marked our controller with the action filter that we created, now every request coming to the actions of this controller will have to be passed through this ActionFilter, that checks for the token in request.
You can mark other controllers as well with the same attribute, or you can do marking at action level as well. Supoose you want certain actions should be available to all users irrespective of their authorization then you can just mark only those actions which require authorization and leave other actions as they are like I explained in Step 4 of Implementing Basic Authentication.

Maintaining Session using Token

We can certainly use these tokens to maintain session as well. The tokens are issues for 900 seconds i.e. 15 minutes. Now we want that user should continue to use this token if he is using other services as well for our application. Or suppose there is a case where we only want user to finish his work on the site within 15 minutes or within his session time before he makes a new request. So while validating token in TokenServices, what I have done is, to increase the time of the token by 900 seconds whenever a valid request comes with a valid token,
        /// <summary>
        /// Method to validate token against expiry and existence in database.
        /// </summary>
        /// <param name="tokenId"></param>
        /// <returns></returns>
        public bool ValidateToken(string tokenId)
        {
            var token = _unitOfWork.TokenRepository.Get(t => t.AuthToken == tokenId && t.ExpiresOn > DateTime.Now);
            if (token != null && !(DateTime.Now > token.ExpiresOn))
            {
                token.ExpiresOn = token.ExpiresOn.AddSeconds(
                                              Convert.ToDouble(ConfigurationManager.AppSettings["AuthTokenExpiry"]));
                _unitOfWork.TokenRepository.Update(token);
                _unitOfWork.Save();
                return true;
            }
            return false;
        }
In above code for token validation, first we check if the requested token exists in the database and is not expired. We check expiry by comparing it with current date time. If it is valid token we just update the token into database with a new ExpiresOn time that is adding 900 seconds.
            if (token != null && !(DateTime.Now > token.ExpiresOn))
            {
                token.ExpiresOn = token.ExpiresOn.AddSeconds(
                                              Convert.ToDouble(ConfigurationManager.AppSettings["AuthTokenExpiry"]));
                _unitOfWork.TokenRepository.Update(token);
                _unitOfWork.Save();
By doing this we can allow end user or client to maintain session and keep using our services/application with a session timeout of 15 minutes. This approach can also be leveraged in multiple ways, like making different services with different session timeouts or many such conditions could be applied when we work on real time application using APIs.

Running the application

Our job is almost done.
We just need to run the application and test if it is working fine or not. If you have saved the token you generated earlier while testing authentication you can use same to test authorization. I am just again running the whole cycle to test application.

Test Authentication

Repeat the tests we did earlier to get Auth Token.Just invoke the Authenticate controller with valid credentials and Basic authorization header. I get,
And without providing Authorization header as basic with credentials I get,
I just saved the token that I got in first request.
Now try to call ProductController actions.

Test Authorization

Run the application to invoke Product Controller actions.Try to invoke them without providing any Token,
Invoke first service in the list,
Click send,
Here we get Unauthorized, i.e. because our ProductController is marked with authorization attribute that checks for a Token. So here our request is invalid. Now try calling this action by providing the token that we saved,
Click on Send and we get,
That means we got the response and our token was valid. Now we see our Authentication and Authorization, both functionalities are working fine. You can test Sessions by your own.
Likewise you can test all actions. You can create other controllers and test the security, and play around with different set of permutations and combinations.

Conclusion

We covered and learnt a lot. In this article I tried to explain about how we can build an API application with basic Authentication and Authorization. One can mould this concept to achieve the level of security needed. Like token generation mechanism could be customized as per one’s requirement. Two level of security could be implemented where authentication and authorization is needed for every service. One can also implement authorization on actions based on Roles.
I already stated that there is no specific way of achieving security, the more you understand the concept, the more secure system you can make. The techniques used in this article or the design implemented in this article should be leveraged well if you use it with SSL (Secure Socket Layer), running the REST apis on https. In my next article I’ll try to explain some more beautiful implementations and concepts. Till then Happy Coding Smile | :)
You can also download the complete source code with all packages from Github.

References

Read more:

Other Series

My other series of articles:

For more technical articles you can reach out to CodeTeddy.