Quantcast
Channel: ASP.Net Web API – Bit of Technology
Viewing all 37 articles
Browse latest View live

Detailed Tutorial for Building ASP.Net Web API RESTful Service

$
0
0

When you are designing, implementing, and releasing new REST API a lot of constraints and standards should be considered; once the API is available to public, and clients start consuming it, significant changes are very hard!

There are lot of API designs in the web; but there is no widely adopted design which work for all scenarios, that is why you are left with many choices and grey areas.

So in this multi-part series we’ll be building from scratch a sample eLearning system API which follows best practices for building RESTful API using Microsoft technology stack. We’ll use Entity framework 6 (Code First) and ASP.Net Web API.

Before digging into code samples and walkthrough I would like to talk little bit about the basics and characteristics of RESTful services and ASP.Net Web API.

Basics of RESTful services:

REST stands for Representational State Transfer, it is a simple stateless architecture that runs over HTTP where each unique URL is representation of some resource. There are four basic design principles which should be followed when creating RESTful service:

  • Use HTTP methods (verbs) explicitly and in consistent way to interact with resources (Uniform Interface), i.e. to retrieve a resource use GET, to create a resource use POST, to update a resource use PUT/PATCH, and to remove a resource use DELETE. 
  • Interaction with resources is stateless; each request initiated by the client should include within the HTTP headers and body of the request all the parameters, context, and data needed by the server to generate the response.
  • Resource identification should be done through URIs, in simple words the interaction between client and resource in the server should be done using URIs only. Those URIs can act like a service discovery and interface for your RESTful service.
  • Support JSON or/and XML as the format of the data exchanged in the request/response payload or in the HTTP body.

For more information about RESTful services, you can check this information rich IBM article.

Introducing the ASP.NET Web API

The ASP.Net Web API shipped with ASP.Net MVC4, it has been around more than one year and half. It is considered a framework for building HTTP services which can be consumed by broad range of clients such as browsers, smart phones, and desktop applications. It is not considered as a part of the MVC framework, it is part of the core ASP.Net platform and can be used in MVC projects, Asp.Net WebForms, or as stand alone web service.

ASP.Net Web API Stack

ASP.Net Web API Stack

Today with the increase of using smart phones and the trend of building Single Page Apps (SPA); having a light weight Web API which exposes your services data to clients is very important. Asp.Net Web API will help you out of the box in creating RESTFul compliant services using features of HTTP like (URIs, request/response, headers, versioning, and different content formats).

What we’ll build in this multi-part series?

We need to keep things simple and easy to understand and learn from, but at the same time we need to cover different features provided by ASP.Net Web API and best practices to build RESTFul service.

We’ll be building a simple API for eLearning system, this API allows students to enroll in different courses, allows tutors to view students enrolled in each course, do CRUD operations on courses and students, and many more operations. I’ll be listing detailed use cases which we’ll covered in the next post.

We’ll discuss and implement different Web API features such as:

  • Using different routing configuration, controllers, resources association, formatting response, and filters.
  • Implementing Dependency Injection using Ninject.
  • Apply results pagination using different formatting techniques.
  • Implementing complex CRUD operations on multiple resources.
  • Securing Web API by using Basic authentication, forcing SSL.
  • Implementing API Versioning using different techniques (URL versioning, by query string, by version header, and by accept header).
  • Implement resources cashing.

Note: we’ll not build a client in this series, we’ll use Fiddler or Postman REST client to compose HTTP requests.

I broke down this series into multiple posts which I’ll be posting gradually, posts are:

All the source code for this series is available on GitHub, you can download it locally or you can fork it. If there is nothing clear or ambiguous please drop me a comment and I’ll do my best to reply your questions.

To get the best of this tutorial I recommend you to follow the posts one by one. Happy coding and hopefully this series will help you to get started with ASP.Net Web API :)

Source code is available on GitHub.



Building ASP.Net Web API RESTful Service – Part 1

$
0
0

This is the first part of Building ASP.Net Web API RESTful Service Series. The topics we’ll cover are:

Building the Database Model using Entity Framework Code First

We’ll be using Entity Framework “Code First approach” where we’ll define our model objects using “Plain Old CLR Objects” POCO. We’ll be code centeric and start by writing standard .NET classes which define the domain model objects that are suitable for our API. Those POCO classes will be responsible to generate our eLearning database.

The eLearning database is simple, we want to be able to define and store “Students”, and “Tutors”. As well we have to define and store “Courses” and “Subjects”. We need to allow each Student to enroll in different “Courses”.

The image below shows the final result of the database schema, I’m listing it early so it will facilitate the understanding of the POCO classes we’ll build now:

eLearning Database Schema

Step 1: Create a new empty Class Library Project

We’ll start by creating a new empty class library project which will be responsible of all data management operations (Data Layer). Choose File->New Project->Windows->Class Library and name your solution “eLearning” and your class library “Learning.Data”. You can choose .NET framework 4 or 4.5.

Step 2: Install Entity framework using NuGet

We need to install Entity framework version 5 or 6 using NuGet package manager or NuGet package console, the package we’ll install is named “EntityFramework“. Our solution will look as below after installing EntityFramework:

eLearningSolution

Step 3: Creating our Model

As we stated before, we do not have our eLearning database and we need to create it by writing standard .NET classes that define the domain model objects.

