Center any Image in div while maintaining Aspect Ratio

This is very useful to keep things under control on the page.

div {
    float:left; 
    width: 50vh;
    height: 50vh;
    position:relative;
    border: 1px solid red;
}

img {
   position: absolute;
    top: 50%;
    left: 50%;
    transform: translateX(-50%) translateY(-50%);
    max-width: 100%;
    max-height: 100%;
    border: 1px solid green;
}

Angular 7 Progress Indicator Component

I came across the following progress indicator for jquery and wanted to try to recreate it as an angular component.

<ol class="ProgressBar">
    <li #lis class="ProgressBar-step" *ngFor="let step of steps; let i = index">
      <svg class="ProgressBar-icon"><use attr.href="{{svgUrl}}"/></svg>

      <span class="ProgressBar-stepLabel">{{step}}</span>
    </li>
</ol>

The only modifications done to the HTML were adding a template variable #lis and iterating on the steps to be displayed.

xlink:href has been deprecated so it was replaced with attr.href and the svg was saved in a file and the path to the file is passed to the component. Styling is pretty much identical.

import { Component, OnInit } from '@angular/core';
import { ElementRef, QueryList, ViewChildren, Renderer2} from '@angular/core';
import { Input } from '@angular/core';

@Component({
  selector: 'app-progress-indicator',
  templateUrl: './progress-indicator.component.html',
  styleUrls: ['./progress-indicator.component.scss'],
})
export class ProgressIndicatorComponent {

  @Input() public steps: string[];
  @Input() public svgUrl:string;

  @ViewChildren('lis') lis: QueryList<ElementRef>;

  private elems: ElementRef<any>[];

  constructor(private renderer: Renderer2) {
  }

  advance() {
    this.elems = this.lis.toArray();
    var count = this.lis.filter(x => x.nativeElement.classList.contains('is-current')).length;
    if (count > 0) {
      let index = 0;
      for (let i = 0; i < this.elems.length; i++) {
        if (this.elems[i].nativeElement.classList.contains('is-current')) {
          index = i;
          break;
        }
      }
      if (index < this.elems.length) {
        if(index <  this.elems.length-1){ // if last one done remove current
             this.renderer.removeClass(this.elems[index].nativeElement, "is-current");
        }
        this.renderer.addClass(this.elems[index].nativeElement, "is-complete");
      } 
      if (index +1 < this.elems.length) {
        this.renderer.addClass(this.elems[++index].nativeElement, "is-current");
      }
    } else {
      this.renderer.addClass(this.lis.first.nativeElement, "is-current");
    }
  }

  previous(){
    this.elems = this.lis.toArray();
    var count = this.lis.filter(x => x.nativeElement.classList.contains('is-current')).length;
    if (count > 0) {
      let index = 0;
      for (let i = 0; i < this.elems.length; i++) {
        if (this.elems[i].nativeElement.classList.contains('is-current')) {
          index = i;
          break;
        }
      }
      if (index >= 0) {
         this.renderer.removeClass(this.elems[index].nativeElement, "is-current");
         this.renderer.removeClass(this.elems[index].nativeElement, "is-complete");
      }
      if(index > 0){
         this.renderer.addClass(this.elems[--index].nativeElement, "is-current");
        this.renderer.removeClass(this.elems[index].nativeElement, "is-complete")
      }
    }
  }
}

The component uses @ViewChildren to access the li tags and Renderer2 to do safe modifications to the classes of each element.

 <app-progress-indicator 
     [steps]='steps'  
     [svgUrl]='"./assets/svg/checkmark-bold.svg#checkmark-bold"'>
</app-progress-indicator>

Usage is as above steps should be an array of strings.

  public steps = ["Test","Review","Result","Mistakes"]; 

Note that QueryList is not accessible by index nor one could iterate on it for ES5 so toarray() was used to get things done. ES6 makes it possible to iterate directly.

Creating REST API Example with Laravel 5

This walkthrough should work on a VM described here

Assuming Database configuration is already set

in app/config/database.php or .env file

cd /var/www/dev1.local/laravel