Now add a new folder called “Entities” then add five classes called “Subject”, “Course”, “Tutor”, “Student”, and “Enrollment” those classes contain just simple properties and will shape our database:


    public class Subject
    {
        public Subject()
        {
            Courses = new List<Course>();
        }

        public int Id { get; set; }
        public string Name { get; set; }

        public ICollection<Course> Courses;
    }

    public class Course
    {
        public Course()
        {
            Enrollments = new List<Enrollment>();
            CourseTutor = new Tutor();
            CourseSubject = new Subject();
        }

        public int Id { get; set; }
        public string Name { get; set; }
        public Double Duration { get; set; }
        public string Description { get; set; }

        public Tutor CourseTutor { get; set; }
        public Subject CourseSubject { get; set; }

        public ICollection<Enrollment> Enrollments { get; set; }
    }

    public class Tutor
    {
        public Tutor()
        {
            Courses = new List<Course>();
        }
        public int Id { get; set; }
        public string Email { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public Enums.Gender Gender { get; set; }

        public ICollection<Course> Courses;
    }

    public class Student
    {
        public Student()
        {
            Enrollments = new List<Enrollment>();
        }

        public int Id { get; set; }
        public string Email { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public Enums.Gender Gender { get; set; }
        public DateTime DateOfBirth { get; set; }
        public DateTime? RegistrationDate { get; set; }
        public DateTime? LastLoginDate { get; set; }

        public ICollection<Enrollment> Enrollments { get; set; }
    }

    public class Enrollment
    {
        public Enrollment()
        {
            Student = new Student();
            Course = new Course();
        }
        public int Id { get; set; }
        public DateTime EnrollmentDate { get; set; }
        public Student Student { get; set; }
        public Course Course { get; set; }
    }

As you noticed those classes do not derive from any base classes nor have any attributes, having those standard classes give us more data access flexibility and allow us to focus on the application needs without worrying about persistence implementation.

Entity framework Code First by default supports an approach called “Convention over Configuration” for mapping your POCO classes to database objects (Tables, Table fields data types, and FK Relations). I find this approach is useful in scenarios where you are building a demo/simple applications. But in our case we need to override this conventions by providing custom database mapping rules using Fluent API.

Step 4: Applying Custom Mapping Rules

Once we apply the custom mapping rules we will be able to define datatype for each column, set null-ability, map FK relationships between tables, and specify PK and Identity columns.

To do this we need to create new folder named “Mappers” then add five classes which derives from System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<T>

Classes are: “CourseMapper”, “EnrollmentMapper”, “StudentMapper”, “SubjectMapper”, and “TutorMapper”.


class CourseMapper : EntityTypeConfiguration<Course>
    {
        public CourseMapper()
        {
            this.ToTable("Courses");

            this.HasKey(c => c.Id);
            this.Property(c => c.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            this.Property(c => c.Id).IsRequired();

            this.Property(c => c.Name).IsRequired();
            this.Property(c => c.Name).HasMaxLength(255);

            this.Property(c => c.Duration).IsRequired();

            this.Property(c => c.Description).IsOptional();
            this.Property(c => c.Description).HasMaxLength(1000);

            this.HasRequired(c => c.CourseSubject).WithMany().Map(s => s.MapKey("SubjectID"));
            this.HasRequired(c => c.CourseTutor).WithMany().Map(t => t.MapKey("TutorID"));

        }
    }

class EnrollmentMapper : EntityTypeConfiguration<Enrollment>
    {
        public EnrollmentMapper()
        {
            this.ToTable("Enrollments");

            this.HasKey(e => e.Id);
            this.Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            this.Property(e => e.Id).IsRequired();

            this.Property(e => e.EnrollmentDate).IsRequired();
            this.Property(e => e.EnrollmentDate).HasColumnType("smalldatetime");

            this.HasOptional(e => e.Student).WithMany(e => e.Enrollments).Map(s => s.MapKey("StudentID")).WillCascadeOnDelete(false);
            this.HasOptional(e => e.Course).WithMany(e => e.Enrollments).Map(c => c.MapKey("CourseID")).WillCascadeOnDelete(false);
        }
    }

class StudentMapper : EntityTypeConfiguration<Student>
    {
        public StudentMapper()
        {
            this.ToTable("Students");

            this.HasKey(s => s.Id);
            this.Property(s => s.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            this.Property(s => s.Id).IsRequired();

            this.Property(s => s.Email).IsRequired();
            this.Property(s => s.Email).HasMaxLength(255);
            this.Property(s => s.Email).IsUnicode(false);

            this.Property(s => s.UserName).IsRequired();
            this.Property(s => s.UserName).HasMaxLength(50);
            this.Property(s => s.UserName).IsUnicode(false);

            this.Property(s => s.Password).IsRequired();
            this.Property(s => s.Password).HasMaxLength(255);

            this.Property(s => s.FirstName).IsRequired();
            this.Property(s => s.FirstName).HasMaxLength(50);

            this.Property(s => s.LastName).IsRequired();
            this.Property(s => s.LastName).HasMaxLength(50);

            this.Property(s => s.Gender).IsOptional();

            this.Property(s => s.DateOfBirth).IsRequired();
            this.Property(s => s.DateOfBirth).HasColumnType("smalldatetime");

            this.Property(s => s.RegistrationDate).IsOptional();
            this.Property(s => s.RegistrationDate).HasColumnType("smalldatetime");

            this.Property(s => s.LastLoginDate).IsOptional();
            this.Property(s => s.LastLoginDate).HasColumnType("smalldatetime");

        }
    }

class SubjectMapper : EntityTypeConfiguration<Subject>
    {
        public SubjectMapper ()
	    {
            this.ToTable("Subjects");

            this.HasKey(s => s.Id);
            this.Property(s => s.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            this.Property(s => s.Id).IsRequired();

            this.Property(s => s.Name).IsRequired();
            this.Property(s => s.Name).HasMaxLength(255);

	    }
    }

class TutorMapper : EntityTypeConfiguration<Tutor>
    {
        public TutorMapper()
        {
            this.ToTable("Tutors");

            this.HasKey(s => s.Id);
            this.Property(s => s.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            this.Property(s => s.Id).IsRequired();

            this.Property(s => s.Email).IsRequired();
            this.Property(s => s.Email).HasMaxLength(255);
            this.Property(s => s.Email).IsUnicode(false);

            this.Property(s => s.UserName).IsRequired();
            this.Property(s => s.UserName).HasMaxLength(50);
            this.Property(s => s.UserName).IsUnicode(false);

            this.Property(s => s.Password).IsRequired();
            this.Property(s => s.Password).HasMaxLength(255);

            this.Property(s => s.FirstName).IsRequired();
            this.Property(s => s.FirstName).HasMaxLength(50);

            this.Property(s => s.LastName).IsRequired();
            this.Property(s => s.LastName).HasMaxLength(50);

            this.Property(s => s.Gender).IsOptional();
        }
    }

By looking at the code above you will notice that we are configuring each POCO class property (Datatype, Null-ability, PK and identity columns, and FK relations). Those configuration will be reflected on the database tables we are building. For more details about mapping/configuring fluent API you can visit this link.

The relationships between eLearning database tables are simple and described as the below:

  • Each “Course” has a “Subject”.
  • Each “Tutor” can tech multiple “Courses”.
  • Each “Student” can enroll in multiple “Courses”. So we’ll have Many-to-Many table to persist the relation called “Enrollment”.

Step 5: Creating Context Class to Handle Database Persistence

Now we need to add new class named “LearningContext” which derives from class “System.Data.Entity.DbContext”:


    public class LearningContext:DbContext
    {
        public LearningContext():
            base("eLearningConnection")
        {
            Configuration.ProxyCreationEnabled = false;
            Configuration.LazyLoadingEnabled = false;

            Database.SetInitializer(new MigrateDatabaseToLatestVersion<LearningContext, LearningContextMigrationConfiguration>());
        }

        public DbSet<Course> Courses {get;set;}
        public DbSet<Enrollment> Enrollments { get; set; }
        public DbSet<Student> Students { get; set; }
        public DbSet<Subject> Subjects { get; set; }
        public DbSet<Tutor> Tutors { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new StudentMapper());
            modelBuilder.Configurations.Add(new SubjectMapper());
            modelBuilder.Configurations.Add(new TutorMapper());
            modelBuilder.Configurations.Add(new CourseMapper());
            modelBuilder.Configurations.Add(new EnrollmentMapper());

            base.OnModelCreating(modelBuilder);
        }
    }

The “LearningContext” class is responsible for three tasks which they are:

  1. Exposing our POCO classes as public DbSet properties, this means that every POCO class is transferred to a database table.
  2. Overriding OnModelCreating procedure which is used to apply custom mapping rules for each POCO class by adding the new configurations to the DbModelBuilder configurations.
  3. In “LearningContext” class constructor we have implemented two things:
  • Disabled the ProxyCreationEnabled and LazyLoadingEnabled properties which they are enabled by default. The Lazy Loading property enables loading the sub-objects of model up front, in our case we want to load them on demand. The Proxy Creation property is used in conjugation with Lazy Loading property, so if is set to false the ”LearningContext” won’t load sub-objects unless Include method is called.
  • Configured the initialization and migration strategy of the database to migrate to latest version if a model has changed (i.e. new property has been added). To implement this we need to add new class called “LearningContextMigrationConfiguration” which derives from class “System.Data.Entity.Migrations.DbMigrationsConfiguration<TContext>”. The code listing as below:

    class LearningContextMigrationConfiguration : DbMigrationsConfiguration<LearningContext>
    {
        public LearningContextMigrationConfiguration()
        {
            this.AutomaticMigrationsEnabled = true;
            this.AutomaticMigrationDataLossAllowed = true;

        }

#if DEBUG
        protected override void Seed(LearningContext context)
        {
            new LearningDataSeeder(context).Seed();
        }
#endif

    }

The “LearningContextMigrationConfiguration” class is responsible for two tasks which they are:

  1. In the constructor of the class we set the property AutomaticMigrationsEnabled to true which means that we need EF to handle the automatic migration for us without caring about DB Versioning. As well we set the property AutomaticMigrationDataLossAllowed  to true, this is dangerous to set in production environment. If it was set to false an exception will be thrown if data loss may occur as part of an automatic migration, but for our series it is fine to keep it to true.
  2. Overriding the Seed procedure which is used to seed our database with initial data, this procedure gets called every time our application starts, I’ve created a class called “LearningDataSeeder” which responsible to seed the database, I won’t list it is code here but you can browse it on GitHub or by downloading the source code for the API.

Till this point we’ve implemented all the code needed to configure and create our eLearning database depending on model objects we’ve defined, we can stop at this point and consider our data layer completed, but we want to enhance it more and implement “Repository Pattern” which facilitates data access and manipulation once we start building the Web API. So in the next post we’ll implement the Repository Pattern for our data access layer.

Source code is available on GitHub.


Building ASP.Net Web API RESTful Service – Part 2

$
0
0

This is the second part of Building ASP.Net Web API RESTful Service Series. The topics we’ll cover are:

Applying the Repository Pattern for the Data Access Layer

Applying Repository Pattern is useful to isolate domain objects from the details of database access layer. It will act as an abstraction layer over the mapping layer where query constructions and database objects manipulation take place. As well the Repository will act like in-memory domain object collection where objects can be added or removed from the Repository as they are removed from a simple collection of objects, moreover the Repository will be responsible to execute the appropriate operations behind the scenes.

Before we dig into the Repository implementation let’s list the use cases needed to be implemented in our Web API, this for sure will help us in building the right Repository methods and operations:

  • Listing all available subjects, and listing single subject by querying ID.
  • Listing all available courses including the sub-models (Subject, and Tutor).
  • Getting single course by querying ID including the sub-models(Subject, Tutor, and Enrolled Students)
  • Listing all available students including all sub-models (Enrolled in Courses, Course Subject, and Tutor)
  • Get summary of all available students.
  • List all enrolled students in specific course by querying course ID.
  • List all classes for a certain student by querying Username.
  • Get certain student by querying Username.
  • Authenticate students by validating Username and Password.
  • Enroll an authenticated student in a course.
  • CRUD operations for Students.
  • CRUD operations for Courses.

Building the Repository Pattern

We need to add new Interface named “ILearningRepository” to implement all the use cases listed above:


public interface ILearningRepository
    {
        IQueryable<Subject> GetAllSubjects();
        Subject GetSubject(int subjectId);

        IQueryable<Course> GetCoursesBySubject(int subjectId);

        IQueryable<Course> GetAllCourses();
        Course GetCourse(int courseId);
        bool CourseExists(int courseId);

        IQueryable<Student> GetAllStudentsWithEnrollments();
        IQueryable<Student> GetAllStudentsSummary();

        IQueryable<Student> GetEnrolledStudentsInCourse(int courseId);
        Student GetStudentEnrollments(string userName);
        Student GetStudent(string userName);

        Tutor GetTutor(int tutorId);

        bool LoginStudent(string userName, string password);

        bool Insert(Student student);
        bool Update(Student originalStudent, Student updatedStudent);
        bool DeleteStudent(int id);

        int EnrollStudentInCourse(int studentId, int courseId, Enrollment enrollment);

        bool Insert(Course course);
        bool Update(Course originalCourse, Course updatedCourse);
        bool DeleteCourse(int id);

        bool SaveAll();
    }

The methods in the interface above covers all the operations needed in our Web API, note how we are returning IQueryable<T> for any method returns a collection of objects, this will facilitate the pagination, sorting, and results ordering in our Web API because IQueryable will give us deferred execution and fully support for LINQ-to-SQL. In other words IQueryable result will save us from returning too many unwanted rows from the database.

Now we need to add new class called “LearningRepository” which will implement the interface “ILearningRepository”. I’ll list partial implementation of the class here. We’ll be able to see the full implementation by browsing the code on GitHub or by downloading the source.


   public class LearningRepository : ILearningRepository
    {
        private LearningContext _ctx;
        public LearningRepository(LearningContext ctx)
        {
            _ctx = ctx;
        }

	public IQueryable<Subject> GetAllSubjects()
        {
            return _ctx.Subjects.AsQueryable();
        }

	/*Rest of methods implementation goes here....*/
     }

You can notice that the constructor of the class “LearningRepository” accepts the database context object “LearningContext” and there is a private member “_ctx” which is used to interact with all DbSet objects without instantiating it. That design pattern is called Dependency Injection, in simple words it means that objects do not create other objects on which they rely to do their work. Instead, they get the objects that they need from an outside source.

So in our situation the class “LearningRepository” depends on class “LearningContext”, but it won’t create an instance from it to complete its work, instead we will inject this object to it using an external DI framework called Ninject. We’ll cover this deeply in the coming parts. If you are new to Dependency Injection design pattern, I recommend you to read my previous blog post about it.

Until this point our data access layer is complete and ready to be used with our Web API, so lets jump to the next post where we’ll start working on Web API.

Source code is available on GitHub.


Building ASP.Net Web API RESTful Service – Part 3

$
0
0

This is the third part of of Building ASP.Net Web API RESTful Service Series. The topics we’ll cover are:

Getting started with ASP.Net Web API

Now we are ready to start building our Web API, as I stated before we can use ASP.Net Web API with MVC projects, Web Forms, or as stand alone web service. In our case we will use an empty MVC 4 template, to do this right-click on solution “eLearning” Choose Add->New Project->Web->ASP.NET MVC 4 Web Application and name your Web API “Learning.Web”->Select Empty Template. Your solution will be as the below image:

eLearningSolution2

Before talking about Web API configuration and how we can build our URIs to consume the resources, we need to understand the relation between the HTTP verb and the resource we’ll consume, as example we will consider the “Course” domain model object as the resource, the below table lists the usage of HTTP verbs with “Course” resource.

Action HTTP Verb Relative URI
Get all courses GET /api/courses
Get single course GET /api/courses/id
Add new course POST /api/coursesNew course is sent in POST body
Update existing course PUT or PATCH /api/courses/idUpdated course is sent in POST body
Delete course DELETE /api/courses/id

Step 1: Configuring first route (Courses Route)

In order to configure this route, the MVC 4 empty template we have just used has by default a class named “WebApiConfig” inside the “App_Start” folder, this class is called at the application start event in “Global.asax” and it is responsible to configure routing for Web API, we’ll be visiting and modifying this class multiple times to configure our Web API routes.

By default there will be a route named “DefaultApi”, we need to delete this route and replace it with route below:


public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
	       config.Routes.MapHttpRoute(
               name: "Courses",
               routeTemplate: "api/courses/{id}",
               defaults: new { controller = "courses", id = RouteParameter.Optional }
           );
	}
     }

What we’ve done here is simple, we added new route named “Courses”, and mapped this route to a URI template “api/courses/{id}”, and assigned two default values to it which they are the name of controller it will use “Courses”, and set the “id” parameter to be optional. Now the relative URI in the form /api/courses or /api/courses/5 will be routed using this route. If we didn’t specify that id is optional then the URI /api/courses won’t be valid.

Step 2: Adding First Controller (Courses Controller)

Controller in Web API is a class that handles HTTP requests from the client, now we have to add a controller which will handle all HTTP verbs issued against URI /api/courses, to do this right-click on Controllers folder->Select Add->Name the controller “CoursesController” and choose “Empty API Controller” Template.

The controller we’ve added derives from “ApiController”, It is important to name the controller as we mentioned before “CoursesController” because Web API controller selection is implemented in a way which looks for all classes derives from “ApiController” then match the first part of the class name Courses with the defaults route controller property we defined in class “WebApiConfig”.

Step 3: Action Selection inside Controllers

We’ll start by adding support for the two GET actions we defined in the table above, getting all courses, and getting single course by id.

Action selecting in Web API controllers is smart; if we created two methods Get() and GetCourse(int id), then issued a GET request to the URL /api/courses/5
the method GetCourse(int id) will be selected and executed; because by convention its starts with “Get” and the URI contains an “id” segment in the path. The same applies for other HTTP verbs (POST, PUT, DELETE). Let’s implement this as the code below:


public class CoursesController : ApiController
    {
        public List<Course> Get()
        {
            ILearningRepository repository = new LearningRepository(new LearningContext());

            return repository.GetAllCourses().ToList();
        }

        public Course GetCourse(int id)
        {
            ILearningRepository repository = new LearningRepository(new LearningContext());

            return repository.GetCourse(id);
        }
     }

So if we made GET request to the URI http://localhost:{your_port}/api/courses the action Get() will be selected and executed and part of the response will be as below:

Note: I’m using JSON view plugin on Firefox to issue GET request and return data in JSON format.

[
    {
        "Id": 1,
        "Name": "History Teaching Methods 1",
        "Duration": 5,
        "Description": "The course will talk in depth about: History Teaching Methods 1",
        "CourseTutor": {
            "Courses": [ ],
            "Id": 1,
            "Email": "Ahmad.Joudeh@outlook.com",
            "UserName": "AhmadJoudeh",
            "Password": "EFZWOFEO",
            "FirstName": "Ahmad",
            "LastName": "Joudeh",
            "Gender": 0
        },
        "CourseSubject": {
            "Courses": [ ],
            "Id": 1,
            "Name": "History"
        },
        "Enrollments": [ ]
    },
    {
        "Id": 2,
        "Name": "History Teaching Methods 2",
        "Duration": 4,
        "Description": "The course will talk in depth about: History Teaching Methods 2",
        "CourseTutor": {
            "Courses": [ ],
            "Id": 1,
            "Email": "Ahmad.Joudeh@outlook.com",
            "UserName": "AhmadJoudeh",
            "Password": "EFZWOFEO",
            "FirstName": "Ahmad",
            "LastName": "Joudeh",
            "Gender": 0
        },
        "CourseSubject": {
            "Courses": [ ],
            "Id": 1,
            "Name": "History"
        },
        "Enrollments": [ ]
    }
]

Now if we try to issue another GET request to the URI http://localhost:{your_port}/api/courses/5 in order to select a single course, the action GetCourse(int id) will be selected and executed, but an exception will be thrown when trying to serialize the object graph we return from method GetCourse. the exception message will read “Self referencing loop detected for property ‘Course’ with type ‘Learning.Data.Entities.Course’. Path ‘Enrollments[0]‘.”. In other words this method is trying to return chain of related objects which they reference each other (Course>Enrollment>Course>Enrollment>etc…).

So what we have implemnted in “CoursesController” till this moment is insufficient, the below points lists what are the lacking parts:

  • Self referencing when returning chain of objects. This can be solved using a design pattern called the Model Factory.
  • We are returning all the fields from the domain model object and leaking sensitive information to the client, for example if you take a look on “Tutor” object you will notice that we are returning the “password” field which shouldn’t be leaked to API consumer. This can be solved using the Model Factory pattern.
  • Each resource returned in the response should be linked to a URI, this will simplify resources query for the client. This can be solved using the Model Factory pattern.
  • We should return HTTP status code when returning single resource, i.e if the resource was not found we should return 404 in response header, if it was found we should return 200 OK, etc…, this can be solved by returning HttpResponseMessage object.
  • Inside each method we are instantiating our repository, this operation is expensive as it includes opening connection to the database, we need to implement Dependency Injection pattern, this can be solved by using Ninject DI framework.
  • The format for JSON response objects are in Pascal Case i.e. “FirstName”, and most probably our API will be consumed in client using JavaScript, it is easier for JS developers to work with properties formatted in Camel Case “firstName”. this can be solved by configuring JSON formatters of the response.

So in the next post we’ll cover how to fix those flaws in our Web API.

Source code is available on GitHub.


Building ASP.Net Web API RESTful Service – Part 4

$
0
0

This is the fourth part of Building ASP.Net Web API RESTful Service Series. The topics we’ll cover are:

Implement Model Factory, Dependency Injection and Configuring Formatters

In the previous post we have highlighted the flaws in current implementation of Courses controller, in this post we’ll be fixing those flaws.

Configuring Formatters

Web API provides media-type formatters for both JSON and XML. The framework inserts these formatters into the pipeline by default. Clients can request either JSON or XML in the Accept header of the HTTP request. In order to configure the JSON formatter we need to implement the code below in class “WebApiConfig”:


public static class WebApiConfig
   {
        public static void Register(HttpConfiguration config)
        {

        var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
            jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    	}
    }

What we did here that we looked at the built in formatters of type JSON, then we changed the contract resolver of the serialization settings to use Camel Case resolver. Now all JSON objects properties return in camel case.

Implement Dependency Injection using Ninject

If Dependency Injection concept is new to you, I recommend to read my previous post about it.

Now to prepare our code for dependency injection we need to add new Base API controller class named “BaseApiController” to folder “Controllers”. This class will derive from “APIController” class and its constructor accepts the Repository Interface “ILearningRepository” as parameter, we’re planing to implement DI Constructor Injection Pattern. The code will look as below:

public class BaseApiController : ApiController
    {
        private ILearningRepository _repo;

        public BaseApiController(ILearningRepository repo)
        {
            _repo = repo;
        }

        protected ILearningRepository TheRepository
        {
            get
            {
                return _repo;
            }
        }
    }

Now our “CoursesController” will derive from the “BaseApiController”, we need to use now Ninject as DI framework to do the heavy lifting for us and resolve the dependencies between our components, to install Ninject use NuGet package Manager and install the following packages:

  • Ninject
  • Ninject.Web.Common
  • WebApiContrib.IoC.Ninject

After we install those package successfully a new file named “NinjectWebCommon” is added to the App_Start folder, this file is responsible of the heavy lifting to configure the dependencies in our project, now we need to specify the dependencies between our components. As you remember in this post, when we created the “LearningRepository” its constructor accepts the database context object “LearningContext” so the “LearningRepository” class depends on the database context to work, we need register this in Ninject Kernel.

So to configure Web API to use DI we need to add the following code to the class “NinjectWebCommon”:

public static class NinjectWebCommon
    {
        private static IKernel CreateKernel()
        {
			var kernel = new StandardKernel();
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

			//Suport WebAPI Injection
            System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new WebApiContrib.IoC.Ninject.NinjectResolver(kernel);

			RegisterServices(kernel);
            return kernel;
		}

		private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<LearningContext>().To<LearningContext>().InRequestScope();
            kernel.Bind<ILearningRepository>().To<LearningRepository>().InRequestScope();
        }
    }

As you notice we are configuring Ninject to have a single instance of database context object shared by all objects created via the kernel for that HTTP request. This is good technique for sharing objects that are expensive to create. you can read more about Ninject Object Scopes here.

Implement the Model Factory Pattern

The Model Factory Pattern will help us in shaping and controlling the response returned to the client, so what we will do here is to create a simplified model for each domain object model (entity) we have in the database. i.e. “Course” entity will map to “CourseModel”, “Tutor” entity will map to “TutorModel” taking in consideration the relations between models (Each course is taught by a Tutor and related to a Subject) etc…

To implement this we need to add new folder named “Models” and add four classes named ”SubjectModel”, “TutorModel”, “CourseModel”, and “EnrollmentModel”. Those are only simple POCO classes which will be used to return the data to the client, the code for classes will be as below:


    public class SubjectModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

	public class TutorModel
    {
        public int Id { get; set; }
        public string Email { get; set; }
        public string UserName { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public Data.Enums.Gender Gender { get; set; }

    }

	public class CourseModel
    {
        public int Id { get; set; }
        public string Url { get; set; }
        public string Name { get; set; }
        public double Duration { get; set; }
        public string Description { get; set; }
        public TutorModel Tutor { get; set; }
        public SubjectModel Subject { get; set; }

    }

	public class EnrollmentModel
    {
        public DateTime EnrollmentDate { get; set; }
        public CourseModel Course { get; set; }
    }

Now we need to use those classes to create the response for the client, we need a single class which is responsible for creating those models, so we’ll add a class named “ModelFactory” as the code below:


public class ModelFactory
    {
        public ModelFactory()
        {

        }

        public CourseModel Create(Course course)
        {
            return new CourseModel()
            {
                Id = course.Id,
                Name = course.Name,
                Duration = course.Duration,
                Description = course.Description,
                Tutor = Create(course.CourseTutor),
                Subject = Create(course.CourseSubject)
            };
        }

        public TutorModel Create(Tutor tutor)
        {
            return new TutorModel()
            {
                Id = tutor.Id,
                Email = tutor.Email,
                UserName = tutor.UserName,
                FirstName = tutor.FirstName,
                LastName = tutor.LastName,
                Gender = tutor.Gender
            };
        }

        public SubjectModel Create(Subject subject)
        {
            return new SubjectModel()
            {
                Id = subject.Id,
                Name = subject.Name
            };
        }

		public EnrollmentModel Create(Enrollment enrollment)
        {
            return new EnrollmentModel()
            {
                EnrollmentDate = enrollment.EnrollmentDate,
                Course =  Create(enrollment.Course)
            };
        }
    }

What we’ve done above is simple, we’ve overloaded the function named “Create”,  so it accepts domain object input i.e. “Course” and returns a new model of type “CourseModel”. Notice how we can control the object graph and the chaining of objects and sub-objects i.e (CourseModel -> TutorModel, and CourseModel -> SubjectModel).

By doing this we’ve fixed two important flaws we have identified in the previous post which they are:

  • Self referencing when returning chain ob objects.
  • Controlling the fields returned to the client. (i.e. “TutorModel” is not returning the “password” fields in the response).

Using the Model Factory in “CoursesController” and coming controllers we’ll talk about is fairly simple, thanks for the “BaseApiController” where all controllers will derive from it. Open “BaseApiController” and add the code below:


public class BaseApiController : ApiController
    {
		 private ModelFactory _modelFactory;

		 protected ModelFactory TheModelFactory
        {
            get
            {
                if (_modelFactory == null)
                {
                    _modelFactory = new ModelFactory();
                }
                return _modelFactory;
            }
        }
    }

What we done here is adding read only property which is responsible to create an instance of the model factory class.

Before introducing changes to the “CoursesController” we need to fix the last two flaws in the previous implementation which they are:

  • Link each resource returned to a URI.
  • Returning HTTP status codes when returning single resource.

Fix the flaw in Linking each resource returned to a URI:

Returning URI for each resource is simple, thanks to the Model Factory pattern we implemented, so for example if we want to add URI to identify Course resource we need to do the following:

  1. Pass an instance of “HttpRequestMessage” to the “ModelFactory” constructor in order to create object of type “System.Web.Http.Routing.UrlHelper” which is responsible to formulate the URI link for this resource based on the “Route Name” we configured in class “WebApiConfig”.
  2. Pass “Request” object of type “System.Net.Http.HttpRequestMessage” in class “BaseApiController” to “ModelFactory” constructor.
  3. Add new property named “URL” to the “CourseModel” which will contain the URI for this resource.

Code listing as the below respecting points sequence:


public class ModelFactory
    {
        private System.Web.Http.Routing.UrlHelper _UrlHelper;

        public ModelFactory(HttpRequestMessage request)
        {
            _UrlHelper = new System.Web.Http.Routing.UrlHelper(request);
        }
    }

 


public class BaseApiController : ApiController
    {
		 private ModelFactory _modelFactory;

		 protected ModelFactory TheModelFactory
        {
            get
            {
                if (_modelFactory == null)
                {
                    _modelFactory = new ModelFactory(Request);
                }
                return _modelFactory;
            }
        }
    }

 


public class ModelFactory
    {
		public CourseModel Create(Course course)
        {
            return new CourseModel()
            {
                Url = _UrlHelper.Link("Courses", new { id = course.Id }),
                Id = course.Id,
                /*Other CourseModel properties remain the same*/
            };
        }
    }

There is a nice plural sight learning course produced by Shawn Wildermuth which discuss deeply this Model Factory Pattern. I recommend watching this course.

Fix the flaw in returning HTTP status codes when returning single resource

Web API framework contains class named “HttpResponseMessage” which can be used to return HTTP status code and data if needed, it is a good practice to return “HttpResponseMessage” objects because it gives us the flexibility to set response code and actual content, you will notice in the code below that we’ll be returning object of type “HttpResponseMessage” for action GetCourse(int id) instead of returning the actual Course domain object.

In the code listing below we’ll implement all the fixes we’ve discussed:


public class CoursesController : BaseApiController
    {
		public CoursesController(ILearningRepository repo)
            : base(repo)
        {
        }

		public IEnumerable<CourseModel> Get()
        {
            IQueryable<Course> query;

            query = TheRepository.GetAllCourses();

            var results = query
                          .ToList()
                          .Select(s => TheModelFactory.Create(s));

            return results;
        }

        public HttpResponseMessage GetCourse(int id)
        {
            try
            {
                var course = TheRepository.GetCourse(id);
                if (course != null)
                {
                    return Request.CreateResponse(HttpStatusCode.OK, TheModelFactory.Create(course));
                }
                else
                {
                    return Request.CreateResponse(HttpStatusCode.NotFound);
                }

            }
            catch (Exception ex)
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
            }
        }
    }

  • We’ve introduced multiple changes to “CoursesController” which they are:
  • Injected the “ILearningRepository” inside “CoursesController” constructor.
  • Using the model factory to create “CourseModel” and sub models “TutorModel” and “SubjectModel”.
  • Returning HTTP status codes for action GetCourse(int id), so if the course was not found we’ll return 404, in case of an exception we’ll return 400 (Bad request) along with the exception message, and if the course is found we’ll return 200 (OK) along with a serialized representation of “CourseModel” object found.

To test the new changes let’s issue a GET request the URI http://localhost:{your_port}/api/courses, and notice how each resource returned has a URL property, as well we have shaped the response returned and controlled the object graph to overcome circular reference serialization issue.

[
    {
        "id": 1,
        "url": "http://localhost:8323/api/courses/1",
        "name": "History Teaching Methods 1",
        "duration": 5,
        "description": "The course will talk in depth about: History Teaching Methods 1",
        "tutor": {
            "id": 1,
            "email": "Ahmad.Joudeh@outlook.com",
            "userName": "AhmadJoudeh",
            "firstName": "Ahmad",
            "lastName": "Joudeh",
            "gender": 0
        },
        "subject": {
            "id": 1,
            "name": "History"
        }
    },
    {
        "id": 2,
        "url": "http://localhost:8323/api/courses/2",
        "name": "History Teaching Methods 2",
        "duration": 4,
        "description": "The course will talk in depth about: History Teaching Methods 2",
        "tutor": {
            "id": 1,
            "email": "Ahmad.Joudeh@outlook.com",
            "userName": "AhmadJoudeh",
            "firstName": "Ahmad",
            "lastName": "Joudeh",
            "gender": 0
        },
        "subject": {
            "id": 1,
            "name": "History"
        }
    }
]

So in the next post we’ll cover how to implement the HTTP verbs (POST,PUT, and DELETE).

Source code is available on GitHub.


Building ASP.Net Web API RESTful Service – Part 5

$
0
0

This is the fifth part of Building ASP.Net Web API RESTful Service Series. The topics we’ll cover are:

Implement HTTP actions POST, PUT, and DELETE In Web API

In this post we’ll continue implementing the other HTTP actions for “CoursesController”, then discuss briefly what we’ll implement in “StudentsController”.

Create new Course using HTTP Post action

We’ll add new method named Post(CourseModel courseModel) to “CoursesController” as the implementation below:


public HttpResponseMessage Post([FromBody] CourseModel courseModel)
{
	try
	{
		var entity = TheModelFactory.Parse(courseModel);

		if (entity == null) Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Could not read subject/tutor from body");

		if (TheRepository.Insert(entity) && TheRepository.SaveAll())
                {
                    return Request.CreateResponse(HttpStatusCode.Created, TheModelFactory.Create(entity));
                }
                else
                {
                    return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Could not save to the database.");
                }
	}
	catch (Exception ex)
	{

		 return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
	}
}

In the above implementation we’ve to note four things:

  • Method named is “Post”, so the clients needs to issue HTTP Post request.
  • The method accepts parameter of type CourseModel, in Web API parameters with complex types are deserialized from the request body. So the client has to send a serialized representation of a CourseModel object in JSON format.
  • We’ve returned proper “HttpResponseMessange” for all possible scenarios that might happen when we execute this operation. In case the resource is created successfully, server should return HTTP response 201(Resource Created) along with the resource created. It is very important to return the resource created in response message because it will contain CourseId generated at the server.
  • We’ve introduced method named “Parse” in “ModelFactory” class which is responsible to parse the “CourseModel” back to the “Course” domain model object which can be added to our repository. You can use GitHub to browse the latest version of “ModelFactory” and “BaseApiController” classes in order to check the changes introduced to apply “Parse” function.

To test this we need to open fiddler and choose the Composer tab, we’ll issue a POST request to the URI: http://localhost:{your_port}/api/courses/ The request will look as the image below:

FiddlerPostRequest-Courses

In this HTTP POST request we need to note the following:

  • The “content-type” header is set to “application/json” because we are sending JSON data in request body.
  • The “accept” header is set to “application/json” because we are returning response in JSON format.
  • The request body contains deserialized JSON data of the complex “CourseModel”, as we mentioned before, each course has a tutor and related to subject, so sending the Ids for subject and tutor is enough because the “TheModelFactory.Parse” function is responsible to retrieve those objects from database and build valid domain object model which can be used with our repository.

If this POST request executed successfully at the server, and the a new course is created we’ll receive status code 201 (Resource Created) in response header along with the new course created on the server in response body. You can check the image blow:

FiddlerPostResponse-Courses

Update existing Course using HTTP PUT action

We’ll add new method named Put(int Id, CourseModel courseModel) to “CoursesController”, as the implementation below:


	[HttpPatch]
	[HttpPut]
	public HttpResponseMessage Put(int id, [FromBody] CourseModel courseModel)
	{
		try
		{

			var updatedCourse = TheModelFactory.Parse(courseModel);

			if (updatedCourse == null) Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Could not read subject/tutor from body");

			var originalCourse = TheRepository.GetCourse(id);

			if (originalCourse == null || originalCourse.Id != id)
			{
				return Request.CreateResponse(HttpStatusCode.NotModified, "Course is not found");
			}
			else
			{
				updatedCourse.Id = id;
			}

			if (TheRepository.Update(originalCourse, updatedCourse) && TheRepository.SaveAll())
			{
				return Request.CreateResponse(HttpStatusCode.OK, TheModelFactory.Create(updatedCourse));
			}
			else
			{
				return Request.CreateResponse(HttpStatusCode.NotModified);
			}

		}
		catch (Exception ex)
		{
			return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
		}
	}

In the above implementation we’ve to note the below:

  • Method named “PUT”, so the clients needs to issue HTTP PUT request, but we’ve added “HttpPatch” attribute to the Put method, so client can issue PUT or PATCH request and both will be executed using Put method. The difference between Put and Patch that if we want to update all fields of the “CourseModel” we need to use PUT, if we want to update partial fields we need to use PATCH, in our implementation we do not need to distinguish between those two actions.
  • Put method accepts two parameters, the Id of the updated resource which is set in URI, and the updated “CourseModel” which represents complex type deserialized in the request body.
  • We’ve returned proper “HttpResponseMessange” for all possible scenarios that might happen when we execute this operation. In case the resource is updated successfully, server should return HTTP response 200 (OK) along with the resource created. If the resource is not modified the server should return HTTP response 304 (Not modified).

To test this we need to use fiddler and choose the Composer tab, we’ll issue a PUT request to the URI: http://localhost:{your_port}/api/courses/33 The request will look as the image below:

FiddlerPutRequest-Courses

In this HTTP PUT request we need to note the following:

  • The “content-type” header is set to “application/json” because we are sending JSON data in request body.
  • The “accept” header is set to “application/json” because we are returning response in JSON format.
  • The request body contains deserialized JSON data of the updated “CourseModel”.

If this PUT request executed successfully at the server, and the course is updated we’ll receive status code 200 (OK) in response header along with the updated course on the server in response body.

Delete Course using HTTP DELETE action

We’ll add new method named Delete(int Id) to “CoursesController”, as the implementation below:


public HttpResponseMessage Delete(int id)
	{
		try
		{
			var course = TheRepository.GetCourse(id);

			if (course == null)
			{
				return Request.CreateResponse(HttpStatusCode.NotFound);
			}

			if (course.Enrollments.Count > 0)
			{
				return Request.CreateResponse(HttpStatusCode.BadRequest, "Can not delete course, students has enrollments in course.");
			}

			if (TheRepository.DeleteCourse(id) && TheRepository.SaveAll())
			{
				return Request.CreateResponse(HttpStatusCode.OK);
			}
			else
			{
				return Request.CreateResponse(HttpStatusCode.BadRequest);
			}

		}
		catch (Exception ex)
		{
			return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex.Message);
		}
	}

In the above implementation we’ve to note the below:

  • Method named “DELETE”, so the clients needs to issue HTTP DELETE request.
  • Delete method accepts  the Id parameter of the deleted course, Id is set in URI, and the request body is empty.
  • We’ve returned proper “HttpResponseMessange” for all possible scenarios that might happen when we execute this operation. In case the resource is deleted successfully, server should return HTTP response 200 (OK). If the deletion of the resource failed server should return HTTP response 400 (Bad request) with explanation content why the request failed to process.

To test this we need to use fiddler and choose the Composer tab, we’ll issue a DELETE request to the URI: http://localhost:{your_port}/api/courses/33 Notice that the body of the request is empty, the request will look as the image below:

FiddlerDeleteRequest-Courses

Adding Students Controller to the Project

The new controller “StudentsController” will be responsible to do CRUD operations on Students. The controller will be responsible for executing the actions below:

  • List all available students by sending GET request to URI: http://localhost:{your_port}/api/students/
  • List single student by sending GET request to URI: http://{your_port}/api/students/HasanAhmad Note that we are identifying resource by passing userName not Id here. This method is secured using basic authentication, so resource owner only can query his detailed information once he provide userName and password. We’ll cover this in details once we talk about Securing Web API.
  • Add new student by sending POST request to URI: http://localhost:{your_port}/api/students/
  • Update existing student by sending PUT/PATCH request to URI: http://localhost:{your_port}/api/students/{userName}
  • Delete student by sending DELETE request to URI: http://localhost:{your_port}/api/students/{userName}

I won’t list the code for “StudentsController” here as it is some how identical to “CoursesController”, you can browse it on GitHub. I will just list the new route configuration we’ve added to the “WebApiConfig” class.


	config.Routes.MapHttpRoute(
                name: "Students",
                routeTemplate: "api/students/{userName}",
                defaults: new { controller = "students", userName = RouteParameter.Optional }
            );

So in the next post we’ll cover how to implement Resources Association.

Source code is available on GitHub.


Building ASP.Net Web API RESTful Service – Part 6

$
0
0

This is the sixth part of Building ASP.Net Web API RESTful Service Series. The topics we’ll cover are:

Implement Resources Association

In this post we’ll be covering the relationship between resources which is called “Resources Association”, for example there is a relation between each “Course” and “Students” i.e. each course has multiple students enrolled in it. So we can build an absolute URI in the form:”api/courses/courseid/students/{userName}”, so if we want to list all students enrolled in course id 5 our GET request will be as: “api/courses/5/students/”. If we want to enroll student his username is “TaiseerJoudeh” in course id 5 we’ll issue POST request to the URI: ”api/courses/5/students/TaiseerJoudeh” and so on.

To implement this we need add new route in “WebApiConfig” class named “Enrollments” as the code below:


     config.Routes.MapHttpRoute(
         name: "Enrollments",
         routeTemplate: "api/courses/{courseId}/students/{userName}",
         defaults: new { controller = "Enrollments", userName = RouteParameter.Optional }
     );

Notice how is “courseId” parameter is not optional and “userName” parameter is optional.

Now we’ve to add new controller named “EnrollmentsController”, we’ll support two HTTP verbs, GET to list all students in specific class, and POST to enroll student in specific calls, you’ll notice that we’ve implemented pagination for GET method, we’ll cover this topic in the next post. The controller code listed as the below:


    public class EnrollmentsController : BaseApiController
    {
        public EnrollmentsController(ILearningRepository repo)
            : base(repo)
        {
        }

        public IEnumerable<StudentBaseModel> Get(int courseId, int page = 0, int pageSize = 10)
        {
            IQueryable<Student> query;

            query = TheRepository.GetEnrolledStudentsInCourse(courseId).OrderBy(s => s.LastName);

            var totalCount = query.Count();

            System.Web.HttpContext.Current.Response.Headers.Add("X-InlineCount", totalCount.ToString());

            var results = query
                        .Skip(pageSize * page)
                        .Take(pageSize)
                        .ToList()
                        .Select(s => TheModelFactory.CreateSummary(s));

            return results;

        }

        public HttpResponseMessage Post(int courseId, [FromUri]string userName, [FromBody]Enrollment enrollment)
        {
            try
            {

                if (!TheRepository.CourseExists(courseId)) return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Could not find Course");

                var student = TheRepository.GetStudent(userName);
                if (student == null) return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Could not find Student");

                var result = TheRepository.EnrollStudentInCourse(student.Id, courseId, enrollment);

                if (result == 1)
                {
                    return Request.CreateResponse(HttpStatusCode.Created);
                }
                else if (result == 2)
                {
                    return Request.CreateResponse(HttpStatusCode.NotModified, "Student already enrolled in this course");
                }

                return Request.CreateResponse(HttpStatusCode.BadRequest);

            }
            catch (Exception ex)
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
            }
        }
    }