Create Database Migration

In this example I decided to create a Courses table

php artisan make:migration create_courses_table --create=courses

Database Migration
Database Migration

 

Navigate with SFTP to /var/www/dev1.local/laravel/database/migrations

Edit the created file 2015_11_10_152128_create_courses_table.php and add the required fields.

Create Courses Table Migration file
Create Courses Table Migration file

 

Adding fields for example, Course name, Classroom, Teacher

$table->string(‘course_name’);
$table->string(‘classroom’);
$table->string(‘teacher’);

Adding Fields to migration
Adding Fields to migration

 

Migrating tables to MariaDB
Migrating tables to MariaDB

Database in SQLyog
Database in SQLyog

 

Create Models folder in  /var/www/dev1.local/laravel/app

mkdir /var/www/dev1.local/laravel/app/Models

Create Course Model

sudo vi  mkdir /var/www/dev1.local/laravel/app/Models/Course.php

Course Model
Course Model

 

Seeding the Database

cd /var/www/dev1.local/laravel/database/seeds

sudo vi CoursestTableSeeder.php

Courses Database Seeder
Courses Database Seeder

 

vi /var/www/dev1.local/laravel/database/seeds/DatabaseSeeder.php

Register CourseDatabaseSeeder
Register CourseDatabaseSeeder

 

composer dump-autoload

php artisan clear-compiled

Run php artisan db:seed

Seeding the database
Seeding the database SQLyog

Seeded data in database
Seeded data in database

Course Controller

php artisan make:controller CourseController

Creating a Controller for Courses
Creating a Controller for Courses

 

sudo vi /var/www/dev1.local/laravel/app/Http/Controllers/CourseController.php

Generated Controller Stub
Generated Controller Stub

 

Implementing the Controller

Add the following uses at the top

use DB;
use Response;
use Input;
use App\Models\Course;

Implementing some of the actions. Index, Store, Show, Delete

public function index()
{
return Response::json(Course::get());
}

public function store()
{
Course::create(array(
‘teacher’ => Input::get(‘teacher’),
‘classroom’ => Input::get(‘classroom’),
‘course_name’ => Input::get(‘course_name’)
));
return Response::json(array(‘success’ => true));
}

public function show($id)
{
$course = Course::find($id);
if(!isset($course)){
return $this->respondNotFound(‘Course does not exist’);
}
return $this->respond([
‘data’ => $this->transform($course)
]);
}

Creating Routes

sudo vi /var/www/dev1.local/laravel/app/Http/routes.php

Add

Route::group([‘prefix’ => ‘/api/v1’], function()
{
Route::resource(‘course’, ‘CourseController’ );
});

save and execute

php artisan route:list

Laravel Routes
Laravel Routes

Testing the API

http://dev1.local/index.php/api/v1/courses

or

http://dev1.local/api/v1/courses

API test
API test

 

Next Post is about Creating Angular based Front-end to consume the above API

Installing CentOS 7, Configuring Virtual Hosts and install Laravel 5 on each host

Download CentOS 7 ISO file mount it and create a VM in Virtualbox and boot

Select the following:

  • Simple webserver
  • PHP

yum install php-common

Open Firewall for Apache and register as service

firewall-cmd –permanent –add-service=http

firewall-cmd –reload

sudo systemctl enable httpd

Install MariaDB and register as service

Check if installed

rpm -qa | grep mariadb

yum install mariadb-server

sudo systemctl enable mariadb.service

mysql

> grant all on *.* to ‘sgalea’@’%’ identified by ‘bitnami’ with grant option;

quit

 

sudo vi /etc/my.cnf

[mysqld]

skip-grant-tables

 

Enable External connections to the database

firewall-cmd –permanent –add-service=mysql

firewall-cmd –reload

 

yum -y install php-mysql

 

Install SFTP and enable as service

yum -y update

yum -y install vsftpd

Conf location: /etc/vsftpd/vsftpd.conf

sudo systemctl enable vsftpd

firewall-cmd –permanent –add-port=21/tcp

firewall-cmd –reload

 

Creating Virtual Hosts Settings

mkdir /etc/httpd/sites-available

mkdir /etc/httpd/sites-enabled

sudo vi /etc/httpd/conf/httpd.conf

Put the following at the end of file

IncludeOptional sites-enabled/*.conf

Esc :wq

Create a file per virtual host in /etc/httpd/sites-available

sudo vi /etc/httpd/sites-available/dev1.local.conf

<VirtualHost *:80>
ServerName  dev1.local
ServerAlias dev1.local
DocumentRoot /var/www/dev1.local/laravel/public
ErrorLog /var/www/dev1.local/logs/error.log
CustomLog /var/www/dev1.local/logs/requests.log combined
</VirtualHost>

sudo vi /etc/httpd/sites-available/dev2.local.conf

<VirtualHost *:80>
ServerName  dev2.local
ServerAlias dev2.local
DocumentRoot /var/www/dev2.local/laravel/public
ErrorLog /var/www/dev2.local/logs/error.log
CustomLog /var/www/dev2.local/logs/requests.log combined
</VirtualHost>

sudo vi /etc/httpd/sites-available/dev3.local.conf

<VirtualHost *:80>
ServerName  dev3.local
ServerAlias dev3.local
DocumentRoot /var/www/dev3.local/laravel/public
ErrorLog /var/www/dev3.local/logs/error.log
CustomLog /var/www/dev3.local/logs/requests.log combined
</VirtualHost>

https://www.digitalocean.com/community/tutorials/how-to-set-up-apache-virtual-hosts-on-centos-7

Enabling the hosts

sudo ln -s /etc/httpd/sites-available/dev1.local.conf /etc/httpd/sites-enabled/dev1.local.conf
sudo ln -s /etc/httpd/sites-available/dev2.local.conf /etc/httpd/sites-enabled/dev2.local.conf
sudo ln -s /etc/httpd/sites-available/dev3.local.conf /etc/httpd/sites-enabled/dev3.local.conf

Create folders

mkdir /var/www/dev1.local

mkdir /var/www/dev2.local

mkdir /var/www/dev3.local

sudo chmod -R 775 /var/www

Install Composer Globally

curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer

Install Laravel Dependencies

ext-mbstring
sudo yum install php-mbstring

ext-mcrypt

wget http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm

rpm -ivh epel-release-7-5.noarch.rpm

yum install php-mcrypt*

Install Laravel

navigate to the folder where one wishes to install it in my case

cd /var/www/dev1.local
composer create-project laravel/laravel –prefer-dist

cd /var/www/dev2.local
composer create-project laravel/laravel –prefer-dist

cd /var/www/dev3.local
composer create-project laravel/laravel –prefer-dist

 

Storage Folder needs write permissions in SELinux

su -c "chcon -R -h -t httpd_sys_script_rw_t /var/www/dev1.local/laravel/storage/"

su -c "chcon -R -h -t httpd_sys_script_rw_t /var/www/dev2.local/laravel/storage/"

su -c "chcon -R -h -t httpd_sys_script_rw_t /var/www/dev3.local/laravel/storage/"

chmod -R 777 /var/www/dev1.local/laravel/storage/

chmod -R 777 /var/www/dev2.local/laravel/storage/

chmod -R 777 /var/www/dev3.local/laravel/storage/

  • Not sure if 777 is a good idea here

We need a location for logs

mkdir /var/www/dev1.local/logs

su -c "chcon -R -h -t httpd_sys_script_rw_t /var/www/dev1.local/logs/"

mkdir /var/www/dev2.local/logs

su -c "chcon -R -h -t httpd_sys_script_rw_t /var/www/dev2.local/logs/"

mkdir /var/www/dev3.local/logs

su -c "chcon -R -h -t httpd_sys_script_rw_t /var/www/dev3.local/logs/"

 

sudo systemctl restart httpd.service

Check virtualhosts

httpd -S

Add virtual hosts in host file on your host OS

On windows: C:\Windows\System32\drivers\etc

edit host file as Administrator

192.168.101.12 dev1.local
192.168.101.12 dev2.local
192.168.101.12 dev3.local

Where 192.168.101.12 is the IP of your Virtual Machine running CentOS 7

Remove index.php from the url

sudo vi /etc/httpd/conf/httpd.conf

AllowOverride Access
AllowOverride Access

Change to:

AllowOverride All

 

Things required while debugging issues:

While debugging try without SELinux

Disable:

setenforce 0

Enable:

setenforce 1

These are not permanent they will be reset to default status after reboot.

Search string in file

grep -R ‘string’ dir/

Find IP

ip addr

Changing IP of the VM

sudo dhclient -r

sudo dhclient

__________________________________________________________________

http://stackoverflow.com/questions/17954625/services-json-failed-to-open-stream-permission-denied-in-laravel-4

Errorlogs location causes htttpd not reload

http://unix.stackexchange.com/questions/175558/apache-wont-restart-after-adding-virtualhost-conf-file-why-not

Blankscreen issue

http://stackoverflow.com/questions/20678360/laravel-blank-white-screen

ServerSetup

http://www.hexblot.com/blog/centos-7-server-installation

 

Next Post is about creating a REST API on Laravel 5 which can be found here

Configuring Laravel 5, FTP and MySQL on Bitnami LAMP Stack for Development

At the time of writing the Stack is running on Ubuntu 14.04 which can be downloaded from here. Since it is 64Bit make sure that Visualization is enabled in the bios settings.

Import the VM in VMware Player or Virtual box, make sure that the network settings are configured correctly so that the VM gets an IP accessible from the host machine. I personally configured it to Bridged Adapter for this exercise and have a habit of Regenerating the MAC Address.

VirtualBox Network Adapter Setup
VirtualBox Network Adapter Setup

If the VM does not get assigned an IP the configuration is wrong and I wouldn’t bother trying to fix it from inside the VM (you could) but I rather fix it from the hyper-visor settings because the stack is pre-configured to work.

Bitnami LAMP Stack with indication of IP
Bitnami LAMP Stack with indication of IP

Login and change password

 

Visit the IP in the browser to check if it is working in my case http://192.168.101.12

Bitnami Main Page
Bitnami Main Page

 

Enabling Laravel

Bitnami LAMP Stack comes with several pre-configured frameworks of which all are disabled by default. One must enable the framework that is required. ( I am nto sure if you can enable more than one at the same time)

Steps:

cd /opt/bitnami/apache2/conf/bitnami

sudo vi bitnami-apps-prefix.conf

Accessing LAMP PHP Framework Config
Accessing LAMP PHP Framework Config

 

Remove the hash from laravel’s line and save and close :wq

Enabling Laravel
Enabling Laravel

 

Restart Apache

sudo /opt/bitnami/ctlscript.sh restart apache

Restarting Apache
Restarting Apache

 

The location where Laravel apps Live is

/opt/bitnami/frameworks/laravel/app/http

Browser URL

http://192.168.101.12/laravel/ where 192.168.101.12 is your VM’s IP

 

Laravel Welcome Screen On Load
Laravel Welcome Screen On Load

 

Configuring FTP

Enabling FTP for easy editing/upload of files ( Note this is a development machine for experimentation so I will not go on explaining issues with FTP and security, but you should consider reading about the risks. )

 

sudo vi /etc/vsftpd.conf

go to the bottom of the file and change

listen_address=127.0.0.1

to

listen_address=0.0.0.0

:wq

Listen on every available network interface
Listen on every available network interface

Allow connections to port 21 (FTP port)

sudo ufw allow 21

Firewall Settings
Firewall Settings

Restart FTP

sudo service vsftpd restart

Restart vsftpd service
Restart vsftpd service

Change bitnamiftp password

sudo passwd bitnamiftp

Change Password for FTP user
Change Password for FTP user

Configure Filezilla

Filezilla FTP Settings
Filezilla FTP Settings

Connected

Connected to VM
Connected to VM

 

Now you may play around with Laravel through FTP 🙂

Let external connections to MySQL

1)

cd /opt/bitnami/mysql

sudo vi my.cnf

Comment out

bind-address = 127.0.0.1

by putting a # infront of it and Esc :wq

Modifying my.cnf to allow external connections
Modifying my.cnf to allow external connections

2)

 

mysql -u root -p
grant all privileges on *.* to 'root'@'%' identified by 'password' with grant option

Granting MySQL Permissions
Granting MySQL Permissions

 

restart mysql

cd /opt/bitnami

sudo ./ctlscript.sh restart mysql

Restart MySQL
Restart MySQL

 

Open Port in firewall

sudo ufw allow 3306

Open port 3306 in firewall
Open port 3306 in firewall

 

Connection Settings in SQLyog
Connection Settings in SQLyog

 

Connection Successful
Connection Successful

JavaScript BreakOut

A couple of weeks ago I was playing around with canvas for the first time I decided to give a try in recreating a BreakOut like game using JavaScript.

The game is developed using Object Oriented approach for better structure and the code is easier to handle.

I found that using multiple canvas with some CSS to overlay them is a better approach to minimize computations and separate things.

Breakout
Breakout

 

 

It is unfinished let alone polished.

Can be viewed at JSFiddle: here

Things missing

  • Menu
  • Ball moving with paddle before start
  • Instructions of play ( Left/Right/Space )
  • Score Keeping
  • Game calculations could be better
  • Level transition although loading mechanism is in place and levels can be described in JSON format.

Might get back to it at some point, but right now I’m working on something else.

Basic AngularJS (1.3.13) SPA

Being on the saga to master AngularJS I decided to post about a basic application with a  module and controller that returns static data to the view. The view and controller are married by routing. This post will not go in detail on how things work.

index.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" data-ng-app="app">
<head>
    <meta charset="utf-8" />
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular-route.min.js"></script>
    <script src="app.module.js"></script>
    <script src="app.config.js"></script>
    <script src="posts.module.js"></script>
    <script src="postsController.js"></script>
<body>
    <div>
      <div data-ng-view></div>
    </div>
</body>
</html>

line 2 defines data-ng-app=”app” which is an attribute Every angular application should have  (could live in other elements)

Line 8-11 are the JavaScript inclusion for the application (in a real website one would minify and merge the files together for faster loading)

Line 14 is where the view will be loaded     <div data-ng-view></div>

AngularJS is modular in such a way that one could separate functionality but one or more modules can be injected into another module for richer functionality.

app.module.js

(function () {
    'use strict';
    
    angular.module("app", [
        'ngRoute',
        'app.posts'
    ]);
   
})();

The main module’s name should match the data-ng-app=”app” as above

ngRoute and app.posts are injected modules that the app module will make use of.

ngRoute is a standard module that takes care of routing

app.posts is a custom module that is built for this application

app.config,js

(function(){
  'use strict';
  
    angular.module("app").config(['$routeProvider',
      function ($routeProvider) {
        $routeProvider
            .when('/', {
		  controller: 'postsController',
		  controllerAs: 'vm',
                  templateUrl: 'posts.html'
            })
            .otherwise({
                redirectTo:"/"
            });
     }
    ]);
});

Every module may have a configuration and this is the first thing that will execute from that module for initialization.  In this case the main module has routing initialized.

$routeProvider is where routing is setup.

in a nut shell the above is configuring that when visiting root ‘/’ use controller postsController with vm alias and use posts.html as a view template else redirect to root.

posts.module.js

(function () {
    'use strict';

    angular.module('app.posts', []);
    
})();

This is just the definition of posts module which has no dependencies. As one may notice it is almost the same as app.module.js

postsController.js

(function () {
    'use strict';

  // Register
  angular
        .module('app.posts')
        .controller('postsController',postsController);
        
 // Inject
 postsController.$inject = [];        

  // Function
 function postsController() {
    var vm = this;
    vm.persons = [
                   {
                      "Name":"Alfreds Futterkiste",
                      "City":"Berlin",
                      "Country":"Germany"
                   },
                   {
                      "Name":"Berglunds snabbkkp",
                      "City":"Luleb",
                      "Country":"Sweden"
                   }
                 ];
  }

})();

Controllers can be written in different ways but the most elegant (opinionated) is Register/Inject/Function

Register the controller with a function name

Inject parameters

Function is the controller’s logic. The variable vm stands for ViewModel because that’s exactly what it represents. and Some JSON data is set to a property in that view model.

posts.html

<ol>
    <li data-ng-repeat="person in vm.persons">
      {{ person.Name + ', ' + person.Country }} <br/>
    </li>
</ol>

This is the view template that will be loaded instead of <div data-ng-view></div>

data-ng-repeat means repeat this element for as much items in the list

The vm here is the alias that was defined in the routing and has nothing to do with the controller vm variable ( but for logical sense it is the same )

{{}} mean execute the expression in between which in this case are the Name and Country

 

here is the code

Same example but using $http request here

Best Practices learned so far

Always encapsulate your code as a module to avoid polluting the global namespace

Always use ‘use strict’;

Use employ single responsibility principle

Separate every thing in files and make sure you organize files by feature if the application is large

Code neatly and use indentation

Love the community: When posting on the internet about code always include a version number

Experts worth following

John Papa

Tod Motto 

Resources

Very good introduction by Dan Wahlin : https://www.youtube.com/watch?v=i9MHigUZKEM

www.angular-tips.com

www.scotch.io

www.egghead.io

https://angularjs.org/

https://www.ng-book.com/

Configuring IIS and Setting up Thinktecture v2 Identity Server

As the title indicate, this post is about installing IIS and Configuring ThinkTecture v2 up and running.

Run appwiz.cpl

Search and run app.wiz.cpl

Select IIS and required features

 

click “Turn windows features on or off” (1)

Tick  “IIS Management Console” (2)

Tick ASP.NET 4.5 (3)

 

It is of utmost importance that ASP.NET 4.5 is ticked else when one would attempt to navigate to thinktecture v2 the following HTTP Error 500.19 will pop up.

HTTP Error 500.19

3Wait for features to be found and installed.

 

4

 

click close

IISNavigate to Localhost

IIS is up and running. Next is Downloading ThinkTecture V2 configuring IIS  to serve ThinkTecture V2

ThinkTecture V2 Release

Visit https://github.com/IdentityServer/IdentityServer2/releases and download ThinkTecture V2

Follow along this video and everything should be fine https://vimeo.com/51088126ThinkTecture V2 Initial Landing Page

https://vimeo.com/51666380

ASP.NET Identity with Facebook (out of the box)

The following is a walk through of how to deal with authentication using Identity Providers mainly Facebook.

Open https://developers.facebook.com/

Add a New App
Add a New App

Click “Add a New App”

 

Add a New App
Add a New App

Click “WWW”

Create New Facebook App ID
Create New Facebook App ID

Click “Create New Facebook App ID”

Create New app ID/Details
Create New app ID/Details

Select Category and click “Create App ID”

Go to Visual studio 2013

New VS2013 Project
New VS2013 Project

Create new Project name it and select “ASP.NET Web application”

New VS2013 Project Selection
New VS2013 Project Selection

Set  Authentication to “Individual User Accounts” and Click Ok

Build and run your project and copy the local URL go to Facebook Development in your browser where you left off

Website URL
Website URL

Paste the url in “Site URL” and “Mobile site URL” in this case localhost:61617 and click next

 

Application DashBoard
Application DashBoard

Refresh the page click Show button near App Secret

 

Authentication
Authentication

Enter your Facebook Password

Go to visual studio

Startup Authentication
Startup Authentication

Navigate in solution explorer to App_start/start.auth.cs

Facebook App ID and App Secret
Facebook App ID and App Secret

Scroll down Facebook boilerplate authentication code. Paste App Id and App Secret and uncomment the three lines

Rebuild the Project and run

Log In
Log In

Once it opens in the browser click Login

Facebook Login
Facebook Login

On the left of the page there should be a Facebook button click it

Application Authorization
Application Authorization

Click okay to authorize

Associate E-mail address with account
Associate E-mail address with account

Enter E-mail address to associate with that Facebook account on your application

Display E-mail after authentication
Display E-mail after authentication

The e-mail will show every time the user is logged in.

That is how to authenticate a user using Facebook as an Identity Provider. Out of the box.

 

What’s else can we do with Facebook?

There a lot of things one can do with Facebook by using Facebook SDK the user can authorize your Web Site to access several Scopes. At the least one could skip the last two steps by requesting access to the e-mail and use that programmatically without the user having to type it.

The following is how to incorporate Facebook SDK in your project.

NuGet Manager
NuGet Manager

Facebook SDK
Facebook SDK

More info at http://www.nuget.org/packages/Facebook/7.0.5-beta

and https://developers.facebook.com/docs/graph-api

The guideline is do not ask for more data than your application really need, because once you lose trust of the users, your web site is dead.

 

.NET HTTPRequest

HTTP Handlers
They are used to process individual endpoints.
Only one handler per request is used
Can be both asynchronous or synchronous
Earliest possible point where you have access to requests

 

HTTPHandlers are extension based. This means that for every extension .aspx .html etc there is a handler (some share handler).

The example used here is very simple and does nothing special except for displaying some static text. The reason is that ideally before attempting to do something elaborate one should check if it works by doing something simple especially while learning.

The examples here were created in ASP.MVC5 applications. The extension that is used is .kk

Synchronous HTTP Handler

The Solution name is HTTP_Handler

Step 1:

Ignore routing for .kk extension in App_Start/RouteConfig.cs (The reason is that we do not want MVC to try to interpret this file)

routes.IgnoreRoute("{file}.kk");

Step 2:

We create the class that will be our handler at the top level  since this is an example and name it CustomHandler.cs

This can be achieved by inheriting IHttpHandler or by using IHttpHandlerFactory (The example uses IHttpHandler)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace HTTP_Handler
{
public class CustomHandler : IHttpHandler
{

public void ProcessRequest(HttpContext context)
{
HttpRequest Request = context.Request;
HttpResponse Response = context.Response;
Response.Write("test");
}

public bool IsReusable
{
get { return true; }
}
}
}

Step 3:

We configure the application to use the handler (Integrated mode).

In web.config

<system.webServer>

<handlers>

<add verb="*" path="*.kk" name="CustomHandler" type="HTTP_Handler.CustomHandler"/>

</handlers>

Step 4:

Build and Run

add hello.kk to the link and load it should print test on screen.

 Asynchronous HTTP Handler

 

The Solution name is HTTP_Async_Handler

Step 1:

Ignore routing for .kk extension in App_Start/RouteConfig.cs (The reason is that we do not want MVC to try to interpret this file)

routes.IgnoreRoute("{file}.kk");

Step 2:

We create the class that will be our handler at the top level  since this is an example and name it CustomHandler.cs

This can be achieved by inheriting IHttpAsyncHandler

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace HTTP_Async_Handler
{
public class CustomHandler:IHttpAsyncHandler
{
// Long Process
private static void generateNumbers(HttpContext context)
{
string s = "";
for (int i = 0; i < 1000; i++)
{
s = s + ' ' + i.ToString();
}
context.Response.Write(s);
}

public static Action<HttpContext> _Handle = generateNumbers;

public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
context.Response.Write("BeginProcessRequest Executed");
return _Handle.BeginInvoke(context,cb,extraData);
}

public void EndProcessRequest(IAsyncResult result)
{
// Clean up code here
}

public bool IsReusable
{
get { return true; }
}

public void ProcessRequest(HttpContext context)
{
context.Response.Write("ProcessRequest Executed Will not execute");
}
}
}

Step 3:

We configure the application to use the handler (Integrated mode).

In web.config

<system.webServer>

<handlers>

<add verb="*" path="*.kk" name="CustomHandler" type="HTTP_Handler.CustomHandler"/>

</handlers>

</system.webServer>

Step 4:

Build and Run

add hello.kk to the link and load it should print test on screen.

 

Want to know more?

Investigate IHttpHandlerFactory

Classic mode & Integrated mode (IIS)