In the POST method notice how we’re using FromUri and FromBody attribute to indicate from where we’re getting the values of the request, we’ll get the “userName” from the URI and the “enrollment” object from Request Body. The “enrollment” object will contain the enrollment data only, we could send the “CourseID” and “StudentID” as well, but it makes more sense to get both values from the URI.

To test the POST request we’ll use fiddler to issue a POST request, we want to enroll student “TaiseerJoudeh” in course with ID=5, the request will be as the image below:

FiddlerPostRequest-Enrollments

As we’ve learned before, we will return HTTP status code as a result for this POST operation, if the request is successful we will return 201 (Resource Created), if the student already enrolled in this class we’ll return status code 304 (Not modified).

In the next post we’ll talk about pagination for large results, using manual pagination, and how we return pagination meta-data.

Source code is available on GitHub.


Building ASP.Net Web API RESTful Service – Part 7

$
0
0

This is the seventh part of Building ASP.Net Web API RESTful Service Series. The topics we’ll cover are:

Implement Resources Pagination

In this post we’ll discuss the different ways to implement results pagination, we’ll implement manual pagination then format the response in two different ways (having pagination meta-data in an envelope, and in pagination header).

It is well known that overwhelming your server with a query which returns hundreds of thousand of records is a bad thing, when we are designing an API, we should consider returning the results of our GET methods in paginated way, i.e. providing 10 results on each request, and giving the API consumer the ability to navigate through results, specify the size of the page,  and which page he wants.

Manual Pagination and Envelopes

We’ll modify the “CoursesController” to use pagination instead of returning the whole courses at once.

Let’s see the code below:


   public Object Get(int page = 0, int pageSize = 10)
        {
            IQueryable<Course> query;

            query = TheRepository.GetAllCourses().OrderBy(c => c.CourseSubject.Id);
            var totalCount = query.Count();
            var totalPages = (int)Math.Ceiling((double)totalCount / pageSize);

            var urlHelper = new UrlHelper(Request);
            var prevLink = page > 0 ? urlHelper.Link("Courses", new { page = page - 1 }) : "";
            var nextLink = page < totalPages - 1 ? urlHelper.Link("Courses", new { page = page + 1 }) : "";

            var results = query
                          .Skip(pageSize * page)
                          .Take(pageSize)
                          .ToList()
                          .Select(s => TheModelFactory.Create(s));

            return new
            {
                TotalCount = totalCount,
                TotalPages = totalPages,
                PrevPageLink = prevLink,
                NextPageLink = nextLink,
                Results = results
            };

        }

What we’ve done here is simple, we’ve introduced the below to “CoursesController”

    • Added two new optional parameters to the GET method with default values, those optional parameters are translated to query string values, i.e. if we want to request the second page of courses our GET request will be on the form: http://localhost:{your_port}/api/courses/?page=1 Notice we didn’t specify the pageSize parameter and it took the default values 10. Sample of response will be on the form below:

{

    "totalCount": 33,
    "totalPages": 4,
    "prevPageLink": "http://localhost:8323/api/courses?page=0&pageSize=10",
    "nextPageLink": "http://localhost:8323/api/courses?page=2&pageSize=10",
    "results": [ /* Array containts the results*/ ]

}

  • The method “GetAllCourses” in our Repository returns “IQueryable” response, which is perfect because till this moment the query is represented in memory and didn’t execute against SQL server, so paging and order by for query are executing correctly.
  • We’re using envelope to wrap our response, this envelope contains pagination meta-data inside the JSON response such as: totalCount, totalPages, prevPageLink, nextPageLink. It is important to return the total records count and total pages so API consumer will be able to bind results and apply pagination on grid easily.

Returning the pagination meta-data in the response body is a common technique, there is nothing wrong about it as everything is visible for the developer, the draw back of this approach is that API consumer will dig into the response to extract data he was originally asking for and maybe ignoring all the pagination meta data we returned if he do not need to use it. So the other cleaner way to return pagination meta-data is to include them in response header, so we’ll keep the response body for the results only and we’ll add new header called “X-Pagination” which contains all pagination meta-data.

Manual Pagination and Pagination Headers

We’ll modify “StudentsController” to use headers to return pagination meta-data, in this approach API consumer can use this header if he is interested in the pagination meta-data, other wise he can just ignore this header and read the results of the query directly from response body.

Applying this is fairly simple, the pagination technique we used in “CoursesControrler” will be used the same here, except for returning the pagination meta-data in new header. Take a look on the code below:


public IEnumerable<StudentBaseModel> Get(int page = 0, int pageSize = 10)
        {
            IQueryable<Student> query;

            query = TheRepository.GetAllStudentsWithEnrollments().OrderBy(c => c.LastName);

            var totalCount = query.Count();
            var totalPages = (int)Math.Ceiling((double)totalCount / pageSize);

            var urlHelper = new UrlHelper(Request);
            var prevLink = page > 0 ? urlHelper.Link("Students", new { page = page - 1, pageSize = pageSize }) : "";
            var nextLink = page < totalPages - 1 ? urlHelper.Link("Students", new { page = page + 1, pageSize = pageSize }) : "";

         var paginationHeader =  new
                                  {
                                      TotalCount = totalCount,
                                      TotalPages = totalPages,
                                      PrevPageLink = prevLink,
                                      NextPageLink = nextLink
                                  };

             System.Web.HttpContext.Current.Response.Headers.Add("X-Pagination",
                                                                 Newtonsoft.Json.JsonConvert.SerializeObject(paginationHeader));

            var results = query
                        .Skip(pageSize * page)
                        .Take(pageSize)
                        .ToList()
                        .Select(s => TheModelFactory.CreateSummary(s));

              return results;
        }

Notice how we added a new header to the response collection headers which contains a serialized JSON object containing all pagination meta-data.

In the next post we’ll talk briefly about web API security and how we can implement Basic authentication.

Source code is available on GitHub.



Building ASP.Net Web API RESTful Service – Part 8

$
0
0

This is the eight part of Building ASP.Net Web API RESTful Service Series. The topics we’ll cover are:

Securing Web API

In this post we’ll talk about securing our eLearning API, till this moment all requests sent from client to the API are done over HTTP protocol (http://) and the communication is not encrypted, but in this post we’ll implement authentication feature in “StudentsController” so we’ll be sending Username and Password for authenticating students. It is well known that transmitting confidential information should be done using secure HTTP (https://).

Enforce HTTPS for Web API

We can enforce HTTPS on the entire Web API by configuring this on IIS level, but in some scenarios you might enforce HTTPS on certain methods where we transmit confidential information and use HTTP for other methods.

In order to implement this we need to use Web API filters; basically filters will allow us to execute some code in the pipeline before the execution of code in controller methods. This new filter will be responsible to examine if the URI scheme is secured, and if it is not secure, the filter will reject the call and send response back to the client informing him that request should be done over HTTPS.

We’ll add a new filter which derives from “AuthorizationFilterAttribute”, this filter contains an overridden method called “OnAuthorization” where we can inject a new response in case the request is not done over HTTPS.

Let’s add new folder named “Filters” to project root then add new class named “ForceHttpsAttribute” which derives from “System.Web.Http.Filters.AuthorizationFilterAttribute”

The code for the filter class will be as the below:


public class ForceHttpsAttribute : AuthorizationFilterAttribute
    {
        public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            var request = actionContext.Request;

            if (request.RequestUri.Scheme != Uri.UriSchemeHttps)
            {
                var html = "<p>Https is required</p>";

                if (request.Method.Method == "GET")
                {
                    actionContext.Response = request.CreateResponse(HttpStatusCode.Found);
                    actionContext.Response.Content = new StringContent(html, Encoding.UTF8, "text/html");

                    UriBuilder httpsNewUri = new UriBuilder(request.RequestUri);
                    httpsNewUri.Scheme = Uri.UriSchemeHttps;
                    httpsNewUri.Port = 443;

                    actionContext.Response.Headers.Location = httpsNewUri.Uri;
                }
                else
                {
                    actionContext.Response = request.CreateResponse(HttpStatusCode.NotFound);
                    actionContext.Response.Content = new StringContent(html, Encoding.UTF8, "text/html");
                }

            }
        }
    }

By looking at the code above we are using “actionContext” parameter to get the request and response object from it. What we are doing here is examining the URI scheme of the request, so if it is not secure (http://) we need to return small html message in the response body informing client to send the request again over https.

As well we are differentiating between the GET method, and other methods (POST, PUT, DELETE); because in case the client initiated a GET request to existing resource over http we need to construct the same request again using https scheme and use 443 SSL port then inject this secure URI in response location header. By doing this the client (browser) will initiate automatically another GET request using https scheme .

In case of non GET requests, we will return 404 status code (Not Found) and small html message informing client to send the request again over https.

Now if we want to enforce this filter over the entire Web API we need to add this filter globally in “WebAPIConfig” class as the code below:


public static void Register(HttpConfiguration config)
   {
       config.Filters.Add(new ForceHttpsAttribute());
   }

But if we want to enforce HTTPS for certain methods or certain controllers we can add this filter attribute “ForceHttps” as the below:


        //Enforce HTTPS on the entire controller
 	[Learning.Web.Filters.ForceHttps()]
        public class CoursesController : BaseApiController
        {
		//Enforce HTTPS on POST method only
	        [Learning.Web.Filters.ForceHttps()]
                public HttpResponseMessage Post([FromBody] CourseModel courseModel)
                {

	        }
	}

Authenticate Users using Basic Authentication

Until this moment all methods in our API are public, and any user on the internet is able to request any resource, but in real life scenario this is not correct, specific data should be accessed by specific people, so we need to authenticate requests on certain resources. A good candidates in our sample API for clients authentications are:

  1. Clients who make a GET request to the URI “http://{your_port}/api/students/{userName}“. This means that if a client issue a request to GET detailed information about student with username “TaiseerJoudeh”, then he needs to provide the username and password for this resource in the request to authenticate him self. As well we won’t allow authenticated user “TaiseerJoudeh” to GET detailed information for another resource because he is not the resource owner and he shouldn’t be able to see his detailed information such as Email, Birth date, classes enrolled in, etc…
  2. Clients who make a POST request the URI “http://{your_port}/api/courses/2/students/{userName}“. This method is used to enroll specific student in specific class, it makes sense to authenticate requests here because if student with username “KhaledHassan” wants to enroll in course with Id 2, then he needs to authenticate himself by providing username and password. Otherwise anyone will be able to enroll any student in any class.

In our scenario we’ll use the Basic Authentication to authenticate users requesting the above two resources, to do so we need to add new Web API filter which will be responsible to read authorization data from request header, check if the authentication type is “basic”, validate credentials sent in the authorization headers, and finally authenticate user if all is good. Otherwise it will return a response with status code 401 (Unauthorized) and it won’t return the resource.

Before digging into the code, let’s talk a little bit about basic authentication.

What is Basic Authentication?

It provides a mean to authenticate the sender of the request before actually processing the HTTP request. This will protect the server against Denial of service attacks (DoS). The way it works that the client who is initiating the HTTP request provides a username and password which is base64-encoded and placed in the HTTP header as string on the form “username:password”, the recipient of the message (server) is expected to first authenticate the credentials and process the request further only when the authentication is successful.

As the username and password are only base64-encoded and to avoid passwords are exposed to others, Basic Authentication should be always used over SSL connection (HTTPS).

To apply this in our API let’s add new class named “LearningAuthorizeAttribute” which derives from “System.Web.Http.Filters.AuthorizationFilterAttribute”


public class LearningAuthorizeAttribute : AuthorizationFilterAttribute
    {

        [Inject]
        public LearningRepository TheRepository { get; set; }

        public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            //Case that user is authenticated using forms authentication
            //so no need to check header for basic authentication.
            if (Thread.CurrentPrincipal.Identity.IsAuthenticated)
            {
                return;
            }

            var authHeader = actionContext.Request.Headers.Authorization;

            if (authHeader != null)
            {
                if (authHeader.Scheme.Equals("basic", StringComparison.OrdinalIgnoreCase) &&
                    !String.IsNullOrWhiteSpace(authHeader.Parameter))
                {
                    var credArray = GetCredentials(authHeader);
                    var userName = credArray[0];
                    var password = credArray[1];

                    if (IsResourceOwner(userName, actionContext))
                    {
                        //You can use Websecurity or asp.net memebrship provider to login, for
                        //for he sake of keeping example simple, we used out own login functionality
                        if (TheRepository.LoginStudent(userName, password))
                        {
                            var currentPrincipal = new GenericPrincipal(new GenericIdentity(userName), null);
                            Thread.CurrentPrincipal = currentPrincipal;
                            return;
                        }
                    }
                }
            }

            HandleUnauthorizedRequest(actionContext);
        }

        private string[] GetCredentials(System.Net.Http.Headers.AuthenticationHeaderValue authHeader)
        {

            //Base 64 encoded string
            var rawCred = authHeader.Parameter;
            var encoding = Encoding.GetEncoding("iso-8859-1");
            var cred = encoding.GetString(Convert.FromBase64String(rawCred));

            var credArray = cred.Split(':');

            return credArray;
        }

        private bool IsResourceOwner(string userName, System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            var routeData = actionContext.Request.GetRouteData();
            var resourceUserName = routeData.Values["userName"] as string;

            if (resourceUserName == userName)
            {
                return true;
            }
            return false;
        }

        private void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);

            actionContext.Response.Headers.Add("WWW-Authenticate",
                                               "Basic Scheme='eLearning' location='http://localhost:8323/account/login'");

        }
    }

In the code above we’ve overridden method “OnAuthorization” and implemented the below:

  1. Getting the authorization data from request headers
  2. Making sure that authorization header scheme is set to “basic” authentication and contains base64-encoded string.
  3. Converting the base64-encoded string to a string on the form “username:password” and get the username and password.
  4. Validating that username sent in authentication header is the same for username in URI to ensure that resource owner only able to view his details.
  5. Validating the credentials against our database.
  6. If the credentials are correct we set the identity for current principal, so in sub subsequent requests the user already authenticated.
  7. If the credentials are incorrect the server sends an HTTP response with a 401 status code (Unauthorized), and a WWW-Authenticate header. Web clients (browser) handle this response by requesting a user ID and password from client.

Now to apply basic authentication on the two methods we mentioned earlier, all we need to do is to add this attribute “LearningAuthorizeAttribute” to those methods as the code below:


public class StudentsController : BaseApiController
    {
	    [LearningAuthorizeAttribute]
		public HttpResponseMessage Get(string userName)
			{

			}
    }


public class EnrollmentsController : BaseApiController
    {
		[LearningAuthorizeAttribute]
		public HttpResponseMessage Post(int courseId, [FromUri]string userName, [FromBody]Enrollment enrollment)
			{

			}
	}

Now we need to test authentication by sending GET request to URI: “http://localhost:{your_port}/api/students/TaiseerJoudeh” using two different clients, Firefox and Fiddler.

Testing user Firefox:

We’ll issue get request using the browser and the response returned will be 401 because we didn’t provide username and password and “Authentication Required” prompt will be displayed asking for the username and password. By providing the the correct credentials we’ll receive status code 200 along with complete JSON object graph which contains all specific data for for this user. For any sub subsequent request for the same resource the code will not check credentials because we have created principal for this user and he is already authenticated.

Testing using Fiddler:

By using fiddler we need to create the base64-encoded string which contains the “username:password” and send it along with the authorization header, to generate this string we will use http://www.base64encode.org/ as the image below:

Web API Basic Authentication

Note that this is not encryption at all, so as we stated earlier, using Basic Authentication should be done over SSL only.

Now we will use the encoded string to pass it in authorization header “Authorization: Basic VGFpc2VlckpvdWRlaDpZRUFSVkZGTw==” the request will be as the image below:

Web API Basic Authorization Header

The response code will be 200 OK and will receive the specific data for this authenticated user.

In the next post we’ll talk about versioning Web API and how we can implement different techniques to implement versioning.

Source code is available on GitHub.


Building ASP.Net Web API RESTful Service – Part 9

$
0
0

This is the ninth part of Building ASP.Net Web API RESTful Service Series. The topics we’ll cover are:

Preparing Web API for Versioning

Once you publish your successful API, consumers will start depending on it and your exposed data will be used and integrated with other data in different ways, but it is known that change is inevitable and new requirements and changes will evolve, if you are lucky you will be able to adopt those changes without introducing any breaking changes for existing clients, but this is not the case always.

So our API needs to change and we have to start building different versions from our API to handle those changes without affecting existing consumers. We need to run the new version concurrently with older version of the API to give consumers enough time to migrate to the latest version, in some cases multiple versions of the API can live forever side by side.

There are multiple ways to version your API, each way has it is own pros and cons, in this post and the coming one we’ll cover versioning by URI, query string, custom header, and by accept header.

Introducing a change and preparing our API

In our case and for keeping things simple we’ll introduce a breaking change on GET method in the “StudentsController” so we’ll return “FullName” and “CoursesDuration” in response body instead of “FirstName” and “LastName” properties.

The simplest way I found in versioning your API is to create an identical controller of “StudentsController” and name it “StudentsV2Controller”, notice the suffix V2 in controller name, we’ll depend on this part to select the appropriate controller based on API version. Now in this controller we’ll introduce our breaking changes on GET method and we keep other HTTP verbs the same as we didn’t introduce any change on them.

Special thanks goes to Shawn Wildermuth for describing this simple yet effective technique for API versioning in his plural sight course.

Currently the JSON response for GET method in “StudentsController” as below:

[
    {
        "id": 2,
        "url": "http://localhost:8323/api/students/HasanAhmad",
        "firstName": "Hasan",
        "lastName": "Ahmad",
        "gender": 0,
        "enrollmentsCount": 4
    },
    {
        "id": 3,
        "url": "http://localhost:8323/api/students/MoatasemAhmad",
        "firstName": "Moatasem",
        "lastName": "Ahmad",
        "gender": 0,
        "enrollmentsCount": 4
    }
]

Now we want to achieve the below JSON response when calling the GET method in our new “StudentsV2Controller”:

[
	{
        "id": 2,
        "url": "http://localhost:8323/api/students/HasanAhmad",
        "fullName": "Hasan Ahmad",
        "gender": 0,
        "enrollmentsCount": 4,
        "coursesDuration": 13
    },
    {
        "id": 3,
        "url": "http://localhost:8323/api/students/MoatasemAhmad",
        "fullName": "Moatasem Ahmad",
        "gender": 0,
        "enrollmentsCount": 4,
        "coursesDuration": 16
    }
]

Now let’s copy and paste the existing controller “StudnetsController” and rename the new one to “StudentsV2Controller”, we need to change the GET implementation as the code below:

public IEnumerable<StudentV2BaseModel> Get(int page = 0, int pageSize = 10)
	{
		IQueryable<Student> query;

		query = TheRepository.GetAllStudentsWithEnrollments().OrderBy(c => c.LastName);

		var totalCount = query.Count();
		var totalPages = Math.Ceiling((double)totalCount / pageSize);

		var urlHelper = new UrlHelper(Request);
		var prevLink = page > 0 ? urlHelper.Link("Students", new { page = page - 1, pageSize = pageSize }) : "";
		var nextLink = page < totalPages - 1 ? urlHelper.Link("Students", new { page = page + 1, pageSize = pageSize }) : "";

		var paginationHeader = new
			 {
				 TotalCount = totalCount,
				 TotalPages = totalPages,
				 PrevPageLink = prevLink,
				 NextPageLink = nextLink
			 };

		System.Web.HttpContext.Current.Response.Headers.Add("X-Pagination",
															 Newtonsoft.Json.JsonConvert.SerializeObject(paginationHeader));

		var results = query
					.Skip(pageSize * page)
					.Take(pageSize)
					.ToList()
					.Select(s => TheModelFactory.CreateV2Summary(s));

		return results;
	}

The code above is almost the same as the GET method in “StudentsController”, the only change we did is returning a new response type “StudentV2BaseModel” by calling the new method “CreateV2Summary” in the “ModelFactory” class. The code below lists the new Data Model “StudentV2BaseModel” and the new function “CreateV2Summary”. Note that V2 suffix in the model name and function name are not mandatory to implement versioning, you can name those anything you want.


public class StudentV2BaseModel
{
	public int Id { get; set; }
	public string Url { get; set; }
	public string FullName { get; set; }
	public Data.Enums.Gender Gender { get; set; }
	public int EnrollmentsCount { get; set; }
	public double CoursesDuration { get; set; }
}

public class ModelFactory
{
	public StudentV2BaseModel CreateV2Summary(Student student)
	{
		return new StudentV2BaseModel()
		{
			Url = _UrlHelper.Link("Students", new { userName = student.UserName }),
			Id = student.Id,
			FullName = string.Format("{0} {1}", student.FirstName, student.LastName),
			Gender = student.Gender,
			EnrollmentsCount = student.Enrollments.Count(),
			CoursesDuration = Math.Round(student.Enrollments.Sum(c=> c.Course.Duration))
		};
	}
}

Now we have prepared our “Students” resource to be versioned, in the next post we will start implementing different techniques for versioning.

Source code is available on GitHub.


Building ASP.Net Web API RESTful Service – Part 10

$
0
0

This is the tenth part of Building ASP.Net Web API RESTful Service Series. The topics we’ll cover are:

Different techniques to Implement Versioning

In this post we’ll discuss four different techniques for API versioning, we’ll start with the most common one which is versioning using URI, then we’ll cover versioning using query string, custom header, and finally using accept header.

Web API Versioning using URI

Including the version number in the URI considers the most common way of versioning, so we can consume a resource by calling http://localhost:{your_port}/api/v1/students/ (client wants to use version 1 of the API) or http://localhost:{your_port}/api/v2/students/ (client wants to use version 2 of the API).

The advantage of this technique that clients know which version they are using. To implement this we need to add two new routes inside the Register method in “WebApiConfig” class as the code below:


	config.Routes.MapHttpRoute(
		  name: "Students",
		  routeTemplate: "api/v1/students/{userName}",
		  defaults: new { controller = "students", userName = RouteParameter.Optional }
	   );

	config.Routes.MapHttpRoute(
	   name: "Students2",
	   routeTemplate: "api/v2/students/{userName}",
	   defaults: new { controller = "studentsV2", userName = RouteParameter.Optional }
   );

Notice in the code above how we added two new routes and mapped each route with it is corresponding controller. i.e. Route named “Students2″ is by default mapped to controller “studentsV2″. In future if we want to add version “V3″ then we need to add new route to select the appropriate controller, this might get messy over time.

The drawbacks for this technique that it is not compliance with REST specification because the URI will keep changing by time, as well we need to keep maintaining new routes once we introduce a new version.

Before we jump and discuss the implementation of the other three techniques we need to take a look on how Web API selects the appropriate controller based on the information sent with the request.

Web API uses a method named “SelectController” in class”DefaultHttpControllerSelector”, this method accept “HttpRequestMessage” object which contains a key/value pair of route data including controller name which is defined in class “WebApiConfig”. Based on this information and by doing reflection on all classes which derives from “ApiController” class, Web API can match the controller name with the appropriate class, if there is a duplicate or class is not found, then an exception will be thrown.

To override this default implementation we need to add new class named “LearningControllerSelector” which derives from class “Http.Dispatcher.DefaultHttpControllerSelector”, then we need to override the method “SelectController”, let’s take a look on the code below:


public class LearningControllerSelector : DefaultHttpControllerSelector
{
	private HttpConfiguration _config;
	public LearningControllerSelector(HttpConfiguration config)
		: base(config)
	{
		_config = config;
	}

	public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
	{
	   var controllers =  GetControllerMapping(); //Will ignore any controls in same name even if they are in different namepsace

	   var routeData = request.GetRouteData();

	   var controllerName = routeData.Values["controller"].ToString();

	   HttpControllerDescriptor controllerDescriptor;

	   if (controllers.TryGetValue(controllerName, out controllerDescriptor))
	   {

		   var version = "2";

		   var versionedControllerName = string.Concat(controllerName, "V", version);

		   HttpControllerDescriptor versionedControllerDescriptor;
		   if (controllers.TryGetValue(versionedControllerName, out versionedControllerDescriptor))
		   {
			   return versionedControllerDescriptor;
		   }

		   return controllerDescriptor;
	   }

	   return null;

	}
}

What we have done here is:

  1. Getting a dictionary of all classes (API Controllers) which derives from “ApiController” class by calling method “GetControllerMapping()”.
  2. Retrieving the route data from the request “request.GetRouteData()” then looking for the controller name in this request.
  3. Trying to get an object of type “HttpControllerDescriptor” based on the controller name we retrieved from the request. The HttpControllerDescriptor objects will contain information that describes the selected controller.
  4. If we found the controller, then we will try to find a versioned controller on the form “ControllerNameV2” using the same technique we used in the previous step. We will cover now how we will get the version number, but for now we can fix it to “2″.

Now we need to use this custom “Controller Selector” we’ve implemented instead of the default one, we can do this by adding the code below inside “Register” method in class “WebApiConfig”


config.Services.Replace(typeof(IHttpControllerSelector), new LearningControllerSelector((config)));

Now we will implement versioning by sending the version number with the request object:

Web API Versioning using Query String

Versioning API by query string is straight forward, we will add query parameter such as “?v=2″ to the URI, the request will be as: http://localhost:{your_port}/api/students/?v=2

We will assume that clients who didn’t provide the version in query string want the oldest version (v=1).

To implement this we’ll add method named “GetVersionFromQueryString” which accepts the “Request” object where we can read query string from it and decide which version client wants. Method will be added to class “LearningControllerSelector”


private string GetVersionFromQueryString(HttpRequestMessage request)
	{
		var query = HttpUtility.ParseQueryString(request.RequestUri.Query);

		var version = query["v"];

		if (version != null)
		{
			return version;
		}

		return "1";

	}

We’ve to call this method inside method “SelectController” to read the version number and select the appropriate controller. The only drawback for this technique is that URI will keep changing by time and this is not compliance with REST specifications.

API Versioning by Custom Header

Now will try another approach where the version is set in the header request not as a part of the URI, we will add our custom header named “X-Learning-Version” and set the version there. We’ll assume that clients who didn’t provide the header value are requesting the oldest version of the API (Version 1), to implement this we need to add new function named “GetVersionFromHeader” to “LearningControllerSelector” class as the code below:


private string GetVersionFromHeader(HttpRequestMessage request)
	{
		const string HEADER_NAME = "X-Learning-Version";

		if (request.Headers.Contains(HEADER_NAME))
		{
			var versionHeader = request.Headers.GetValues(HEADER_NAME).FirstOrDefault();
			if (versionHeader != null) {
				return versionHeader;
			}
		}

		return "1";
	}

Basically what we have done here is simple, we hard-coded the custom header name, and checked if the headers collection contains this name, if so we tried to get the value from this header.

To test this out we need to issue GET request using fiddler as the image below, note how we added the new header “X-Learning-Version” to request header collection:

API Version by Custom Header

The only drawback for this technique is that we are introducing new custom header to the headers collection, we can version by headers using the Accept Header without introducing new custom header as we’ll see in fourth technique below.

API Versioning using Accept Header

In this approach we’ll version by using the “Accept” header. Out GET request accept header will be on form: “Accept:application/json; version=2″.

We’ll assume that clients who didn’t provide the version value in accept header are requesting the oldest version of the API (Version 1), to implement this we need to add new function named “GetVersionFromAcceptHeaderVersion” to “LearningControllerSelector” class as the code below:


private string GetVersionFromAcceptHeaderVersion(HttpRequestMessage request)
{
	var acceptHeader = request.Headers.Accept;

	foreach (var mime in acceptHeader)
	{
		if (mime.MediaType == "application/json")
		{
			var version = mime.Parameters
			.Where(v => v.Name.Equals("version", StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

			if (version != null)
			{
				return version.Value;
			}
			return "1";
		}
	}
	return "1";
}

In the code above we are looping on all header values collection and examining if the media type is “application/json”, if this is the case then we get the value of the parameter named “version”.

To test this out we need to issue GET request using fiddler as the image below, note how we added version parameter to the “Accept” header:

Web API Version by Accept header

This is more standard way of API versioning because we didn’t add new custom header, and we didn’t version the API by changing the URI.

If you have plural sight subscription; I highly recommend watching this course where Shawn Wildermuth covers another ways for API versioning.

In the next post we’ll talk about resources cashing using Entity Tags.

Source code is available on GitHub.


Building ASP.Net Web API RESTful Service – Part 11

$
0
0

This is the eleventh part of Building ASP.Net Web API RESTful Service Series. The topics we’ll cover are:

Caching resources using CacheCow and ETag

In this post we’ll discuss how we can implement resource caching by using an open source framework for HTTP caching on the client and server, this framework is called CacheCow. It is created by Ali Kheyrollahi, we’ll cover in this post the server side caching.

API Source code is available on GitHub.

Using resource caching will enhance API performance, reduce the overhead on the server, and minimize the response size.

The form of caching we want to achieve here called Conditional Requests, the idea is pretty simple; the client will ask the server if it has an updated copy of the resource by sending some information about the cached resources it holds using a request header called ETag, then the server will decide weather there is an updated resource that should be returned to the client, or the client has the most recent copy, so if the client has the most recent copy the server will return HTTP status 304 (Not modified) without the resource content (empty body). By using Conditional Requests the client will send HTTP requests always to the server but the added value here that the server will only return full response 200 (OK) including resource content within the body only if the client has stale copy of the resource.

So what is ETag (Entity Tag)?

ETag is a unique key (string) generated at the server for particular resource, you can think of it as check-sum for a resource that semantically changes when the resource has updated.

ETag has two types, weak, and strong. The value of weak ETag is prefixed by W, i.e. ETag: “W/53fsfsd322″ and the strong ETag is not prefixed with anything, i.e. ETag: “534928jhfr4″. usually Weak ETags indicates that the cached resource is useful to be used for short time (In memory caching) and the strong ETag means that the resource caching is implemented using persistence storage and the content of the both resources (client and server) are identical byte for byte.

How ETags work?

By looking on the illustration below we will notice that at the beginning the client initiate HTTP GET request asking for the course with Id: 4 assuming that that this resource has not requested before, then the server will respond by returning the resource in the response body along with a generated ETag in the response header.

Now the client wants to request the same resource again (Course id: 4) by sending another HTTP GET, assuming that the client is interested in using caching, then the GET request initiated will include a header called If-None-Match with the value of the ETag for this resource, once the server receives this request it will read the ETag value and compare it with the ETag value saved on the server, if they are identical then the server will send HTTP status 304 (Not modified) without the resource content (empty body) and the client will know that it has the most recent copy of the resource.

For HTTP GET and DELETE we can use the header If-None-Match, but when updating a resource and we want to use ETags we have to send the header If-Match with the HTTP PUT/PATCH requestso the server will examine the ETag and if they are different; the server will respond with HTTP Status 412 (Precondition Failed) so the client knows that there is a fresher version of the resource on the server and the update won’t take place until the client has the same resource version on the server.

WebApiCachingETag

Configuring Web API to use CacheCow

After we had a brief explanation of how conditional requests and ETags work let’s implement this feature in our Web API.

Now we need to Install CacheCow server from NuGet, so open NuGet package manager console and type “Install-Package CacheCow.Server -Version 0.4.12” this will install two dlls, the  server version and common dll.

Configuring CacheCow is pretty easy, all we need to do is to create Cache Handler and inject it into the Web API pipeline, this this handler will be responsible to inspect each request and response coming to our API by looking for ETags and Match headers and do the heavy lifting for us.

To implement this open the file “WebApiConfig.cs” and at the end of the file add the below line of codes:

//Configure HTTP Caching using Entity Tags (ETags)
var cacheCowCacheHandler = new CacheCow.Server.CachingHandler();
config.MessageHandlers.Add(cacheCowCacheHandler);

Till this moment we have configured our API to use In-memory caching; this is the default configuration for CacheCow, this will be fine if you have a single server or for demo purposes, but in case of load balancers and web farms, the cache state should be persisted for the whole farm in single place and all web servers should be aware of this cache. In this case we need to configure CaschCow to use persistence medium (SQL Server, MongoDB, MemCache). But before moving to persistence store let we test the in-memory caching.

Cache Cow in-memory caching:

To test this we need to open fiddler and choose the Composer tab, we’ll issue a GET request to the URI: http://localhost:{your_port}/api/courses/4 The request will look as the image below:

CacheCowGet-WeakeTag

In this GET request we need to note the following:

  • The HTTP status response is 200 OK which means that server returned the resource content in the response body.
  • New two headers are added to the response which they are eTag and Last-Modified, we are interested here on the eTag value and we’ll get rid off the Last-Modified header later on as we’ll send conditional requests using eTag only.
  • The value of the eTag is weak (Prefixed with W) because we are using in-memory caching for now, in other words if we restarted IIS or shutdown its worker process all eTag values the client saving are useless.

Now after receiving the eTag header value, the client is responsible to send this value along with any subsequent requests for the same resource, the client will use the header “If-None-Match” when sending the request and the server will respond by HTTP status 304 with empty response body if the requested resource has not changed, other wise it will return 200 OK with new eTag value and resource content in the response body. To examine this let we open fiddler and issue GET request to the same resource (Course with Id: 4) as the image below:

CacheCow-WeakeTag-Response

In this GET request we need to note the following:

  • The HTTP status response is 304 Not modified which means that server returned empty body and the copy of the resource at client side is the latest.
  • The same eTag header value is returned in the response.

Now let’s move to configure CacheCow to use persistence caching medium (SQL Server) instead of in-memory caching.

Cache Cow persistence caching using SQL Server:

Configuring CacheCow to use SQL server is easy we need to install NuGet package which works with the medium we want to use, in our case SQL server, so open NuGet package manager console and type:  ”Install-Package CacheCow.Server.EntityTagStore.SqlServer -Version 0.4.11“, this will install the requiered dlls.

Now open the file “WebApiConfig.cs” again paste the code snippet below:

//Configure HTTP Caching using Entity Tags (ETags)
var connString = System.Configuration.ConfigurationManager.ConnectionStrings["eLearningConnection"].ConnectionString;
var eTagStore = new CacheCow.Server.EntityTagStore.SqlServer.SqlServerEntityTagStore(connString);
var cacheCowCacheHandler = new CacheCow.Server.CachingHandler(eTagStore);
cacheCowCacheHandler.AddLastModifiedHeader = false;
config.MessageHandlers.Add(cacheCowCacheHandler);

What we implemented above is obvious, CacheCow needs to store caching information in SQL server, so we need to inform which database to use, in our case we’ll put this caching information in the same database of the API “eLearning”. Then we need to pass the SQL server eTagStore instance to the caching handler. As well we’ve turned off adding last modified header to the response because we are interested in eTag values only.

If you directly tried to issue any request against our API you will receive 500 error (Internal Server Error) because as we mentioned before CacheCow needs to store information about the cached resource on the server, this means it needs a table and some stored procedures to manipulate this table, so we need run SQL script before we go on. To do this navigate to the path where you NuGet packages are installed, usually they are on “{projectpath}packagesCacheCow.Server.EntityTagStore.SqlServer.0.4.11scripts“, open the file named “script.sql” and execute all its content against your local eLearning Database.

After running the script navigate to SQL server explorer and open eLearning database, you will notice that this script created a table named “CacheState” and another five stored procedures mainly used for manipulating this table.

To test this out we need to issue the same GET request as the image below:

CacheCow-StrongETag-Request

As you notice from the above image, the ETag value now is not weak, it is strong because we persisted it on SQL server, so if we opened the table “CacheState” you will notice that CacheCow has inserted new record including the ETag value, Route Pattern, Last Modified date, and binary hash key as the image below:

CacheCow-CacheStateTable

Now if the client sends any subsequent requests to the same resource, the same ETag value will be returned as long as no other clients updated the resource by issuing HTTP PUT/PATCH on the same resource.

So if the client includes this ETag value within the If-None-Match header then the server will respond by 304 HTTP status.

Now let’s simulate the update scenario, the client will issue HTTP PUT on the resource (Course with Id 4) including the ETag value in the header If-Match along with the request as the image below:

CacheCow-PUT-StrongETag

In this PUT request we need to note the following:

  • The HTTP status response is 200 OK which means that client has the most recent copy of the resource and the update of the resource has took place successfully.
  • New ETag has been returned in the response because the resource has been changed on the server, so the client is responsible to save this new ETag for any subsequent requests for the same resource.
  • The new ETag value and last modified date has been updated in table “CacheStore” for this resource.

Now if we directly tried to issue another PUT request using the old ETag (8fad5904b1a749e1b99bc3f5602e042b) we will receive HTTP Status 412 (Precondition Failed) which means that updating the resource has failed because the client doesn’t have the latest version of the resource. Now client needs to issue GET request to get the latest version  of the resource and the new generated ETag (ad508f75c5144729a1563a4363a7a158), let’s test this as the image below:

CacheCow-If-Match-PreconditionFailed

That’s all for now!

I hope you liked this tutorial, I tried my best to explain all important features of Web API which allows you to get started and build your RESTful API. You can always get back to the complete running source code on github.

Please feel free to drop any comment or suggestion to enhance this tutorial. if you have quick question please send me on twitter.

The post Building ASP.Net Web API RESTful Service – Part 11 appeared first on Bit of Technology.

What is New in ASP.Net Web API 2 – Part 1

$
0
0

Asp.Net Web API 2 has been released with the release of Asp.Net MVC 5 since 5 months ago, Web API 2 can be used with .NET framework 4.5 only, the Web API 2 template is available by default on VS 2013 and you can install Web Tools 2013.1 for VS 2012 to have this template as well by visiting this link.

In my previous tutorial on Building ASP.Net Web API RESTful service, I’ve covered different features of the first release of ASP.Net Web API, in this two series post (part 2 can be found here) I will focus on the main features in version 2, I’ll be using the same project I’ve used in the previous tutorial but I will start new Web API 2 project then we’ll implement and discuss the new features. The source code for the new Web API 2 project can be found on my GitHub repository.

Note: I will not upgrade the existing eLearning Web API to version 2, but if you are interested to know how to upgrade version 1 to version 2 then you can follow the steps in ASP.Net official post here.

What is new in ASP.Net Web API 2?

ASP.Net Web API 2 comes with a couple of nice features and enhancements, the most four important features in my opinion are:

  1. ASP.Net Web API 2 Attribute Routing:

    • Web API 2 now supports attribute routing along with the conventional based routing where we used to define a route per controller inside “WebApiConfig.cs” class. Using attribute routing is very useful in situation that we have a single controller which is responsible for multiple actions, with version 2 the routes now can be defined directly on the controller or at the action level.
  2. IHttpActionResult:

    • In the first version of Asp.Net Web API we always returned HTTP response messages for all HTTP verbs using the extension method Request.CreateResponse and this was really easy, now with version 2 of ASP.Net Web API this is simplified more by introducing a new interface named IHttpActionResult, this interface acts like a factory for HttpResponseMessage with a support for custom responses such as (Ok, BadRequest,Notfound, Unauthorized, etc…).
  3. Cross Origin Resource Sharing Support (CORS):

    • Usually webpages from different domain are not allowed to issue AJAX requests to HTTP Services (API) on other domains due to Same-Origin Policy, the solution for this was to enable JSONP response. But in ASP.Net Web API 2 enabling CORS support is made easy, once you enable CORS it will allow JavaScript on webpage to send AJAX requests to another HTTP Service (API) on a different domain. This can be configured on the entire API, on certain controller, or even on selected actions.
  4. Enhancement on oData Support.

    • Note: I’ll not cover this in the current post as I’m planing to do dedicated series of posts on oData support for ASP.Net Web API.

Let’s cover the new features in practical example

As stated before and to keep things simple we’ll depend on my previous tutorial eLearning API concepts to demonstrate those features. All we want to use from the eLearning API is its data access layer and database model, as well the same repository pattern, in other words w’ll use only project eLearning.Data, if you are interested to know how we built the eLearning.Data project then you can follow along on how we created the database model here and how we applied the repository pattern here.

Once you have your database access layer project ready then you can follow along with me to create new eLearning.WebAPI2 project to demonstrate those new features.

I will assume that you have Web Tools 2013.1 for VS 2012 installed on your machine, so you can use the ASP.NetWeb API 2 template directly which will add the needed assemblies for ASP.Net Web API2.

Step 1: Create new empty ASP.Net Web API 2 project

We’ll start by creating a new empty ASP.Net Web API 2 project as the image below, you can name your project “eLearning.WebAPI2”, do not forget to choose .NET framework 4.5 version. Once The project is added we need install Entity Framework version 6 using NuGet package manager or NuGet package console, the package we’ll install is named “EntityFramework“. When the package is installed, we need to  add a reference for the class library “eLearning.Data” which will act as our database repository.

Web API 2 Project Template

 

 

 

 

Step 2: Configuring routes

The ASP.Net Web API 2 template we used has by default a class named “WebApiConfig” inside the “App_Start” folder, when you open this class you will notice that there is new line 

config.MapHttpAttributeRoutes();
 this didn’t exists in Web API version one, the main responsbility for this line of code is to enable Attribute Routing feature in Web API version 2 where we can define routes on the controller directly. In this tutorial we want to use routing by attributes only to route all requests, so feel free to delete the default route named “DefaultApi”.

The other important change introduced in Web API 2 is how the “WebApiConfig” file is registered, go ahead and open class “Global.asax”  and you will notice that there is new line used for configuring the routes 

GlobalConfiguration.Configure(WebApiConfig.Register);
 this line is responsible for registering the routes when the global configuration class is initiated and ready to be called.

Step 3: Adding first controller (Courses Controller)

Now we want to add a Web API Controller which will handle HTTP requests issues against the URI “/api/courses”. To do this right-click on Controllers folder->Select Add->Name the controller “CoursesController” and choose “Empty API Controller” Template. Note: It is not required to name the controller “CoursesController” as we used in Web API version 1, now the controllers selection are based on the attributes we define not the routes which used be configured in class “WebApiConfig”

We’ll add support for getting single course by id and getting all courses. There are different ways to define routing attributes, you can define route prefix on controller level, and you can define them on action level. As well we’ll cover how we can configure routing to an exceptional route within the same controller. Below are the scenarios we’ll cover:

1. Define attributes on action level

Let’s Implement the code below which add support for handling and HTTP GET request sent to the URI “api/courses/23″:

public class CoursesController : ApiController
    {
        [Route("api/courses/{id:int}")]
        public HttpResponseMessage GetCourse(int id)
        {
            Learning.Data.LearningContext ctx = null;
            Learning.Data.ILearningRepository repo = null;

            try
            {
                ctx = new Learning.Data.LearningContext();
                repo = new Learning.Data.LearningRepository(ctx);

                var course = repo.GetCourse(id, false);
                if (course != null)
                {
                    return Request.CreateResponse(HttpStatusCode.OK, course);
                }
                else
                {
                    return Request.CreateResponse(HttpStatusCode.NotFound);
                }

            }
            catch (Exception ex)
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
            }
            finally
            {
                ctx.Dispose();
            }
        }
}

What we have done here is simple, if you look at the highlighted line of code above you will notice how we defined the route on action level by using attribute 

System.Web.Http.Route
 where we specified the request URI and stated that id parameter should be integer, if you tried to issue GET request to URI “/api/courses/abc” you will get 404 response.

In Web API version 1 we used to define names for routes inside “WebApiConfig” class, those names were useful as we used them to link each resource to URI or for results navigation purpose, in our case we still need to return “PrevPageLink” and “NextPageLink” in the response body when user issue HTTP GET request to URI “/api/courses”. This still available in Web API version 2 but defining route names will take place on the attribute level, let’s implement the code below:

public class CoursesController : ApiController
    {
	[Route("api/courses/", Name = "CoursesRoute")]
        public HttpResponseMessage Get(int page = 0, int pageSize = 10)
        {
            IQueryable<Course> query;

            Learning.Data.LearningContext ctx = new Learning.Data.LearningContext();

            Learning.Data.ILearningRepository repo = new Learning.Data.LearningRepository(ctx);

            query = repo.GetAllCourses().OrderBy(c => c.CourseSubject.Id);
            var totalCount = query.Count();
            var totalPages = (int)Math.Ceiling((double)totalCount / pageSize);

            var urlHelper = new UrlHelper(Request);
            var prevLink = page > 0 ? urlHelper.Link("CoursesRoute", new { page = page - 1, pageSize = pageSize }) : "";
            var nextLink = page < totalPages - 1 ? urlHelper.Link("CoursesRoute", new { page = page + 1, pageSize = pageSize }) : "";

            var results = query
                          .Skip(pageSize * page)
                          .Take(pageSize)
                          .ToList();

            var result = new
            {
                TotalCount = totalCount,
                TotalPages = totalPages,
                PrevPageLink = prevLink,
                NextPageLink = nextLink,
                Results = results
            };

            return Request.CreateResponse(HttpStatusCode.OK, result);

        }
   }

In the code above notice how we defined the route name on attribute level, you can not define route names on Controller level so if you have another actions need route names then you have to define them on each attribute.

2. Define attributes on controller level

Now instead of repeating the prefix “/api/courses” on each action, we can add this prefix on controller level and define the specific route attributes information on each action, the change is fairly simple as the code below:

[RoutePrefix("api/courses")]
public class CoursesController : ApiController
	{
		[Route(Name = "CoursesRoute")]
		public HttpResponseMessage Get(int page = 0, int pageSize = 10)
		{
			/*Rest of implementation goes here*/
		}

		[Route("{id:int}")]
		public HttpResponseMessage GetCourse(int id)
		{
			/*Rest of implementation goes here*/
		}
	}

3. Routing to exceptional route

In some cases you need to route to different URI while you are on the same controller, this was not possible in Web API version 1 but it’s very easy to implement in version 2, assume that we want to get all courses names based on certain subject, our URI have to be on the form: “api/subjects/{subjectid}/courses” lets implement this by adding the code below:

[Route("~/api/subject/{subjectid:int}/courses")]
public HttpResponseMessage GetCoursesBySubject(int subjectid)
{
	Learning.Data.LearningContext ctx = null;
	Learning.Data.ILearningRepository repo = null;
	IQueryable<Course> query;

	try
	{
		ctx = new Learning.Data.LearningContext();
		repo = new Learning.Data.LearningRepository(ctx);

		query = repo.GetCoursesBySubject(subjectid);
		var coursesList = query.Select(c => c.Name).ToList();
		if (coursesList != null)
		{
			return Request.CreateResponse(HttpStatusCode.OK, coursesList);
		}
		else
		{
			return Request.CreateResponse(HttpStatusCode.NotFound);
		}

	}
	catch (Exception ex)
	{
		return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
	}
	finally
	{
		ctx.Dispose();
	}
}

Now how we defined the routing attribute and prefixed it with “~” so Web API will route any HTTP GET request coming to the URI “api/subject/8/courses” to this route, this is really nice feature when you want to introduce exceptional routing in the same controller.

In the next post I’ll cover the IHttpActionResult return type as well the support for CORS in ASP.Net Web API 2.

Source code is available on GitHub.

The post What is New in ASP.Net Web API 2 – Part 1 appeared first on Bit of Technology.

What is New in ASP.Net Web API 2 – Part 2

$
0
0

In the previous post we’ve covered ASP.Net Web API 2 attribute routing, in this post we’ll complete covering new features, we’ll start by discussing the new response return type IHttpActionResult then cover the support for CORS.

Source code is available on GitHub.

ASP.Net Web API 2 IHttpActionResult:

As we talked before ASP.Net Web API 2 has introduced new simplified interface named IHttpActionResult, this interface acts like a factory for HttpResponseMessage, it comes with custom built in responses such as (Ok, BadRequest, NotFound, Unauthorized, Exception, Conflict, Redirect).

Let’s modify the GetCourse(int id) method to return IHttpActionResult instead of HttpResponseMessage as the code below:

[Route("{id:int}")]
public IHttpActionResult GetCourse(int id)
{
	Learning.Data.LearningContext ctx = null;
	Learning.Data.ILearningRepository repo = null;
	try
	{
		ctx = new Learning.Data.LearningContext();
		repo = new Learning.Data.LearningRepository(ctx);

		var course = repo.GetCourse(id, false);
		if (course != null)
		{
			return Ok<Learning.Data.Entities.Course>(course);
		}
		else
		{
			return NotFound();
		}
	}
	catch (Exception ex)
	{
		return InternalServerError(ex);
	}
	finally
	{
		ctx.Dispose();
	}
}

Notice how we’re returning Ok (200 HTTP status code) with custom negotiated content, the body of the response contains JSON representation of the returned course. As well we are returning NotFound (404 HTTP status code) when the course is not found.

But what if want to extend the NotFound() response and customize it to return plain text message in response body? This is straight forward using IHttpActionResult interface as the below:

Construct our own Action Result:

We want to build our own NotFound(“Your custom not found message”) action result, so we need to add a class which implements IHttpActionResult, let’s add new file named NotFoundPlainTextActionResult as the code below:

public class NotFoundPlainTextActionResult : IHttpActionResult
{
    public string Message { get; private set; }
    public HttpRequestMessage Request { get; private set; }

    public NotFoundPlainTextActionResult(HttpRequestMessage request, string message)
    {
        this.Request = request;
        this.Message = message;
    }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        return Task.FromResult(ExecuteResult());
    }

    public HttpResponseMessage ExecuteResult()
    {
        HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.NotFound);

        response.Content = new StringContent(Message);
        response.RequestMessage = Request;
        return response;
    }
}

public static class ApiControllerExtension
{
    public static NotFoundPlainTextActionResult NotFound(ApiController controller, string message)
    {
        return new NotFoundPlainTextActionResult(controller.Request, message);
    }
}

By looking at the code above you will notice that the class “NotFoundPlainTextActionResult” implements interface “IHttpActionResult”, then we’ve added our own implementation to the method “ExecuteAsync” which returns a Task of type HttpResponseMessage. This HttpResponseMessage will return HTTP 404 status code along with the custom message we’ll provide in the response body.

In order to be able to reuse this in different controllers we need and new class named ApiControllerExtension which contains a method returns this customized Not Found response type.

Now back to our” CoursesController” we need to change the implementation of the standard NotFound() to the new one as the code below:

if (course != null)
	{
		return Ok<Learning.Data.Entities.Course>(course);
	}
	else
	{
		return eLearning.WebAPI2.CustomIHttpActionResult.ApiControllerExtension.NotFound(this, "Course not found");
	}

You can read more about extending IHttpActionResult result by visiting Filip W. post.

ASP.Net Web API 2 CORS Support:

Enabling Cross Origin Resource Sharing in ASP.Net Web API 2 is simple, once it is enabled any client sending AJAX requests from webpage (on a different domain) to our API will be accepted.

By default CORS assembly doesn’t exist within ASP.NET Web API 2 assemblies so we need install it from NuGet, so open your NuGet package console, and type the following 

Install-Package Microsoft.AspNet.WebApi.Cors -Version 5.0.0
 once the package is installed open “WebApiConfig” class and add the following line of code inside the register method
config.EnableCors();
 by doing this we didn’t enable CORS yet, there are different levels to enable CORS on ASP.Net Web API, levels are:

1. On controller level

You can now add attribute named EnableCors on the entire controller so by default every action on this controller will support CORS as well, to do this open file “CoursesController” and add the highlighted line of code below:

[RoutePrefix("api/courses")]
[EnableCors("*", "*", "GET,POST")]
public class CoursesController : ApiController
{
	//Rest of implementation is here
}

The EnableCors attribute accept 3 parameters, in the first one you can specify the origin of the domain where requests coming from, so if you want to allow only domain www.example.com to send requests for your API; then you specify this explicitly in this parameter, most of the cases you need to allow * which means all requests are accepted from any origin. In the second parameter you can specify if you need a certain header to be included in each request, so you can force consumers to send this header along with each request, in our case we will use * as well. The third parameter is used to specify which HTTP verbs this controller accepts, you can put * as well, but in our case we want to allow only GET and POST verbs to be called from requests coming from different origin.

In case you want to exclude a certain action in the controller from CORS support you can add the attribute DisableCors to this action, let we assume we want to disable CORS support on method GetCourse so the code to disable CORS support on this action will be as the below:

[Route("{id:int}")]
[DisableCors()]
public IHttpActionResult GetCourse(int id)
{
	//Rest of implementation is here
}

2. On action level

Enabling CORS on certain actions is fairly simple, all you want to do is adding the attribute EnableCors on this action, as well EnableCors accepts the same 3 parameters we discussed earlier. Enabling it on action level will be as the below code:

[Route(Name = "CoursesRoute")]
[EnableCors("*", "*", "GET")]
public HttpResponseMessage Get(int page = 0, int pageSize = 10)
{
	//Rest of implemntation is here
}

 3. On the entire API

In some situations where you have many controllers and you want to allow CORS on your entire API, it is not convenient to visit each controller and add EanbleCors attribute to it, in this situation we can allow it on the entire API inside the Register method in Class WebApiConfig, so open your WebApiConfig class and add the code below:

//Support for CORS
EnableCorsAttribute CorsAttribute = new EnableCorsAttribute("*", "*", "GET,POST");
config.EnableCors(CorsAttribute);

By adding this we enabled CORS support for every controller we have in our API, still you can disable CORS support on selected actions by adding DisableCors attribute on action level.

Source code is available on GitHub.

That’s all for now!

Thanks for reading and please feel free to drop any comment or question if there is nothing clear. Happy Coding!

The post What is New in ASP.Net Web API 2 – Part 2 appeared first on Bit of Technology.

Building OData Service using ASP.Net Web API Tutorial – Part 1

$
0
0

In my previous tutorial we’ve covered different aspects of how to Build RESTful service using Asp.NET Web API, in this multi-part series tutorial we’ll be building OData service following the same REST architecture we’ve talked about previously.

Before jump into code samples let’s talk a little bit about OData definition and specifications.

OData Introduction

OData stands for Open Data Protocol. It is standard to for providing access to data over the internet, OData is championed by Microsoft as an open specification and adopted by many different platforms. By using OData it will allow you to build a uniform way to expose full featured data APIs (Querying, Updating), the nice thing about OData that it builds on top of mature standard web technologies and protocols such as HTTP, Atom Publishing Protocol, JSON, and follow the REST architecture in order to provide data access from different applications, services and data stores.

It is well known that any service follows the REST principles well adhere to the aspects below:

  • Resources are identified by a unique URI only.
  • Actions on the resource should be done using using HTTP verbs (GET, POST, PUT, and DELETE).
  • Enable content negotiation to allow clients specifying the format of the data type returned: XML format (AtomPub), or JSON format (Verbose/Light).

odata service asp net web api

Querying Existing OData Service

Before start building our OData service let’s examine querying an existing OData service published on the internet and uses the Northwind database, the base URI for this service is http://services.odata.org/Northwind/Northwind.svc. You can use any REST client such as (Fiddler, PostMan) to compose those HTTP requests, as we are only querying  the service now (No sending updates) you can use your favorite browser as well. Note you can use Linq4Pad to generate and test complex OData qyeries

The tables below illustrates some of the OData query options which can be used to query the service:

Option
OData Service URL
Notes
$filterhttp://services.odata.org/Northwind/Northwind.svc/Products?$filter=ProductName eq 'Tofu'Filter the results based on Boolean condition, I.e. get product name = 'Tofu'
$orderbyhttp://services.odata.org/Northwind/Northwind.svc/Products?$orderby=ProductNameSort the results, i.e: Sort the products by Product Name
$skiphttp://services.odata.org/Northwind/Northwind.svc/Products?$skip=10Skip the first n results, used for server side paging
$tophttp://services.odata.org/Northwind/Northwind.svc/Products?$top=10Returns only the first n the results, used for server side paging
$selecthttp://services.odata.org/Northwind/Northwind.svc/Products?$filter=ProductName eq 'Tofu'&$select=ProductName,UnitPriceSelect which properties to be returned in the response. i.e. returning ProductName and UnitPrice
$expandhttp://services.odata.org/Northwind/Northwind.svc/Products?$expand=SupplierExpand the related entities inline i.e. expand the supplier entity for each product
$inlinecounthttp://services.odata.org/Northwind/Northwind.svc/Products?$inlinecount=allpagesInform the server to return the total count of matching records in the response.

As we see in the table above we can combine different query options together and provide complex search criteria for example if we want to implement server side paging we can issue the following HTTP GET request: http://services.odata.org/Northwind/Northwind.svc/Products?$top=10&$skip=0&$orderby=ProductName&$inlinecount=allpages where $skip represents the number of records to skip usually (PageSize x PageIndex) and $inlinecount represents the total number of products. To view the complete list of available query options you can visit this link.

As we stated before OData service allows content negotiation, so the client can choose the response format by setting the Accept header of the request, each response format has its own pros and cons, the table below illustrates the differences:

 
XML (Atom Publishing)
JSON Verbose
JSON Light
OData VersionVersion 1, 2, and 3Version 1, 2 and 3Version 3
Metadata and Hyper LinksData and MetaDataData and MetadataNo Metadata, Just the Data
Payload Size for all Products entity28.67 KBs14.34 KBs, smaller by 50%4.25 KBs, smaller by 75%
Easy to consume in mobile clientsNoYesYes
Accept Headerapplication/atom+xmlapplication/json;odata=verboseapplication/json

I’ve decided to split this tutorial into four parts as the below:

Source Code for this series is available on GitHub, you can download it locally or you can fork it. If you have any question or if there is nothing unclear please drop me a comment.

The post Building OData Service using ASP.Net Web API Tutorial – Part 1 appeared first on Bit of Technology.


Building OData Service using ASP.Net Web API Tutorial – Part 2

$
0
0

This is the second part of Building OData Service using Asp.Net Web API. The topics we’ll cover are:

Create read-only OData endpoint using Asp.Net Web API

In this tutorial I’ll be using the same solution I’ve used in the previous tutorial but I will start new Web API 2 project then we’ll implement OData service using Web API. The source code for the new OData Service project can be found on my GitHub repository.

Practical example covering how to build OData Service

To keep things simple we’ll depend on my previous tutorial eLearning API concepts to demonstrate how to build OData Service. All we want to use from the eLearning API is its data access layer and database model, in other words w’ll use only project Learning.Data. I recommend you to check how we built the Learning.Data project here as the navigation properties between database entities are important to understand the relations that will be generated between OData entities.

Once you have your database access layer project ready then you can follow along with me to create new Learning.ODataService project.

I will assume that you have Web Tools 2013.1 for VS 2012 installed on your machine or you have VS 2013, so you can use the ASP.NetWeb API 2 template directly which will add the needed assemblies for ASP.Net Web API2.

Step 1: Create new empty ASP.Net Web API 2 project

We’ll start by creating a new empty ASP.Net Web API 2 project as the image below, you can name your project “Learning.ODataService”, do not forget to choose .NET framework 4.5 version. Once The project is created we need install Entity Framework version 6 using NuGet package manager or NuGet package console, the package we’ll install is named “EntityFramework“. When the package is installed, we need to  add a reference for the class library “Learning.Data” which will act as our database access layer.

ODataServiceProject

Step 2: Add support for OData to Web API

By default the ASP.Net Web API doesn’t come with a support for OData, to add this we need to install NuGet package named “Microsoft.ASP.NET Web API 2.1 OData” to our Web API project. To do this open package manager console and type “Install-Package Microsoft.AspNet.WebApi.OData”.

Step 3: Configure OData Routes

The ASP.Net Web API 2 template we used has by default a class named “WebApiConfig” inside the “App_Start” folder, when you open this class you will notice that inside the “Register” method it has a “config.MapHttpAttributeRoutes()” line and “DefaultApi” route which is used to configure traditional Web API routes, the nice thing here that we can define OData end points along with traditional Web API end points in the same application.

In this tutorial we want to define only OData end points so feel free to delete the default route named “DefaultApi” as well the “config.MapHttpAttributeRoutes()” line .

Now you need to replace the code in “WebApiConfig” class with the code below:

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Routes.MapODataRoute("elearningOData", "OData", GenerateEdmModel());
        }

        private static IEdmModel GenerateEdmModel()
        {
            var builder = new ODataConventionModelBuilder();
            builder.EntitySet<Course>("Courses");
            builder.EntitySet<Enrollment>("Enrollments");
            builder.EntitySet<Subject>("Subjects");
	    builder.EntitySet<Tutor>("Tutors");

            return builder.GetEdmModel();
        }
    }

The code above is responsible for defining the routes for our OData service and generating an Entity Data Model (EDM) for our OData service.

The EDM is responsible to define the type system, relationships, and actions that can be expressed in the OData formats, there are two approaches to define an EDM, the first one which depends on conventions should use class ODataConventionModelBuilder, and the second one should use class ODataModelBuilder. 

We’ll use the ODataConventionModelBuilder as it will depend on the navigation properties defined between your entities to generate the association sets and relationship links. This method requires less code to write. If you want more flexibility and control over the association sets then you have to use the ODataModelBuilder approach.

So we will add four different entities to the model builder, note that the string parameter “Courses” defines the entity set name and should match the controller name, so our controller name must be named “CoursesController”.

The MapODataRoute is an extension method which will be availabe after we installed OData package, it is responsible to define the routes for our OData service, the first parameter of this method is friendly name that is not visible for service clients, the second parameter is the URI prefix for the OData endpoint, so in our case the URI for the Courses resource will be as the following: http://hostname/odata/Courses. As we mentioned before you can have multiple OData endpoints in the same application, all you need to do is to call MapODataRoute with different URI prefix.

Step 4: Add first OData Controller (Read only controller)

Now we want to add a Web API Controller which will handle HTTP requests issued against the OData URI “/odata/Courses”. To do this right-click on Controllers folder->Select Add->Name the controller “CoursesController” and choose “Empty API Controller” Template.

First thing to do here is to derive our “CoursesController” from “System.Web.Http.OData.EntitySetController“, the constructor of this class accepts two parameters, the first one is the entity type mapped to this controller, and the second one is the data type of the primary key for this entity, the code for this OData controller will look as the below:

public class CoursesController : EntitySetController<Course, int>
    {
        LearningContext ctx = new LearningContext();

        [Queryable(PageSize=10)]
        public override IQueryable<Course> Get()
        {
            return ctx.Courses.AsQueryable();
        }

        protected override Course GetEntityByKey(int key)
        {
            return ctx.Courses.Find(key);
        }
    }

The EntitySetController class has number of abstract and override methods for updating or querying an entity, so you will notice that there are many methods you can override such as: Get(), GetEntityByKey(), CreateEntity(), PatchEntity(), UpdateEntity(), etc..

As I mentioned before, this controller will be a read only controller, which means that I’ll implement only read support for URI “/odata/Courses”, so by looking at the code above we’ve implemented the following:

  • Overriding the Get() method and attributing it with [Queryable] attribute which allow clients to issue HTTP Get request to this endpoint where they can encode filter, order by, pagination parameter in the URI. This Queryable attribute is an action filter which is responsible to parse and validate the query sent in the URI. This attribute is useful to protect your end point service from clients who might issue a query which takes long time to execute or ask for large sets of data, so for example I’ve set the PageSize of the response to return only 10 records at a time. you can read more about the set of parameters available here.
  • Overriding the GetEntityByKey(int key) method which allow clients to issue HTTP Get request to a single Course on the form: “/odata/Courses(5)”, note that the key data type is integer as it represents the primary key in Courses entity.

 Step 5: Testing The Courses Controller

Now we need to test the controller, we’ll use fiddler or PostMan to compose the HTTP Get requests, the accept header for all requests will be application/json so we’ll get JSON Light response, you can check how the results are formatted if you passed application/json;odata=verbose or application/atom+xml. The scenarios we want to cover as the below:

  • use $filter: We need to filter all courses where the duration of the course is greater than 4 hours
    • Get Request: http://hostname/OData/Courses?$filter=Duration%20gt%204
  • use $orderby, $take: We need to order by course name and take the top 5 records
    • Get Request: http://hostname/OData/Courses?$orderby=Name&$top=5
  • use $select: We need to get the Name and Duration fields only for all fields
    • Get Request: http://hostname/OData/Courses?$select=Name,Duration
  • $expand: We need to get related Course Tutor and Subject for each Course and order the Courses by Name descending
    • Get Request: http://hostname/OData/Courses?$expand=CourseTutor,CourseSubject&$orderby=Name desc

Notes about the $expand query:

  • The $expand allow clients to ask for related entities inline based on the navigation properties defined between the entities, as you notice the $expand accepts comma separated values so you can ask for different entities at the same time, for more information about the $expand query you can visit this link.
  • By looking at the JSON response below for the $expand query we requested you will notice that the fields UserName and Password (Lines 5 and 6) for each Tutor is returned in the response which doesn’t make sense.

{
  "CourseTutor": {
    "Id": 5,
    "Email": "Iyad.Radi@gmail.com",
    "UserName": "IyadRadi",
    "Password": "MXELYDAC",
    "FirstName": "Iyad",
    "LastName": "Radi",
    "Gender": "Male"
  },
  "CourseSubject": {
    "Id": 5,
    "Name": "Commerce"
  },
  "Id": 15,
  "Name": "Commerce, Business Studies and Economics Teaching Methods 1",
  "Duration": 3,
  "Description": "The course will talk in depth about: Commerce, Business Studies and Economics Teaching Methods 1"
}

The nice thing here that we can fix fix this issue by ignoring those two properties from the EDM model only without changing any property on the data model, to do this open the class “WebApiConfig” and replace the code in method GenerateEdmModel() with the code below, notice how we specified the ignored properties in lines 8 and 9:

private static IEdmModel GenerateEdmModel()
        {
            var builder = new ODataConventionModelBuilder();
            builder.EntitySet<Course>("Courses");
            builder.EntitySet<Enrollment>("Enrollments");
            builder.EntitySet<Subject>("Subjects");

            var tutorsEntitySet = builder.EntitySet<Tutor>("Tutors");

            tutorsEntitySet.EntityType.Ignore(s => s.UserName);
            tutorsEntitySet.EntityType.Ignore(s => s.Password);

            return builder.GetEdmModel();
        }

In the next post we’ll see how we can implement a controller which will support full CRUD operations on the Tutors resource.

Please drop your questions and comments on the comments section below.

Source code is available on GitHub.

The post Building OData Service using ASP.Net Web API Tutorial – Part 2 appeared first on Bit of Technology.

Building OData Service using ASP.Net Web API Tutorial – Part 3

$
0
0

This is the third part of Building OData Service using Asp.Net Web API. The topics we’ll cover are:

CRUD Operations on OData endpoint using Asp.Net Web API

In this post We’ll add another OData controller which will support all the CRUD operations, as we talked before OData follows the conventions of HTTP and REST; so if we want to create a resources we’ll issue HTTP POST, if we want to delete a resource we’ll issue HTTP DELETE and so on. One more thing we want to add support for is partial updates (HTTP PATCH) which will be very efficient when we update certain properties on the entity, the request payload for PATCH will come on a key/value pair and will contain the properties changed only.

Step 1: Add OData Controller (Support for CRUD operations)

Let’s add a new Web API Controller which will handle all HTTP requests issued against the OData URI “/odata/Tutors”. To do this right-click on Controllers folder->Select Add->Name the controller “TutorsController” and choose “Empty API Controller” Template.

As we did before we have to derive our “TutorsController” from class “EntitySetController“, then we’ll add support for the Get() and GetEntityByKey(int key) methods and will implement creating a new Tutor; so when the client issue HTTP POST request to the URI “/odata/Tutors” the “CreateEntity(Tutor entity)” method will be responsible to handle the request. The code will look as the below:

public class TutorsController : EntitySetController<Tutor, int>
    {
        LearningContext ctx = new LearningContext();

        [Queryable()]
        public override IQueryable<Tutor> Get()
        {
            return ctx.Tutors.AsQueryable();
        }

        protected override Tutor GetEntityByKey(int key)
        {
            return ctx.Tutors.Find(key);
        }

        protected override int GetKey(Tutor entity)
        {
            return entity.Id;
        }

        protected override Tutor CreateEntity(Tutor entity)
        {
            Tutor insertedTutor = entity;
            insertedTutor.UserName = string.Format("{0}.{1}",entity.FirstName, entity.LastName);
            insertedTutor.Password = Helpers.RandomString(8);
            ctx.Tutors.Add(insertedTutor);
            ctx.SaveChanges();
            return entity;
        }
  }

By looking at the code above you’ll notice that we overrided the CreateEntity() method which accepts a strongly typed Tutor entity, the nice thing here that once you override the CreateEntity() method the base class “EntitySetController” will be responsible of returning the right HTTP response message (201) and adding the correct location header for the created resource. To test this out let’s issue issue an HTTP POST request to URI “odata/Tutors”, the Post request will look as the below:

web api odata crud

Step 2: Testing OData Prefer Header

By looking at the request above you will notice that status code is 201 created is returned as well the response body contains the newly created Tutor, but what if the client do not want to return a duplicate entity of the newly created Tutor from the server? The nice thing here that OData allow us to send Prefer header with request to indicate if we need to return the created entity back to the client. The default value for the header is “return-content” so if we tried to issue another POST request and pass the Prefer header with value “return-no-content” the server will create the resource and will return 204 no content response.

Step 3: Add Support for Resource Deletion

Adding support for delete is simple, we need to override method Delete(int key) so any HTTP DELETE request sent to the URI “/odata/Tutors “will be handled by this method, let’s implement this in the code below:

public override void Delete(int key)
	{
		var tutor = ctx.Tutors.Find(key);
		if (tutor == null) 
		{
			throw new HttpResponseException(HttpStatusCode.NotFound);
		}

		ctx.Tutors.Remove(tutor);
		ctx.SaveChanges();
	}

To test this out we need to issue HTTP DELETE request to the URI “OData/Tutors(12)” and if the tutor exists the HTTP response will be 204 no content. What worth mentioning here that if we tried to delete a tutor which doesn’t exists then by looking at code on line 6 you will notice that I’m throwing HttpResponseException with status code 404 along with empty response body; nothing wrong about this but if you want to build OData compliant service then handling the errors should be done on a different way; to fix this we need to return an HttpResponseException with an object of type “Microsoft.Data.OData.ODataError” in the response body.

Step 4: Return Complaint OData Errors

To fix the issue above I’ll create a helper class which will return ODataError, we’ll use this class in different methods and for another controllers, so add new class named “Helpers” and paste the code below:

public static class Helpers
    {
        public static HttpResponseException ResourceNotFoundError(HttpRequestMessage request)
        {
            HttpResponseException httpException;
            HttpResponseMessage response;
            ODataError error;

            error = new ODataError
            {
                Message = "Resource Not Found - 404",
                ErrorCode = "NotFound"
            };

            response = request.CreateResponse(HttpStatusCode.NotFound, error);

            httpException = new HttpResponseException(response);

            return httpException;
        }
    }

By looking at the code above you will notice that there is nothing special here, we only returning an object of ODataError in the response body, you can set the Message and ErrorCode properties for something meaningful for your OData service clients. Now insted of throwing the exception directly in the controller we’ll call this helper method as the code below:

if (tutor == null) 
	{
		throw Helpers.ResourceNotFoundError(Request);
	}

Step 5: Add Support for Partial Updates (PATCH)

In cases we want to update 1 or 2 properties of a resource which has 30 properties; it will be very efficient if we are able to send only over the wire the properties which have been changed, as well it will be very efficient on the database level if we generated an update statement which contains the update fields only. To achieve this we need to override the method PatchEntity() as the code below:

protected override Tutor PatchEntity(int key, Delta<Tutor> patch)
        {
            var tutor = ctx.Tutors.Find(key);
            if (tutor == null)
            {
                throw Helpers.ResourceNotFoundError(Request);
            }   
            patch.Patch(tutor);
            ctx.SaveChanges();
            return tutor;
        }

As I mentioned before the changed properties will be in key/value form in the response body thanks to the Delta<T> OData class which makes it easy to perform partial updates on any entity, to test this out we’ll issue HTTP Patch request to the URI “/odata/Tutors(10)” where we will modify the LastName property only for this Tutor, request will be as the below:

web api odata crud ODataPatchRequest

Before we send the request Let’s open SQL Server Profile to monitor the database query which will be generated to update this Tutor, you will notice from the image below how efficient is using the Patch update when we want to modify certain properties on an entity, the query generated do an update only for the changed property.

ODataSqlProfiler

In the next post we’ll see how we can consume this OData service from Single Page Application built using AngularJS and Breeze.js

Please drop your questions and comments on the comments section below.

Source code is available on GitHub.

The post Building OData Service using ASP.Net Web API Tutorial – Part 3 appeared first on Bit of Technology.

Token Based Authentication using ASP.NET Web API 2, Owin, and Identity

$
0
0

Last week I was looking at the top viewed posts on my blog and I noticed that visitors are interested in the authentication part of ASP.NET Web API, CORS Support, and how to authenticate users in single page applications built with AngularJS using token based approach.

So I decided to compile mini tutorial of two posts which covers and connects those topics. In this tutorial we’ll build SPA using AngularJS for the front-end, and ASP.NET Web API 2, Owin middleware, and ASP.NET Identity for the back-end.

Part 2 of this tutorial (AngularJS Token Authentication using ASP.NET Web API 2, Owin, and ASP.NET Identity).

The demo application can be accessed on (http://ngAuthenticationWeb.azurewebsites.net). The back-end API can be accessed on (http://ngAuthenticationAPI.azurewebsites.net/) and both are hosted on Microsoft Azure, for learning purposes feel free to integrate and play with the back-end API with your front-end application. The API supports CORS and accepts HTTP calls from any origin. You can check the source code for this tutorial on Github.

AngularJS Authentication

 

Token Based Authentication

As I stated before we’ll use token based approach to implement authentication between the front-end application and the back-end API, as we all know the common and old way to implement authentication is the cookie-based approach were the cookie is sent with each request from the client to the server, and on the server it is used to identify the authenticated user.

With the evolution of front-end frameworks and the huge change on how we build web applications nowadays the preferred approach to authenticate users is to use signed token as this token sent to the server with each request, some of the benefits for using this approach are:

  • Scalability of Servers: The token sent to the server is self contained which holds all the user information needed for authentication, so adding more servers to your web farm is an easy task, there is no dependent on shared session stores.
  • Loosely Coupling: Your front-end application is not coupled with specific authentication mechanism, the token is generated from the server and your API is built in a way to understand this token and do the authentication.
  • Mobile Friendly: Cookies and browsers like each other, but storing cookies on native platforms (Android, iOS, Windows Phone) is not a trivial task, having standard way to authenticate users will simplify our life if we decided to consume the back-end API from native applications.

What we’ll build in this tutorial?

The front-end SPA will be built using HTML5, AngularJS, and Twitter Bootstrap. The back-end server will be built using ASP.NET Web API 2 on top of Owin middleware not directly on top of ASP.NET; the reason for doing so that we’ll configure the server to issue OAuth bearer token authentication using Owin middleware too, so setting up everything on the same pipeline is better approach. In addition to this we’ll use ASP.NET Identity system which is built on top of Owin middleware and we’ll use it to register new users and validate their credentials before generating the tokens.

As I mentioned before our back-end API should accept request coming from any origin, not only our front-end, so we’ll be enabling CORS (Cross Origin Resource Sharing) in Web API as well for the OAuth bearer token provider.

Use cases which will be covered in this application:

  • Allow users to signup (register) by providing username and password then store credentials in secure medium.
  • Prevent anonymous users from viewing secured data or secured pages (views).
  • Once the user is logged in successfully, the system should not ask for credentials or re-authentication for the next 24 hours.

So in this post we’ll cover step by step how to build the back-end API, and on the next post we’ll cover how we’ll build and integrate the SPA with the API.

Enough theories let’s get our hands dirty and start implementing the API!

Building the Back-End API

Step 1: Creating the Web API Project

In this tutorial I’m using Visual Studio 2013 and .Net framework 4.5, you can follow along using Visual Studio 2012 but you need to install Web Tools 2013.1 for VS 2012 by visiting this link.

Now create an empty solution and name it “AngularJSAuthentication” then add new ASP.NET Web application named “AngularJSAuthentication.API”, the selected template for project will be as the image below. Notice that the authentication is set to “No Authentication” taking into consideration that we’ll add this manually.

Web API Project Template

Step 2: Installing the needed NuGet Packages:

Now we need to install the NuGet packages which are needed to setup our Owin server and configure ASP.NET Web API to be hosted within an Owin server, so open NuGet Package Manger Console and type the below:

Install-Package Microsoft.AspNet.WebApi.Owin -Version 5.1.2
Install-Package Microsoft.Owin.Host.SystemWeb -Version 2.1.0

The  package “Microsoft.Owin.Host.SystemWeb” is used to enable our Owin server to run our API on IIS using ASP.NET request pipeline as eventually we’ll host this API on Microsoft Azure Websites which uses IIS.

Step 3: Add Owin “Startup” Class

Right click on your project then add new class named “Startup”. We’ll visit this class many times and modify it, for now it will contain the code below:

using Microsoft.Owin;
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;

[assembly: OwinStartup(typeof(AngularJSAuthentication.API.Startup))]
namespace AngularJSAuthentication.API
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            HttpConfiguration config = new HttpConfiguration();
            WebApiConfig.Register(config);
            app.UseWebApi(config);
        }

    }
}

What we’ve implemented above is simple, this class will be fired once our server starts, notice the “assembly” attribute which states which class to fire on start-up. The “Configuration” method accepts parameter of type “IAppBuilder” this parameter will be supplied by the host at run-time. This “app” parameter is an interface which will be used to compose the application for our Owin server.

The “HttpConfiguration” object is used to configure API routes, so we’ll pass this object to method “Register” in “WebApiConfig” class.

Lastly, we’ll pass the “config” object to the extension method “UseWebApi” which will be responsible to wire up ASP.NET Web API to our Owin server pipeline.

Usually the class “WebApiConfig” exists with the templates we’ve selected, if it doesn’t exist then add it under the folder “App_Start”. Below is the code inside it:

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
            jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        }
    }

Step 4: Delete Global.asax Class

No need to use this class and fire up the Application_Start event after we’ve configured our “Startup” class so feel free to delete it.

Step 5: Add the ASP.NET Identity System

After we’ve configured the Web API, it is time to add the needed NuGet packages to add support for registering and validating user credentials, so open package manager console and add the below NuGet packages:

Install-Package Microsoft.AspNet.Identity.Owin -Version 2.0.1
Install-Package Microsoft.AspNet.Identity.EntityFramework -Version 2.0.1

The first package will add support for ASP.NET Identity Owin, and the second package will add support for using ASP.NET Identity with Entity Framework so we can save users to SQL Server database.

Now we need to add Database context class which will be responsible to communicate with our database, so add new class and name it “AuthContext” then paste the code snippet below:

public class AuthContext : IdentityDbContext<IdentityUser>
    {
        public AuthContext()
            : base("AuthContext")
        {

        }
    }

As you can see this class inherits from “IdentityDbContext” class, you can think about this class as special version of the traditional “DbContext” Class, it will provide all of the Entity Framework code-first mapping and DbSet properties needed to manage the identity tables in SQL Server. You can read more about this class on Scott Allen Blog.

Now we want to add “UserModel” which contains the properties needed to be sent once we register a user, this model is POCO class with some data annotations attributes used for the sake of validating the registration payload request. So under “Models” folder add new class named “UserModel” and paste the code below:

public class UserModel
    {
        [Required]
        [Display(Name = "User name")]
        public string UserName { get; set; }

        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "Password")]
        public string Password { get; set; }

        [DataType(DataType.Password)]
        [Display(Name = "Confirm password")]
        [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
        public string ConfirmPassword { get; set; }
    }

Now we need to add new connection string named “AuthContext” in our Web.Config class, so open you web.config and add the below section:

<connectionStrings>
    <add name="AuthContext" connectionString="Data Source=.\sqlexpress;Initial Catalog=AngularJSAuth;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
  </connectionStrings>

Step 6: Add Repository class to support ASP.NET Identity System

Now we want to implement two methods needed in our application which they are: “RegisterUser” and “FindUser”, so add new class named “AuthRepository” and paste the code snippet below:

public class AuthRepository : IDisposable
    {
        private AuthContext _ctx;

        private UserManager<IdentityUser> _userManager;

        public AuthRepository()
        {
            _ctx = new AuthContext();
            _userManager = new UserManager<IdentityUser>(new UserStore<IdentityUser>(_ctx));
        }

        public async Task<IdentityResult> RegisterUser(UserModel userModel)
        {
            IdentityUser user = new IdentityUser
            {
                UserName = userModel.UserName
            };

            var result = await _userManager.CreateAsync(user, userModel.Password);

            return result;
        }

        public async Task<IdentityUser> FindUser(string userName, string password)
        {
            IdentityUser user = await _userManager.FindAsync(userName, password);

            return user;
        }

        public void Dispose()
        {
            _ctx.Dispose();
            _userManager.Dispose();

        }
    }

What we’ve implemented above is the following: we are depending on the “UserManager” that provides the domain logic for working with user information. The “UserManager” knows when to hash a password, how and when to validate a user, and how to manage claims. You can read more about ASP.NET Identity System.

Step 7: Add our “Account” Controller

Now it is the time to add our first Web API controller which will be used to register new users, so under file “Controllers” add Empty Web API 2 Controller named “AccountController” and paste the code below:

[RoutePrefix("api/Account")]
    public class AccountController : ApiController
    {
        private AuthRepository _repo = null;

        public AccountController()
        {
            _repo = new AuthRepository();
        }

        // POST api/Account/Register
        [AllowAnonymous]
        [Route("Register")]
        public async Task<IHttpActionResult> Register(UserModel userModel)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            IdentityResult result = await _repo.RegisterUser(userModel);

            IHttpActionResult errorResult = GetErrorResult(result);

            if (errorResult != null)
            {
                return errorResult;
            }

            return Ok();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _repo.Dispose();
            }

            base.Dispose(disposing);
        }

        private IHttpActionResult GetErrorResult(IdentityResult result)
        {
            if (result == null)
            {
                return InternalServerError();
            }

            if (!result.Succeeded)
            {
                if (result.Errors != null)
                {
                    foreach (string error in result.Errors)
                    {
                        ModelState.AddModelError("", error);
                    }
                }

                if (ModelState.IsValid)
                {
                    // No ModelState errors are available to send, so just return an empty BadRequest.
                    return BadRequest();
                }

                return BadRequest(ModelState);
            }

            return null;
        }
    }

By looking at the “Register” method you will notice that we’ve configured the endpoint for this method to be “/api/account/register” so any user wants to register into our system must issue HTTP POST request to this URI and the pay load for this request will contain the JSON object as below:

{
  "userName": "Taiseer",
  "password": "SuperPass",
  "confirmPassword": "SuperPass"
}

Now you can run your application and issue HTTP POST request to your local URI: “http://localhost:port/api/account/register” or you can try the published API using this end point: http://ngauthenticationapi.azurewebsites.net/api/account/register if all went fine you will receive HTTP status code 200 and the database specified in connection string will be created automatically and the user will be inserted into table “dbo.AspNetUsers”.

Note: It is very important to send this POST request over HTTPS so the sensitive information get encrypted between the client and the server.

The “GetErrorResult” method is just a helper method which is used to validate the “UserModel” and return the correct HTTP status code if the input data is invalid.

Step 8: Add Secured Orders Controller

Now we want to add another controller to serve our Orders, we’ll assume that this controller will return orders only for Authenticated users, to keep things simple we’ll return static data. So add new controller named “OrdersController” under “Controllers” folder and paste the code below:

[RoutePrefix("api/Orders")]
    public class OrdersController : ApiController
    {
        [Authorize]
        [Route("")]
        public IHttpActionResult Get()
        {
            return Ok(Order.CreateOrders());
        }

    }

    #region Helpers

    public class Order
    {
        public int OrderID { get; set; }
        public string CustomerName { get; set; }
        public string ShipperCity { get; set; }
        public Boolean IsShipped { get; set; }

        public static List<Order> CreateOrders()
        {
            List<Order> OrderList = new List<Order> 
            {
                new Order {OrderID = 10248, CustomerName = "Taiseer Joudeh", ShipperCity = "Amman", IsShipped = true },
                new Order {OrderID = 10249, CustomerName = "Ahmad Hasan", ShipperCity = "Dubai", IsShipped = false},
                new Order {OrderID = 10250,CustomerName = "Tamer Yaser", ShipperCity = "Jeddah", IsShipped = false },
                new Order {OrderID = 10251,CustomerName = "Lina Majed", ShipperCity = "Abu Dhabi", IsShipped = false},
                new Order {OrderID = 10252,CustomerName = "Yasmeen Rami", ShipperCity = "Kuwait", IsShipped = true}
            };

            return OrderList;
        }
    }

    #endregion

Notice how we added the “Authorize” attribute on the method “Get” so if you tried to issue HTTP GET request to the end point “http://localhost:port/api/orders” you will receive HTTP status code 401 unauthorized because the request you send till this moment doesn’t contain valid authorization header. You can check this using this end point: http://ngauthenticationapi.azurewebsites.net/api/orders

Step 9: Add support for OAuth Bearer Tokens Generation

Till this moment we didn’t configure our API to use OAuth authentication workflow, to do so open package manager console and install the following NuGet package:

Install-Package Microsoft.Owin.Security.OAuth -Version 2.1.0

After you install this package open file “Startup” again and call the new method named “ConfigureOAuth” as the first line inside the method “Configuration”, the implemntation for this method as below:

public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureOAuth(app);
	    //Rest of code is here;
        }

        public void ConfigureOAuth(IAppBuilder app)
        {
            OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
            {
                AllowInsecureHttp = true,
                TokenEndpointPath = new PathString("/token"),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
                Provider = new SimpleAuthorizationServerProvider()
            };

            // Token Generation
            app.UseOAuthAuthorizationServer(OAuthServerOptions);
            app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

        }
    }

Here we’ve created new instance from class “OAuthAuthorizationServerOptions” and set its option as the below:

  • The path for generating tokens will be as :”http://localhost:port/token”. We’ll see how we will issue HTTP POST request to generate token in the next steps.
  • We’ve specified the expiry for token to be 24 hours, so if the user tried to use the same token for authentication after 24 hours from the issue time, his request will be rejected and HTTP status code 401 is returned.
  • We’ve specified the implementation on how to validate the credentials for users asking for tokens in custom class named “SimpleAuthorizationServerProvider”.

Now we passed this options to the extension method “UseOAuthAuthorizationServer” so we’ll add the authentication middleware to the pipeline.

Step 10: Implement the “SimpleAuthorizationServerProvider” class

Add new folder named “Providers” then add new class named “SimpleAuthorizationServerProvider”, paste the code snippet below:

public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
    {
        public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            context.Validated();
        }

        public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {

            context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

            using (AuthRepository _repo = new AuthRepository())
            {
                IdentityUser user = await _repo.FindUser(context.UserName, context.Password);

                if (user == null)
                {
                    context.SetError("invalid_grant", "The user name or password is incorrect.");
                    return;
                }
            }

            var identity = new ClaimsIdentity(context.Options.AuthenticationType);
            identity.AddClaim(new Claim("sub", context.UserName));
            identity.AddClaim(new Claim("role", "user"));

            context.Validated(identity);

        }
    }

As you notice this class inherits from class “OAuthAuthorizationServerProvider”, we’ve overridden two methods “ValidateClientAuthentication” and “GrantResourceOwnerCredentials”. The first method is responsible for validating the “Client”, in our case we have only one client so we’ll always return that its validated successfully.

The second method “GrantResourceOwnerCredentials” is responsible to validate the username and password sent to the authorization server’s token endpoint, so we’ll use the “AuthRepository” class we created earlier and call the method “FindUser” to check if the username and password are valid.

If the credentials are valid we’ll create “ClaimsIdentity” class and pass the authentication type to it, in our case “bearer token”, then we’ll add two claims (“sub”,”role”) and those will be included in the signed token. You can add different claims here but the token size will increase for sure.

Now generating the token happens behind the scenes when we call “context.Validated(identity)”.

To allow CORS on the token middleware provider we need to add the header “Access-Control-Allow-Origin” to Owin context, if you forget this, generating the token will fail when you try to call it from your browser. Not that this allows CORS for token middleware provider not for ASP.NET Web API which we’ll add on the next step.

Step 11: Allow CORS for ASP.NET Web API

First of all we need to install the following NuGet package manger, so open package manager console and type:

Install-Package Microsoft.Owin.Cors -Version 2.1.0

Now open class “Startup” again and add the highlighted line of code (line 8) to the method “Configuration” as the below:

public void Configuration(IAppBuilder app)
        {
            HttpConfiguration config = new HttpConfiguration();

            ConfigureOAuth(app);

            WebApiConfig.Register(config);
            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
            app.UseWebApi(config);

        }

Step 12: Testing the Back-end API

Assuming that you registered the username “Taiseer” with password “SuperPass” in the step below, we’ll use the same username to generate token, so to test this out open your favorite REST client application in order to issue HTTP requests to generate token for user “Taiseer”. For me I’ll be using PostMan.

Now we’ll issue a POST request to the endpoint http://ngauthenticationapi.azurewebsites.net/token the request will be as the image below:

OAuth Token Request

Notice that the content-type and payload type is “x-www-form-urlencoded” so the payload body will be on form (grant_type=password&username=”Taiseer”&password=”SuperPass”). If all is correct you’ll notice that we’ve received signed token on the response.

As well the “grant_type” Indicates the type of grant being presented in exchange for an access token, in our case it is password.

Now we want to use this token to request the secure data using the end point http://ngauthenticationapi.azurewebsites.net/api/orders so we’ll issue GET request to the end point and will pass the bearer token in the Authorization header, so for any secure end point we’ve to pass this bearer token along with each request to authenticate the user.

Note: that we are not transferring the username/password as the case of Basic authentication.

The GET request will be as the image below:

Token Get Secure Resource

If all is correct we’ll receive HTTP status 200 along with the secured data in the response body, if you try to change any character with signed token you directly receive HTTP status code 401 unauthorized.

Now our back-end API is ready to be consumed from any front end application or native mobile app.

You can check the demo application, play with the back-end API for learning purposes (http://ngauthenticationapi.azurewebsites.net), and check the source code on Github.

Follow me on Twitter @tjoudeh

References

 

The post Token Based Authentication using ASP.NET Web API 2, Owin, and Identity appeared first on Bit of Technology.

AngularJS Token Authentication using ASP.NET Web API 2, Owin, and Identity

$
0
0

This is the second part of AngularJS Token Authentication using  ASP.NET Web API 2 and Owin middleware, you can find the first part using the link below:

Token Based Authentication using ASP.NET Web API 2, Owin middleware, and ASP.NET Identity – Part 1.

You can check the demo application on (http://ngAuthenticationWeb.azurewebsites.net), play with the back-end API for learning purposes (http://ngauthenticationapi.azurewebsites.net), and check the source code on Github.

AngularJS Authentication

In this post we’ll build sample SPA using AngularJS, this application will allow the users to do the following:

  • Register in our system by providing username and password.
  • Secure certain views from viewing by authenticated users (Anonymous users).
  • Allow registered users to log-in and keep them logged in for 24 hours or until they log-out from the system, this should be done using tokens.

If you are new to AngularJS, you can check my other tutorial which provides step by step instructions on how to build SPA using AngularJS, it is important to understand the fundamentals aspects of AngularJS before start working with it, in this tutorial I’ll assume that reader have basic understanding of how AngularJS works.

Step 1: Download Third Party Libraries

To get started we need to download all libraries needed in our application:

  • AngularJS: We’ll serve AngularJS from from CDN, the version is 1.2.16
  • Loading Bar: We’ll use the loading bar as UI indication for every XHR request the application will made, to get this plugin we need to download it from here.
  • UI Bootstrap theme: to style our application, we need to download a free bootstrap ready made theme from http://bootswatch.com/ I’ve used a theme named “Yeti”.

Step 2: Organize Project Structure

You can use your favorite IDE to build the web application, the app is completely decoupled from the back-end API, there is no dependency on any server side technology here, in my case I’m using Visual Studio 2013 so add new project named “AngularJSAuthentication.Web” to the solution we created in the previous post, the template for this project is “Empty” without any core dependencies checked.

After you add the project you can organize your project structure as the image below, I prefer to contain all the AngularJS application and resources files we’ll create in folder named “app”.

AngularJS Project Structure

Step 3: Add the Shell Page (index.html)

Now we’ll add the “Single Page” which is a container for our application, it will contain the navigation menu and AngularJS directive for rendering different application views “pages”. After you add the “index.html” page to project root we need to reference the 3rd party JavaScript and CSS files needed as the below:

<!DOCTYPE html>
<html data-ng-app="AngularAuthApp">
<head>
    <meta content="IE=edge, chrome=1" http-equiv="X-UA-Compatible" />
    <title>AngularJS Authentication</title>
    <link href="content/css/bootstrap.min.css" rel="stylesheet" />
    <link href="content/css/site.css" rel="stylesheet" />
<link href="content/css/loading-bar.css" rel="stylesheet" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top" role="navigation" data-ng-controller="indexController">
        <div class="container">
            <div class="navbar-header">
                  <button class="btn btn-success navbar-toggle" data-ng-click="navbarExpanded = !navbarExpanded">
                        <span class="glyphicon glyphicon-chevron-down"></span>
                    </button>
                <a class="navbar-brand" href="#/">Home</a>
            </div>
            <div class="collapse navbar-collapse" data-collapse="!navbarExpanded">
                <ul class="nav navbar-nav navbar-right">
                    <li data-ng-hide="!authentication.isAuth"><a href="#">Welcome {{authentication.userName}}</a></li>
                    <li data-ng-hide="!authentication.isAuth"><a href="#/orders">My Orders</a></li>
                    <li data-ng-hide="!authentication.isAuth"><a href="" data-ng-click="logOut()">Logout</a></li>
                    <li data-ng-hide="authentication.isAuth"> <a href="#/login">Login</a></li>
                    <li data-ng-hide="authentication.isAuth"> <a href="#/signup">Sign Up</a></li>
                </ul>
            </div>
        </div>
    </div>
    <div class="jumbotron">
        <div class="container">
            <div class="page-header text-center">
                <h1>AngularJS Authentication</h1>
            </div>
            <p>This single page application is built using AngularJS, it is using OAuth bearer token authentication, ASP.NET Web API 2, OWIN middleware, and ASP.NET Identity to generate tokens and register users.</p>
        </div>
    </div>
    <div class="container">
        <div data-ng-view="">
        </div>
    </div>
    <hr />
    <div id="footer">
        <div class="container">
            <div class="row">
                <div class="col-md-6">
                    <p class="text-muted">Created by Taiseer Joudeh. Twitter: <a target="_blank" href="http://twitter.com/tjoudeh">@tjoudeh</a></p>
                </div>
                <div class="col-md-6">
                    <p class="text-muted">Taiseer Joudeh Blog: <a target="_blank" href="http://bitoftech.net">bitoftech.net</a></p>
                </div>
            </div>
        </div>
    </div>
    <!-- 3rd party libraries -->
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular-route.min.js"></script>
    <script src="scripts/angular-local-storage.min.js"></script>
    <script src="scripts/loading-bar.min.js"></script>
    <!-- Load app main script -->
    <script src="app/app.js"></script>
    <!-- Load services -->
    <script src="app/services/authInterceptorService.js"></script>
    <script src="app/services/authService.js"></script>
    <script src="app/services/ordersService.js"></script>
    <!-- Load controllers -->
    <script src="app/controllers/indexController.js"></script>
    <script src="app/controllers/homeController.js"></script>
    <script src="app/controllers/loginController.js"></script>
    <script src="app/controllers/signupController.js"></script>
    <script src="app/controllers/ordersController.js"></script>
</body>
</html>

Step 4: “Booting up” our Application and Configure Routes

We’ll add file named “app.js” in the root of folder “app”, this file is responsible to create modules in applications, in our case we’ll have a single module called “AngularAuthApp”, we can consider the module as a collection of services, directives, filters which is used in the application. Each module has configuration block where it gets applied to the application during the bootstrap process.

As well we need to define and map the views with the controllers so open “app.js” file and paste the code below:

var app = angular.module('AngularAuthApp', ['ngRoute', 'LocalStorageModule', 'angular-loading-bar']);

app.config(function ($routeProvider) {

    $routeProvider.when("/home", {
        controller: "homeController",
        templateUrl: "/app/views/home.html"
    });

    $routeProvider.when("/login", {
        controller: "loginController",
        templateUrl: "/app/views/login.html"
    });

    $routeProvider.when("/signup", {
        controller: "signupController",
        templateUrl: "/app/views/signup.html"
    });

    $routeProvider.when("/orders", {
        controller: "ordersController",
        templateUrl: "/app/views/orders.html"
    });

    $routeProvider.otherwise({ redirectTo: "/home" });
});

app.run(['authService', function (authService) {
    authService.fillAuthData();
}]);

So far we’ve defined and mapped 4 views to their corresponding controllers as the below:

Orders View

Step 5: Add AngularJS Authentication Service (Factory)

This AngularJS service will be responsible for signing up new users, log-in/log-out registered users, and store the generated token in client local storage so this token can be sent with each request to access secure resources on the back-end API, the code for AuthService will be as the below:

'use strict';
app.factory('authService', ['$http', '$q', 'localStorageService', function ($http, $q, localStorageService) {

    var serviceBase = 'http://ngauthenticationapi.azurewebsites.net/';
    var authServiceFactory = {};

    var _authentication = {
        isAuth: false,
        userName : ""
    };

    var _saveRegistration = function (registration) {

        _logOut();

        return $http.post(serviceBase + 'api/account/register', registration).then(function (response) {
            return response;
        });

    };

    var _login = function (loginData) {

        var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;

        var deferred = $q.defer();

        $http.post(serviceBase + 'token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) {

            localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });

            _authentication.isAuth = true;
            _authentication.userName = loginData.userName;

            deferred.resolve(response);

        }).error(function (err, status) {
            _logOut();
            deferred.reject(err);
        });

        return deferred.promise;

    };

    var _logOut = function () {

        localStorageService.remove('authorizationData');

        _authentication.isAuth = false;
        _authentication.userName = "";

    };

    var _fillAuthData = function () {

        var authData = localStorageService.get('authorizationData');
        if (authData)
        {
            _authentication.isAuth = true;
            _authentication.userName = authData.userName;
        }

    }

    authServiceFactory.saveRegistration = _saveRegistration;
    authServiceFactory.login = _login;
    authServiceFactory.logOut = _logOut;
    authServiceFactory.fillAuthData = _fillAuthData;
    authServiceFactory.authentication = _authentication;

    return authServiceFactory;
}]);

Now by looking on the method “_saveRegistration” you will notice that we are issuing HTTP Post to the end point “http://ngauthenticationapi.azurewebsites.net/api/account/register” defined in the previous post, this method returns a promise which will be resolved in the controller.

The function “_login” is responsible to send HTTP Post request to the endpoint “http://ngauthenticationapi.azurewebsites.net/token”, this endpoint will validate the credentials passed and if they are valid it will return an “access_token”. We have to store this token into persistence medium on the client so for any subsequent requests for secured resources we’ve to read this token value and send it in the “Authorization” header with the HTTP request.

Notice that we have configured the POST request for this endpoint to use “application/x-www-form-urlencoded” as its Content-Type and sent the data as string not JSON object.

The best way to store this token is to use AngularJS module named “angular-local-storage” which gives access to the browsers local storage with cookie fallback if you are using old browser, so I will depend on this module to store the token and the logged in username in key named “authorizationData”. We will use this key in different places in our app to read the token value from it.

As well we’ll add object named “authentication” which will store two values (isAuth, and username). This object will be used to change the layout for our index page.

Step 6: Add the Signup Controller and its View

The view for the signup is simple so open file named “signup.html” and add it under folders “views” open the file and paste the HTML below:

<form class="form-login" role="form">
    <h2 class="form-login-heading">Sign up</h2>
    <input type="text" class="form-control" placeholder="Username" data-ng-model="registration.userName" required autofocus>
    <input type="password" class="form-control" placeholder="Password" data-ng-model="registration.password" required>
    <input type="password" class="form-control" placeholder="Confirm Password" data-ng-model="registration.confirmPassword" required>
    <button class="btn btn-lg btn-info btn-block" type="submit" data-ng-click="signUp()">Submit</button>
    <div data-ng-hide="message == ''" data-ng-class="(savedSuccessfully) ? 'alert alert-success' : 'alert alert-danger'">
        {{message}}
    </div>
</form>

Now we need to add controller named “signupController.js” under folder “controllers”, this controller is simple and will contain the business logic needed to register new users and call the “saveRegistration” method we’ve created in “authService” service, so open the file and paste the code below:

'use strict';
app.controller('signupController', ['$scope', '$location', '$timeout', 'authService', function ($scope, $location, $timeout, authService) {

    $scope.savedSuccessfully = false;
    $scope.message = "";

    $scope.registration = {
        userName: "",
        password: "",
        confirmPassword: ""
    };

    $scope.signUp = function () {

        authService.saveRegistration($scope.registration).then(function (response) {

            $scope.savedSuccessfully = true;
            $scope.message = "User has been registered successfully, you will be redicted to login page in 2 seconds.";
            startTimer();

        },
         function (response) {
             var errors = [];
             for (var key in response.data.modelState) {
                 for (var i = 0; i < response.data.modelState[key].length; i++) {
                     errors.push(response.data.modelState[key][i]);
                 }
             }
             $scope.message = "Failed to register user due to:" + errors.join(' ');
         });
    };

    var startTimer = function () {
        var timer = $timeout(function () {
            $timeout.cancel(timer);
            $location.path('/login');
        }, 2000);
    }

}]);

Step 6: Add the log-in Controller and its View

The view for the log-in is simple so open file named “login.html” and add it under folders “views” open the file and paste the HTML below:

<form class="form-login" role="form">
    <h2 class="form-login-heading">Login</h2>
    <input type="text" class="form-control" placeholder="Username" data-ng-model="loginData.userName" required autofocus>
    <input type="password" class="form-control" placeholder="Password" data-ng-model="loginData.password" required>
    <button class="btn btn-lg btn-info btn-block" type="submit" data-ng-click="login()">Login</button>
     <div data-ng-hide="message == ''" class="alert alert-danger">
        {{message}}
    </div>
</form>

Now we need to add controller named “loginController.js” under folder “controllers”, this controller will be responsible to redirect authenticated users only to the orders view, if you tried to request the orders view as anonymous user, you will be redirected to log-in view. We’ll see in the next steps how we’ll implement the redirection for anonymous users to the log-in view once users request a secure view.

Now open the “loginController.js” file and paste the code below:

'use strict';
app.controller('loginController', ['$scope', '$location', 'authService', function ($scope, $location, authService) {

    $scope.loginData = {
        userName: "",
        password: ""
    };

    $scope.message = "";

    $scope.login = function () {

        authService.login($scope.loginData).then(function (response) {

            $location.path('/orders');

        },
         function (err) {
             $scope.message = err.error_description;
         });
    };

}]);

Step 7: Add AngularJS Orders Service (Factory)

This service will be responsible to issue HTTP GET request to the end point “http://ngauthenticationapi.azurewebsites.net/api/orders” we’ve defined in the previous post, if you recall we added “Authorize” attribute to indicate that this method is secured and should be called by authenticated users, if you try to call the end point directly you will receive HTTP status code 401 Unauthorized.

So add new file named “ordersService.js” under folder “services” and paste the code below:

'use strict';
app.factory('ordersService', ['$http', function ($http) {

    var serviceBase = 'http://ngauthenticationapi.azurewebsites.net/';
    var ordersServiceFactory = {};

    var _getOrders = function () {

        return $http.get(serviceBase + 'api/orders').then(function (results) {
            return results;
        });
    };

    ordersServiceFactory.getOrders = _getOrders;

    return ordersServiceFactory;

}]);

By looking at the code above you’ll notice that we are not setting the “Authorization” header and passing the bearer token we stored in the local storage earlier in this service, so we’ll receive 401 response always! Also we are not checking if the response is rejected with status code 401 so we redirect the user to the log-in page.

There is nothing prevent us from reading the stored token from the local storage and checking if the response is rejected inside this service, but what if we have another services that needs to pass the bearer token along with each request? We’ll end up replicating this code for each service.

To solve this issue we need to find a centralized place so we add this code once so all other services interested in sending bearer token can benefit from it, to do so we need to use “AngualrJS Interceptor“.

Step 8: Add AngularJS Interceptor (Factory)

Interceptor is regular service (factory) which allow us to capture every XHR request and manipulate it before sending it to the back-end API or after receiving the response from the API, in our case we are interested to capture each request before sending it so we can set the bearer token, as well we are interested in checking if the response from back-end API contains errors which means we need to check the error code returned so if its 401 then we redirect the user to the log-in page.

To do so add new file named “authInterceptorService.js” under “services” folder and paste the code below:

'use strict';
app.factory('authInterceptorService', ['$q', '$location', 'localStorageService', function ($q, $location, localStorageService) {

    var authInterceptorServiceFactory = {};

    var _request = function (config) {

        config.headers = config.headers || {};

        var authData = localStorageService.get('authorizationData');
        if (authData) {
            config.headers.Authorization = 'Bearer ' + authData.token;
        }

        return config;
    }

    var _responseError = function (rejection) {
        if (rejection.status === 401) {
            $location.path('/login');
        }
        return $q.reject(rejection);
    }

    authInterceptorServiceFactory.request = _request;
    authInterceptorServiceFactory.responseError = _responseError;

    return authInterceptorServiceFactory;
}]);

By looking at the code above, the method “_request” will be fired before $http sends the request to the back-end API, so this is the right place to read the token from local storage and set it into “Authorization” header with each request. Note that I’m checking if the local storage object is nothing so in this case this means the user is anonymous and there is no need to set the token with each XHR request.

Now the method “_responseError” will be hit after the we receive a response from the Back-end API and only if there is failure status returned. So we need to check the status code, in case it was 401 we’ll redirect the user to the log-in page where he’ll be able to authenticate again.

Now we need to push this interceptor to the interceptors array, so open file “app.js” and add the below code snippet:

app.config(function ($httpProvider) {
    $httpProvider.interceptors.push('authInterceptorService');
});

By doing this there is no need to setup extra code for setting up tokens or checking the status code, any AngularJS service executes XHR requests will use this interceptor. Note: this will work if you are using AngularJS service $http or $resource.

Step 9: Add the Index Controller

Now we’ll add the Index controller which will be responsible to change the layout for home page i.e (Display Welcome {Logged In Username}, Show My Orders Tab), as well we’ll add log-out functionality on it as the image below.

Index Bar

Taking in consideration that there is no straight way to log-out the user when we use token based approach, the work around we can do here is to remove the local storage key “authorizationData” and set some variables to their initial state.

So add a file named “indexController.js”  under folder “controllers” and paste the code below:

'use strict';
app.controller('indexController', ['$scope', '$location', 'authService', function ($scope, $location, authService) {

    $scope.logOut = function () {
        authService.logOut();
        $location.path('/home');
    }

    $scope.authentication = authService.authentication;

}]);

Step 10: Add the Home Controller and its View

This is last controller and view we’ll add to complete the app, it is simple view and empty controller which is used to display two boxes for log-in and signup as the image below:

Home View

So add new file named “homeController.js” under the “controllers” folder and paste the code below:

'use strict';
app.controller('homeController', ['$scope', function ($scope) {
   
}]);

As well add new file named “home.html” under “views” folder and paste the code below:

<div class="row">
        <div class="col-md-2">
            &nbsp;
        </div>
        <div class="col-md-4">
            <h2>Login</h2>
            <p class="text-primary">If you have Username and Password, you can use the button below to access the secured content using a token.</p>
            <p><a class="btn btn-info" href="#/login" role="button">Login &raquo;</a></p>
        </div>
        <div class="col-md-4">
            <h2>Sign Up</h2>
            <p class="text-primary">Use the button below to create Username and Password to access the secured content using a token.</p>
            <p><a class="btn btn-info" href="#/signup" role="button">Sign Up &raquo;</a></p>
        </div>
        <div class="col-md-2">
            &nbsp;
        </div>
    </div>

By now we should have SPA which uses the token based approach to authenticate users.

One side note before closing: The redirection for anonymous users to log-in page is done on client side code; so any malicious user can tamper with this. It is very important to secure all back-end APIs as we implemented on this tutorial and not to depend on client side code only.

That’s it for now! Hopefully this two posts will be beneficial for folks looking to use token based authentication along with ASP.NET Web API 2 and Owin middleware.

I would like to hear your feedback and comments if there is a better way to implement this especially redirection users to log-in page when the are anonymous.

You can check the demo application on (http://ngAuthenticationWeb.azurewebsites.net), play with the back-end API for learning purposes (http://ngauthenticationapi.azurewebsites.net), and check the source code on Github.

Follow me on Twitter @tjoudeh

The post AngularJS Token Authentication using ASP.NET Web API 2, Owin, and Identity appeared first on Bit of Technology.

AngularJS Authentication with Auth0 & ASP .Net OWIN

$
0
0
This is guest post written originally to Auth0.

Recently I’ve blogged about using tokens to authenticate users in single page applications, I’ve used ASP.NET Web API, Owin middleware and ASP.NET Identity to store local accounts in database, I didn’t tap into social identity logins such as (Google, Microsoft Accounts, Facebook, etc..) because each provider will not supply the same information (profile schema) about the logged in user, there might be properties missing or with different names, so handling this manually and storing those different schemes will not be a straight forward process.

I was introduced to Auth0 by Matias Woloski, basically Auth0 is a feature rich identity management system which supports local database accounts, integration with more than 30 social identity providers, and enterprise identity providers such as (AD, Office 365, Google Apps, etc…). You can check the full list here.

In this post I’ll implement the same set of features I’ve implemented previously using Auth0 management system as well I’ll integrate authentication with multiple social identity providers using less code in the back-end API and in the front-end application which will be built using AngularJS. So let’s jump to the implementation.

I’ll split this post into two sections, the first section will be for creating the back-end API and configuring Auth0 application, and the second section will cover creating the SPA and Auth0 widget.

The demo application we’ll build in this post can be accessed from (http://auth0web.azurewebsites.net). The source code is available on my GitHub Repo.

Section 1: Building the Back-end API

Step 1.1: Create new Application in Auth0

After you register with Autho you need to create an application, Auth0 comes with set of applications with easy to integrate SDKs, in our case we’ll select “ASP.NET (OWIN)” application as the image below:

OWIN Application

After you give the application a friendly name, in my case I named it “ASP.NET (OWIN)” a popup window will show up asking which connections you want to enable for this application. “Connection” in Auth0 means identity providers you want to allow in the application, in my case I’ll allow Database local accounts, Facebook, Google, GitHub, and Microsoft Accounts as the image below. Usually the social accounts will be disabled for all applications, to enable them navigate to “Connections” tab, choose “Social” then enable the social providers you like to enable for your application.

Social Connections

Once the application is created, you can navigate to application “settings” link where you will find all the needed information (Domain, Client Id, Client Secret, Callback URLs, etc…) to configure the Web API we’ll build in the next step.

App Settings

Step 1.2: Create the Web API

In this tutorial I’m using Visual Studio 2013 and .Net framework 4.5, you can follow along using Visual Studio 2012 but you need to install Web Tools 2013.1 for VS 2012 by visiting this link.

Now create an empty solution and name it “AuthZero” then add new ASP.NET Web application named “AuthZero.API”, the selected template for the project will be “Empty” template with no core dependencies, check the image below:

WebAPIProject

Step 1.3: Install the needed NuGet Packages

This project is empty so we need to install the NuGet packages needed to setup our Owin server and configure ASP.NET Web API to be hosted within an Owin server, so open NuGet Package Manager Console and install the below packages:

Install-Package Microsoft.AspNet.WebApi -Version 5.1.2
Install-Package Microsoft.AspNet.WebApi.Owin -Version 5.1.2
Install-Package Microsoft.Owin.Host.SystemWeb -Version 2.1.0
Install-Package Microsoft.Owin.Security.Jwt -Version 2.1.0
Install-Package Microsoft.Owin.Cors -Version 2.1.0
Update-Package System.IdentityModel.Tokens.Jwt

The first package “Microsoft.AspNet.WebApi” contains everything we need to host our API on IIS, the second package “Microsoft.AspNet.WebApi.Owin” will allow us to host Web API within an Owin server.

The third package “Microsoft.Owin.Host.SystemWeb” will be used to enable our Owin server to run our API on IIS using ASP.NET request pipeline as eventually we’ll host this API on Microsoft Azure Websites which uses IIS.

The forth package “Microsoft.Owin.Security.Jwt” will enable Owin server Middleware to protect and validate JSON Web Tokens (JWT).

The last package “Microsoft.Owin.Cors” will be responsible to allow CORS for our Web API so it will accept requests coming from any origin.

Note: The package “System.IdentityModel.Tokens.Jwt” gets installed by default is old (version 1.0.0) so we need to update it to latest (version 3.0.2).

Step 1.4: Add Auth0 settings to Web.config

We need to read the Auth0 settings for the application we created earlier to configure our API, so open Web.Config file and add the below keys, do not forget to replace the values of those keys with the correct one you obtain once you create application on Auth0.

<appSettings>
     <add key="auth0:ClientId" value="YOUR_CLIENT_ID" />
     <add key="auth0:ClientSecret" value="YOUR_CLIENT_SECRET" />
     <add key="auth0:Domain" value="YOUR_DOMAIN" />
  </appSettings>

Step 1.5: Add Owin “Startup” Class

Now we want to add new class named “Startup”. It will contain the code below:

[assembly: OwinStartup(typeof(AuthZero.API.Startup))]
namespace AuthZero.API
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            HttpConfiguration config = new HttpConfiguration();

            ConfigureAuthZero(app);

            WebApiConfig.Register(config);
            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
            app.UseWebApi(config);

        }
    }
}

What we’ve implemented above is simple, this class will be fired once our server starts, notice the “assembly” attribute which states which class to fire on start-up. The “Configuration” method accepts parameter of type “IAppBuilder” this parameter will be supplied by the host at run-time. This “app” parameter is an interface which will be used to compose the application for our Owin server.

The implementation of method “ConfigureAuthZero” will be covered in the next step, this method will be responsible to configure our Web API to generate JWT using Auth0 application we created earlier.

The “HttpConfiguration” object is used to configure API routes, so we’ll pass this object to method “Register” in “WebApiConfig” class.

Lastly, we’ll pass the “config” object to the extension method “UseWebApi” which will be responsible to wire up ASP.NET Web API to our Owin server pipeline.

The implementation of “WebApiConfig” is simple, all you need to do is to add this class under the folder “App_Start” then paste the code below:

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
            jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        }
    }

Step 1.6: Configure generating JWT using Auth0

Now we want to configure our Web API to use Auth0 application created earlier to generate JSON Web Tokens which will be used to allow authenticated users to access the secured methods in our Web API. So to implement this open class “Startup” and add the code below:

//Rest of Startup class implementation is here

private void ConfigureAuthZero(IAppBuilder app)
        {
            var issuer = "https://" + ConfigurationManager.AppSettings["auth0:Domain"] + "/";
            var audience = ConfigurationManager.AppSettings["auth0:ClientId"];
            var secret = TextEncodings.Base64.Encode(TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["auth0:ClientSecret"]));

            // Api controllers with an [Authorize] attribute will be validated with JWT
            app.UseJwtBearerAuthentication(
                new JwtBearerAuthenticationOptions
                {
                    AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
                    AllowedAudiences = new[] { audience },
                    IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
                    {
                        new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret)
                    }
                });
        }

What we’ve implemented in this method is the following:

  • Read Autho application settings stored in the web.config file.
  • We’ve added the JSON Web Token Bearer middleware to our Owin server, this class accepts set of options, as you can see we’ve set the authentication mode to “Active” which configures the middleware to check every incoming request and attempt to authenticate the call, and if it is successful, it will create a principal that represents the current user and assign that principal to the hosting environment.
  • We’ve set the issuer of our JSON Web Token (Domain Name) along with the base64 encoded symmetric key (Client Secret) which will be used to sign the generated JSON Web Token.

Now if we want to secure any end point in our Web API, all we need to do is to attribute any Web API controller with “[Authorize]” attribute, so requests containing a valid bearer token can only access it.

Note: The JWT Token expiration time can be set from Autho Application settings as the image below, the default value is 36000 seconds (10 hours).

JWT Expiration

Step 1.7: Add a Secure Shipments Controller

Now we want to add a secure controller to serve our Shipments, we’ll assume that this controller will return shipments only for authenticated users, to keep things simple we’ll return static data. So add new controller named “ShipmentsController” and paste the code below:

[RoutePrefix("api/shipments")]
    public class ShipmentsController : ApiController
    {
        [Authorize]
        [Route("")]
        public IHttpActionResult Get()
        {
            return Ok(Shipment.CreateShipments());
        }
    }

    #region Helpers

    public class Shipment
    {
        public int ShipmentId { get; set; }
        public string Origin { get; set; }
        public string Destination { get; set; }

        public static List<Shipment> CreateShipments()
        {
            List<Shipment> ShipmentList = new List<Shipment> 
            {
                new Shipment {ShipmentId = 10248, Origin = "Amman", Destination = "Dubai" },
                new Shipment {ShipmentId = 10249, Origin = "Dubai", Destination = "Abu Dhabi"},
                new Shipment {ShipmentId = 10250,Origin = "Dubai", Destination = "New York"},
                new Shipment {ShipmentId = 10251,Origin = "Boston", Destination = "New Jersey"},
                new Shipment {ShipmentId = 10252,Origin = "Cairo", Destination = "Jeddah"}
            };

            return ShipmentList;
        }
    }

    #endregion

Notice how we added the “Authorize” attribute on the method “Get” so if you tried to issue HTTP GET request to the end point “http://localhost:port/api/shipments” you will receive HTTP status code 401 unauthorized because the request you sent till this moment doesn’t contain JWT in the authorization header. You can check it using this end point: http://auth0api.azurewebsites.net/api/shipments

Step 1.8: Add new user and Test the API

Auth0 dashboard allows you to manage users registered in the applications you created under Auth0, so to test the API we’ve created we need to create a user before, I’ll jump back to Auth0 dashboard and navigate to the “Users” tab then click “New”, a popup window will appear as the image below, this window will allow us to create local database user, so fill up the form to create new user, I’ll use email “taiseer.joudeh@hotmail.com” and password “87654321″.

Auth0 New User

Once the user is created we need to generate JWT token so we can access the secured end point, to generate JWT we can send HTTP POST request to the end point https://tjoudeh.auth0.com/oauth/ro this end point will work only for local database connections and AD/LDAP. You can check Auth0 API playground here. To get JWT token open your favorite REST client and issue POST request as the image below:

JWT Request

Notice that the content-type and payload type is “x-www-form-urlencoded” so the payload body will contain encoded URL, as well notice that we’ve specified the “Connection” for this token and the “grant_type” If all is correct we’ll received JWT token (id_token) on the response.

Note: The “grant_type” indicates the type of grant being presented in exchange for an access token, in our case it is password.

Now we want to use this token to request the secure data using the end point http://auth0api.azurewebsites.net/api/shipments so we’ll issue GET request to this end point and will pass the bearer JWT token in the Authorization header, so for any secure end point we have to pass this bearer token along with each request to authenticate the user.

The GET request will be as the image below:

Get Secure

If all is correct we’ll receive HTTP status 200 Ok along with the secured data in the response body, if you try to change any character with signed token you directly receive HTTP status code 401 unauthorized.

By now our back-end API is ready to be consumed by the front-end app we’ll build in the next section.

Section 2: Building the Front-end SPA

Now we want to build SPA using AngularJS which will communicate with the back-end API created earlier. Auth0 provides a very neat and feature rich JavaScript plugin named “Widget“. This widget is very easy to implement in any web app. When you use it you will get features out of the box such as social integration with social providers, integration with AD, and sign up/forgot password features. The widget plugin looks as the image below:

Auth0Widget

The enabled social login providers can be controlled from Autho dashboard using the “Connection” tab, so for example if you want to enable LinkedIn, you just need to activate it on your Auth0 application and it will show directly on the Widget.

Step 2.1: Add the Shell Page (Index.html)

First of all, we need to add the “Single Page” which is a container for our application, this page will contain a link to sign in, a section will show up for authenticated users only, and “ng-view” directive which will be used to load partial views. The html for this page will be as the below:

<!DOCTYPE html>
<html>
    <head>
        <link href="content/app.css" rel="stylesheet" />
        <link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
    </head>
    <body ng-app="auth0-sample" class="home" ng-controller="mainController">
        <div class="login-page clearfix">
          <div class="login-box auth0-box" ng-hide="loggedIn">
            <img src="https://i.cloudup.com/StzWWrY34s.png" />
            <h3>Auth0 Example</h3>
            <p>Zero friction identity infrastructure, built for developers</p>
             <a ng-click="login()" class="btn btn-primary btn-lg btn-block">SignIn</a>
          </div>
             <!-- This log in page would normally be done using routes
          but for the simplicity of the excercise, we're using ng-show -->
          <div ng-show="loggedIn" class="logged-in-box auth0-box">
            <img ng-src="{{auth.profile.picture}}" class="avatar"/>
            <h3>Welcome {{auth.profile.name}}</h3>
            <div class="profile-info row">
                <div class="profile-info-label col-xs-6">Nickname</div>
                <div class="profile-info-content col-xs-6">{{auth.profile.nickname}}</div>
            </div>
            <div class="profile-info row">
                <div class="profile-info-label col-xs-6">Your JSON Web Token</div>
                <div class="profile-info-content col-xs-6">{{auth.idToken | limitTo:12}}...</div>
                
            </div>
                 <div class="profile-info row">
                    <a ng-href ="#/shipments" class="btn btn-success btn-sm btn-block">View my shipments</a>
               </div>
               <div class="profile-info row">
                    <a ng-click="logout()" class="btn btn-danger btn-sm btn-block">Log out</a>
               </div>
          </div>
          <div data-ng-view="">
        </div>
        </div>
        <script src="https://code.angularjs.org/1.2.16/angular.min.js" type="text/javascript"></script>
        <script src="https://code.angularjs.org/1.2.16/angular-cookies.min.js" type="text/javascript"></script>
        <script src="https://code.angularjs.org/1.2.16/angular-route.min.js" type="text/javascript"></script>
        <script src="app/app.js" type="text/javascript"></script>
        <script src="app/controllers.js" type="text/javascript"></script>
    </body>
</html>

Step 2.2: Add reference for Auth0-angular.js and Widget libraries

Now we need to add a reference for file Auth0-angular.js, this file is AngularJS module which allows us to trigger the authentication process and parse the JSON Web Token with the “ClientID” we obtained once we created Auth0 application.

As well we need to add a reference for the “Widget” plugin which will be responsible to show the nice login popup we’ve showed earlier. To implement this and at the bottom of “index.html” page add a reference to those new JS files (line 5 and 6) as the code snippet below:

<!--rest of HTML is here--> 
<script src="https://code.angularjs.org/1.2.16/angular.min.js" type="text/javascript"></script>
<script src="https://code.angularjs.org/1.2.16/angular-cookies.min.js" type="text/javascript"></script>
<script src="https://code.angularjs.org/1.2.16/angular-route.min.js" type="text/javascript"></script>
<script src="https://cdn.auth0.com/w2/auth0-widget-4.js"></script>
<script src="https://cdn.auth0.com/w2/auth0-angular-0.4.js"> </script>
<script src="app/app.js" type="text/javascript"></script>
<script src="app/controllers.js" type="text/javascript"></script>

Step 2.3: Booting up our AngularJS app

We’ll add file named “app.js”, this file will be responsible to configure our AngularJS app, so add this file and paste the code below:

var app = angular.module('auth0-sample', ['auth0-redirect', 'ngRoute']);

app.config(function (authProvider, $httpProvider, $routeProvider) {
    authProvider.init({
        domain: 'tjoudeh.auth0.com',
        clientID: '80YvW9Bsa5P67RnMZRJfZv8jEsDSerDW',
        callbackURL: location.href
    });
});

By looking at the code above you will notice that we’ve injected the dependency “auth0-redirect” to our module, once it is injected we can use the “authProvider” service where we’ll use to configure the widget, so we need to set the values for the domain, clientID, and callBackURL. Those values are obtained from Autho application we’ve created earlier. Once you set the callbackURL you need to visit Auth0 application settings and set the same callbackURL as the image below:

Auth0 CallBack URL

The callbackURL is used once user is successfully authenticated, Auth0 will redirect user to the callbackURL with a hash containing an access_token and the JSON Web Token (id_token).

Step 2.4: Showing up the Widget Plugin

Now it is time to show the Widget once the user clicks on SignIn link, so we need to add file named “controllers.js”, inside this file we’ll define a controller named “mainController”, the implementation for this controller as the code below:

app.controller('mainController', ['$scope', '$location', 'auth', 'AUTH_EVENTS',
  function ($scope, $location, auth, AUTH_EVENTS) {

    $scope.auth = auth;
    $scope.loggedIn = auth.isAuthenticated;

    $scope.$on(AUTH_EVENTS.loginSuccess, function () {
      $scope.loggedIn = true;
      $location.path('/shipments');
    });
    $scope.$on(AUTH_EVENTS.loginFailure, function () {
      console.log("There was an error");
    });

    $scope.login = function () {
        auth.signin({popup: false});
    }

    $scope.logout = function () {
        auth.signout();
        $scope.loggedIn = false;
        $location.path('/');
    };

}]);

You can notice that we are injecting the “auth” service and “AUTH_EVENTS”, inside the “login” function we are just calling “auth.signin” and passing “popup:false” as an option,  the nice thing here that Auth0-angularjs module broadcasts events related to successful/unsuccessful logins so all child scopes which are interested to listen to this event can handle the login response. So in our case when the login is successful (User is authenticated) we’ll set flag named “loggedIn” to true and redirect the user to a secure partial view named “shipments” which we’ll add in the following steps.

Once the user is authenticated the JSON Web Token and the access token is stored automatically using AngularJS cookie store so you won’t worry about refreshing the single page application and losing the authenticated user context, all this is done by the Widget and Auth0-angularjs module.

Note: To check how to customize the Widget plugin check the link here.

As well we’ve added support for signing out the users, all we need to do is call “auth.signout” and redirect the user to the application root, the widget will take care of clearing the cookie store from the stored token.

Step 2.5: Add Shipments View and Controller

Now we want to add a view which should be accessed by authenticated users only, so we need to add new partial view named “shipments.html”, it will only renders the static data from the end point http://auth0api.azurewebsites.net/api/shipments when issuing GET request. The html for partial view as the below:

<div class="row">
    <div class="col-md-4">
        &nbsp;
    </div>
    <div class="col-md-4">
        <h5><strong>My Secured Shipments</strong> </h5>
        <table class="table table-striped table-bordered table-hover">
            <thead>
                <tr>
                    <th>Shipment ID</th>
                    <th>Origin</th>
                    <th>Destination</th>
                </tr>
            </thead>
            <tbody>
                <tr data-ng-repeat="shipment in shipments">
                    <td>
                        {{ shipment.shipmentId }}
                    </td>
                    <td>
                        {{ shipment.origin }}
                    </td>
                    <td>
                        {{ shipment.destination }}
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
    <div class="col-md-4">
        &nbsp;
    </div>

Now open file “controller.js” and add the implementation for “shipmentsController” as the code below:

app.controller('shipmentsController', ['$scope', '$http', '$location', function ($scope, $http, $location) {
    var serviceBase = "http://auth0api.azurewebsites.net/";
    $scope.shipments = [];
    init();

    function init() {
        getShipments();
    }
    function getShipments() {
        var shipmentsSuccess = function (response) {
            $scope.shipments = response.data;
        }
        var shipmentsFail = function (error) {
            if (error.status === 401) {
                $location.path('/');
            }
        }
        $http.get(serviceBase + 'api/shipments').then(shipmentsSuccess, shipmentsFail);
    }
}]);

The implementation for this controller is pretty straight forward. We are just sending HTTP GET request to the secured endpoint http://auth0api.azurewebsites.net/api/shipments, so if the call has succeeded we will set the returned shipments in $scope object named “shipments” and if it failed because the user is unauthorized (HTTP status code 401) then we’ll redirect the user to the application root.

Now to be able to access the secured end point we have to send the JSON Web Token in the authorization header for this request. As you notice we are not setting the token value inside this controller. The right way to do this is to use “AngularJS Interceptors”. Thanks for the Auth0-angularjs module which makes implementing this very simple. This interceptor will allow us to capture every XHR request and manipulate it before sending it to the back-end API so we’ll be able to set the bearer token if the token exists in the cookie store (user is authenticated).

Step 2.6: Add the Interceptor and Configure Routes

All you need to do to add the interceptor is to push it to $httpProvider service interceptors array. Setting the token with each request will be done by Auth0-angularjs module.

As well to configure the shipments route we need to map the “shipmentsController” with “shipments” partial view using $routeProvider service, so open “app.js” file again and replace all the code in it with the code snippet below:

var app = angular.module('auth0-sample', ['auth0-redirect', 'ngRoute', 'authInterceptor']);

app.config(function (authProvider, $httpProvider, $routeProvider) {
    authProvider.init({
        domain: 'tjoudeh.auth0.com',
        clientID: '80YvW9Bsa5P67RnMZRJfZv8jEsDSerDW',
        callbackURL: location.href
    });

    $httpProvider.interceptors.push('authInterceptor');

    $routeProvider.when("/shipments", {
        controller: "shipmentsController",
        templateUrl: "/app/views/shipments.html"
    });

    $routeProvider.otherwise({ redirectTo: "/" });
});

By completing this step we are ready to run the application and see how Auth0 simplified and enriched the experience of users authentication.

If all is implemented correctly, after you are authenticated using social login or database account your profile information and the secured shipments view will look as the image below:

LogedIn

That’s it for now folks!

I hope this step by step post will help you to integrate Auth0 with your applications, if you have any question please drop me a comment.

The post AngularJS Authentication with Auth0 & ASP .Net OWIN appeared first on Bit of Technology.

Viewing all 37 articles
Browse latest View live