Wednesday, November 23, 2016

ASP.NETCore: Create a Web API application


1. Introduction


This article will walk you through on building a simple web API service using .NETCore. Service is extended to interact with a SQL server database in a windows PC and then modify the same service to work with a MYSQL database in a Linux server.


2. Background



3. Prerequisites


In this article, we are working with two environments, Windows and a Linux environment. Check whether you have installed these prerequisites before you start.

In Windows environment,
In Linux environment,

I have used Entity framework Core to access data from databases, necessary references to EFCore is installed in next steps.


4. Create a Web API application in .NETCore


Let’s try to create a .NETCore application from Visual Studio 2015





























Create a new project from Visual Studio 2015, In .NETCore tab, select ASP.NET Core Web Application (.NET Core) . Give it a name and click on OK.



























Select Web API from ASP.NET Core templates and click on OK.





















Check folder structure of the application, It includes a Program.cs and Startup file. It includes a project.json file to define all required packages for your application. appsettings.json file maintains application settings same as web.config file in a ASP.NET Web application. Controllers folder has all Web API Controllers.


4.1. Open service application from Visual Studio Code.

















cd into the application directory and open Visual Studio Code using code . command. You can see folder structure of your application as above. Add assets to build and debug your application as the info dialog box suggests.










vscode folder is added into the solution with launch.json and tasks.json file.


4.2. Dependencies in project.json file


Let’s see what are the dependencies required for a mvc application.














Since We create a Web API application, in project.json file, It shows Microsoft.AspNetCore.Mvc package dependency.


4.3. Run ValuesController and check service calls.


Let’s run Web API application and check available services.





























Build (Ctrl + Shift + b) and run (Ctrl + F5) your application and ping to the Read service as above. Its shows return values in the browser.


4.4. Let’s build the movie service


In this solution, Movie service is accessing a SQL Server database on windows, and later the same application with less modifications, going to access a MYSql server database in a Linux server


4.4.1. Create Movie model






















namespace movieStore.Models
{
 public class Movie
  {
    public int ID { get; set; }
    public string Title { get; set; }
    public string Director { get; set; }
    public int Year { get; set; }
    public string Language { get; set; }
    }
}

Create a Model folder to define entities in your application. Then create Movie class and add properties into it. We follow Code First approach in this example. So when we create the database Movie table will be created.


4.5. Create Movie service with SQL server on Windows.

4.5.1. Create Context class to build the database.












namespace movieStore.Models
{
    public class MovieDbContext : DbContext
    {
        public MovieDbContext(DbContextOptions<MovieDbContext> options) : base(options)
        {
        }
        public DbSet<Movie> Movies { get; set; }
    }
}

From context class, our database will be generated. Context class should be inherited from DbContext class. In order to do that, we have to add references from Entityframework core.


4.5.2. Install Entityframework Core (EF Core)








Add entityframeworkcore reference as a dependency into project.json file, “Microsoft.EntityFrameworkCore”: “1.0.0” and resolve reference error in MovieDbContext class by adding using Microsoft.EntityFrameworkCore statement.


4.5.3. Define the connectionstring










Define the connectionstring in appsettings.json file to connect to the Sql server,

“ConnectionStrings: { “DefaultConnection”: “Data Source=localhost;Initial Catalog=movieDB;Integrated Security= true” }


4.5.4. Check MovieDbContext class


















In MovieDbContext class, define constructor with context options and call base class method.


4.5.5. Add entities in moviecontext class






Try to run migrations for MovieDbContext class,
 
 dotnet ef migrations add InitialMigration

It gives an error,

No executable found matching command “dotnet-ef”

We have to install entityframeworkcore tools to run migrations from .NET cli. Let’s try to do that.


4.5.6. Add EFCore tools








Add EFCore tools in tools section of project.json,

 "Microsoft.EntityframeworkCore.Tools" : "1.0.0-preview2-final"

Try to run migration and it gives an error again!!,

Could not invoke this command with the startup project ‘demo’. Check that ‘Microsoft.EntityFrameworkCore.Design’ has been added to “dependencies” in the startup project and that the version of ‘Microsoft.EntityFrameworkCore.Tools’ in “tools” and ‘Microsoft.EntityFrameworkCore.Design` are the same. See http://go.microsoft.com/fwlink/?LinkId=798221 for more details,

We haven’t added EFCore Design as a reference, We have to add EFCore Design references to run migrations scripts. Let’s add it and check. And also it mentions ‘Microsoft.EntityFrameworkCore.Design’ and ‘Microsoft.EntityFrameworkCore.Tools’ version should be same.


4.5.7. Add EFCore Design reference.








Add EFCore Design reference into project.json file. Note that, `Microsoft.EntityFrameworkCore.Design' and `Microsoft.EntityFrameworkCore.Tools' version are same.

 "Microsoft.EntityFrameworkCore.Design": "1.0.0-preview2-final"

Then try to run migrations command again and it gives another error,

No parameterless constructor was found on ‘MovieDbContext’. Either add a parameterless constructor to ‘MovieDbContext’ or add an implementation of ‘IDbContextFactory‘ in the same assembly as ‘MovieDbContext’.


4.5.8. Startup class implementation









public void ConfigureServices(IServiceCollection services)
   {
         services.AddDbContext<MovieDbContext>(options =>                                                                                                                            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
// Add framework services
services.AddMvc();
}

In Configure services method, it’s going to add some services into the application.

services.AddDbContext(options => options.UseSqlServer(Configuration.GetConnectionString(“DefaultConnection”)));

Add the database context and define the connectionstring of your database, in configure service method, it’s missing some references, since we haven't add any EntityframeworkCore sqlserver references.


4.5.9. Add EFCore Sqlserver references








Add EFCore Sql server reference in project.json file and restore them.

 “Microsoft.EntityFrameworkCore.SqlServer”: “1.0.0”

















Now sqlserver reference is added. Configure service method looks fine.


4.5.10. Run Migrations


Let’s create movieDB in sql server.
















Run Sqlserver migrations, It doesn’t give any errors in .NET CLI, Migrations folder is created with migrations scripts. In Initial Migration class, it defines Up and Down methods to create and drop movie table respectively.


4.5.11. Update the database









run commands to update the database. In sqlserver, movieDB got created.

 dotnet ef database update



4.5.12. Add Movie controller


In Visual studio code, We can’t use scaffolding. So i created a Movie Controller with all the CRUD operations of Movie entity in visual studio. Let’s add it.
























In Movie Controller, it works with application/json type data, and the route is api/Movies. Note that in .NET Core Api controllers inherit from Controller class, not from API Controller class.























Go to api/movies method and check Network tab in developer tools. method returns 200 - OK. as a response. We don’t have data in movie database, Let’s try to add some data.


4.5.13. Add data using Postman














Postman is a tool to test your service apis. Although we can test GET requests through browser, to test POST requests, we need to use Postman. Add a movie using Postman and retrieve it using web browser.

We have created a service API using .NETCore and SQLServer. Let’s try to run this same application on Ubuntu with MySQL.


4.6. Change Movie service to work with MYSQL on Linux server.

4.6.1. Clone your application in Ubuntu


Let’s try to open your application in Ubuntu, We are going to connect this application to MySQL server,











Type git clone … with repository url, Your project will be downloaded. Then cd into application directory and open it in visual studio code.


4.6.2. Restore packages and build your application












Restore packages defined in project.json file and Build your application. It all works fine.


4.6.3. Let’s try to run the application

















Let’s try to run our application without any modifications, It seems working fine. Let’s navigate to api/values , It calls READ service of Values service. It returns 200 - OK as response.















Ping to api/movies, it returns an empty array, since we don’t have a database.

Check the terminal and try to find any errors, It shows a fail error in red. It says 'Microsoft.EntityFrameworkCore.Query.Internal.SqlServerQueryCompilationContextFactory[1] An exception occurred in the database while iterating the results of a query. System.NotSupportedException: The keyword ‘integrated security’ is not supported on this platform. at System.Data.SqlClient.SqlConnectionString..ctor(String connectionString) …'

It says an error as The keyword ‘integrated security’ is not supported on this platform. If you remember, where we have used integrated security , that’s in sql server connectionString. We can’t operate with Sql server on Ubuntu. We have to install My SQL server to store data in your application. Let’s do that.


4.6.4. Add MySQL connectionString







Add mysql connectionString in appsetings.json file, movieDB will get created in mysql server.

 "DefaultConnection" : "server=localhost;database=movieDB;uid=root;pwd=hansamali;sslmode=none;"


4.6.5. Add MySQL service in your application

















If you remember, we added Sql service into the application when we run in Windows. In Ubuntu also same thing we have to do. Add MySQL service into your application with dbContext class. But it seems we are missing something in here.

Note that, Microsoft.EntityframeworkCore has been highlighted. Your application doesn’t use that reference anymore. It’s a reference from Sql server. We have to add a reference from MySQL to proceed with this. Let’s try to add it.








Add MySQL EFCore reference in project.json file and restore it.

“MySql.Data.EntityFrameworkCore” : “7.0.4-ir-191”

Add necessary changes in ConfigureServices method in Startup class.















services.AddDbContext(options =>

options.UseMySQL(Configuration.GetConnectionString(“DefaultConnection”)));

Add necessary using statements in startup class.

using MySQL.Data.EntityFrameworkCore.Extensions;

In windows with Sql server, We run migration scripts and ensure database is created. But with Ubuntu, we can’t do that. Somehow we have to ensure our database is created. Let’s give it a try.


4.6.6. Ensure MySQL database got created












Add this lines of code to ensure MySQL database got created.

var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseMySQL(Configuration.GetConnectionString(“DefaultConnection”));

var context = new MovieDbContext(optionsBuilder.Options);
context.Database.EnsureCreated();


4.6.7. Run your application




















Then build and run the application, navigate to movies read service and verify it works fine. read service returns empty array. Let’s check database is created in MySQL server.


4.6.8. View MySQL databases



























run commands to access mysql shell,

 mysql -u root -p

type command to view all the available databases, you can see movieDB is successfully created.

 show databases;


4.6.9. Let’s add some data into Movie database in MySQL





























Call POST service in movie controller and add a movie into the mysql database. Refresh read movie service, it shows available movies in your mysql database.

Connect to the mysql shell and try to view data in Movies table.

Go to mysql shell by typing this command,
 
 mysql -u root -p


view available databases

 show database;

type following command to go inside a database and query it

 use movieDB;

You can see available tables in movieDB using this command

 show tables;

Type a select query to view data in movies table

 select * from Movies;

In this post, I described how to run a web api application in windows with Sqlserver. And then we tried to configure same service application on Ubuntu with MySql server, with less amount of coding we could achieve that. It was a really cool feature in .NETCore


5. Download


5.1. TechNet Gallery

5.2. GitHub



6. Conclusion


In this article as you saw, we could modify same .NETCore application in both environments, Windows and Linux. We worked with two different databases SQL server and MYSQL, with Entityframework Core. I hope EFCore will provide its features for Oracle soon. Since .NETCore is cross platform and open source building applications for multiple environments is possible today.


7. References



Tuesday, November 22, 2016

.NET Core: Create web application with Yeoman template generator

1 Introduction


This article describes how to create ASP.NET Core web application using Yeoman template generator. When we create a ASP.NET Core application in windows platform, we can use visual studio templates. since ASP.NET Core is supported in Linux and Mac like platforms, we can use template generator tool like Yeoman to create a basic project template.


2 What is Yeoman?


Yeoman is a free open source tool. It’s more like visual studio project templates. It’s going to create a complete project with given set of tools. Yeoman has set of generators, It complies with industry best practices. Developers can easily start with their applications with specific tool set, without worrying about the setup or template of the application. Yeoman templates includes building, testing and minification in your application, So developer can focus on the logic of their application.


3 Install node js















 sudo apt-get install nodejs
 node --version


Install node js, before installing Yeoman. Yeoman is going to run on a node server, After installing node js check the version of it.


4 Install npm






















 sudo apt install npm


When we install nodejs, npm is also comes along with it. If you start installing npm before installing node js, follow like this.

npm is a package manager for Yeoman, It’s going to download any dependencies in your application, You don’t want to manually download and install it.


5 Let’s try to install Yeoman!!










 npm install -g yo


Run Yo installer command,




















But it doesn’t seem work, We get an ugly permission issue, Let’s try to fix this.

It says permission denied for some paths. It suggests to run installer command as root/Administrator, Let’s try out that.




























It looks perfectly fine, when we use sudo command with yo installer command.













 yo


We can check whether Yeoman is installed properly using Yo command.

We have successfully installed Yeoman. Now we don’t want to manually create .NETCore applications. We can use generated templates using Yo. Let’s start using Yeoman templates.

create a new directory and cd into it. Then run yo command.












Run Yo command, and check what happens.

It points to Install a generator by default. It doesn’t point to Run a generator, until we install a generator.










search for asp net generator in npm package management store.





















We get a permission issue when installing asp net generator, Let’s try what yo says, will run npm install command and see what happens.







 npm install -g generator


We tried to install generator using npm install command, But it shows the same error!!!!

Since this is a permission issue, will run the command with sudo and check what happens.








 sudo npm install -g generator-aspnet


When installing generator as an administrator, it installs without getting any errors.

Let’s run Yo command and select a template.




























Select aspnet as generator, and then select what type of application you want to create.

Select Empty Web Application and give a name to it.



















Go inside the project folder and open it in visual studio code.

In visual studio code add .vscode folder and restore relevant packages. It shows solution like this.






































In program.cs file, It shows WebHostBuilder class, with cross platform Kestrel server and IIS integration both.

It has defined a separate Startup class, to configure the http request pipeline.












Build and run .NETCore application and check terminal window,

You can see logging is enabled for browser navigation.

We can see complete project is created using Yeoman template generator. It includes program.cs, project.json and web.config files.

It includes Startup class to manage the http request pipeline. And also it has a wwwroot folder to host our web application.

Since Yeoman is generating complete application, We don’t have to do anything manually. We can only focus on the application logic and start working on it.


6 Download

6.1 TechNet Gallery



6.2 GitHub



7 Conclusion


If you go thorough this article, you will understand how easy it is to create a basic .NET Core template using Yeoman


8 References




Monday, October 31, 2016

Sri Lanka .NET Forum - October Meetup - 2016

Angular 2 with ASP.NET Core


Session Abstract: Both Angular 2 and .NET Core are the hottest frameworks at the moment among frontend and backend developers respectively. And what's more, they are open source too. So we'll find out what is so good about these frameworks and how to get them to work together by building an app.

Event : https://www.meetup.com/Sri-Lanka-NET-Forum/events/234463826/

Source Code : https://github.com/immysl/fav-movies

Related Blogs :








Monday, October 17, 2016

.NET Core with a Linux server: Hello World!



Hello World in .NET Core Ubuntu


Let’s start our first application on .NET Core - Ubuntu.

Create a new project














Create a folder in your desktop, myprojects, go inside of it and create a new project using the 'dotnet new' command.

You can see Program.cs and project.json file is created. To build our first project in .NET Core, let’s install the Visual Studio Code editor.

Install Visual Studio Code















Download the correct version of Visual Studio Code relevant to Ubuntu and install it.






















Go to your project location and open your project in Visual Studio Code. It shows a message to install an extension. Extensions allow you to add languages, debuggers and tools to your development environment, Click on Show Recommendations to view recommended extensions.











Select C# powered by Omnisharp, since we are using C# code in .NET Core. It provides IntelliSense for .NET. Omnisharp provides a set of tooling and libraries to IDEs like Visual Studio Code, Sublime, Atom, Emacs, Vim and Brackets. After installing the C# extension, enable it.




















program.cs file shows entry point to the application as usual.

project.json File



























project.json file shows NuGet dependencies required to build the application.

Let’s see what is the meaning of these attributes in the project.json file:
  • version”: “1.0.0-* specifies the version of .NET Core. It says version should start with 1.0.0.
  • buildOptions defines how the project should be built.
  • dependencies list all the dependencies in your application.
  • frameworks defines a target framework that will be used with specific dependencies.
  • imports defines where our application runs, When we add dnxcore50 , it says we are running in Core CLR on the dnx.








You can see a message to install build and debug assets, install them. And another message to restore the packages in project.json, restore them as well.













After adding an Assets folder, you can see .vscode folder with launch.json and tasks.json files. All the build errors are gone. Check the output window. It shows package restore is completed.

project.lock.json File





















































After packages restoring is completed, project-lock.json file has been added to the solution.

It’s going to capture entire dependency graph that your application depends on. In the project.json file, you define the top level dependencies, a more detailed level description is available in project-lock.json file.

launch.json File























This file is going to confgure debugging and running in the application. In this example, it’s going to launch the .NET Core console or even we can attatch to .NET Core console.

tasks.json File


























This file is used to automate tasks like building, packaging, testing and deploying software. In this example, it defines a build task and specifies to run as a build command.

Hello World in the terminal

















That’s all we want to know about the .NET Core application, Let’s see the output of our first application, When we run with 'dotnet run' command, it shows the output of the application.

Download Source

TechNet Gallery


GitHub


Saturday, September 24, 2016

Install .NETCore in a Linux server


Install .NETCore on Ubuntu


In .NET framework history, .NET have its full framework from .NET 1.0 to .NET 4.6.2, specially created for windows platform. Latest version of .NET framework is .NET 4.6.2 up to now, In the end of June Microsoft released a new .NET framework called .NET Core for Windows, Linux and Mac. A great feature of .NET core is, a solution build on windows can be run and modify in a linux based environment. We can build an application on Windows, and can host it in a Linux server.

Add dot net apt-get feed












Setup the apt-get feed and update it.

apt-get is a free package manager program. It works with Ubuntu’s APT (Advanced Packaging Tool). Using that command line program, We can Install new packages, remove or upgrade packages.

For this example, I used Ubuntu 16.04, run these commands,

sudo sh -c ‘echo “deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/ xenial main” > /etc/apt/sources.list.d/dotnetdev.list’


sudo apt-key adv –keyserver apt-mo.trafficmanager.net –recv-keys 417A0893

Then update apt-get feed Using following command,

sudo apt-get update


Install .NETCore top of apt-get






















Install .NETCore using following command,

sudo apt-get install dotnet-dev-1.0.0-preview2-003121

















Check whether .NETCore is properly installed using dotnet command. It shows .NETCore version as 1.0.1


Tuesday, August 30, 2016

C#: How to generate a unique key or password using salting + hashing

1. Introduction


When an application develops, we need to protect user passwords from security attacks. When your application operates on a license key, we need to validate the license.

In today's world providing security to your system is bit crucial. We have to face malicious scripts, security threats and unwanted attacks in out there. Let’s see how we can prevent those kind of attacks.


2. Password Hashing


In hashing, we are going to convert password string into a byte array. Hashing is a one way function, we can’t reverse it. We can see many hashing algorithms available.

Let’s say we hashed the users password and stored in our database. When user second time logs in, we have to verify entered password is correct. What we can do is, we can hash the entered text into password field and compare it with the hashed value from the database. Since Hashing is a one way function, we can’t decrypt and retrieve original text.


2.1. Invalid username or password


When user enters wrong password, System should not let the user know it’s Invalid password , instead of it should tell Invalid username or password . Then if hacker tries to login into your system, he doesn’t know whether username or password got wrong.


2.2. Hash Functions


SHA1, MD5 are popular hashing algorithms. SHA1 got inspired from MD algorithms and created SHA algorithms. From these two algorithms, better to use SHA1, Because it’s high secure than MD5. MD5 is going to convert a string into 128 bits. But SHA1 convert a string into 160 bits. In MD5 less no of operations required to crack the message, when compared to SHA1. But MD is faster than SHA1. However it’s better to use SHA1 algorithm instead of MD5, since MD5 can be broken easily.


2.3. Hashes can be cracked easily


Hackers can guess passwords and simply hash them with a hashing algorithm and try it in your system. It takes few seconds to generate a hash. Within a limited amount of time, your passwords can be cracked easily. These type of guessing password and hashing is called as Dictionary attacks and Brute force attacks.

In dictionary attacks, it uses a file with some words. These words can be extracted from a database or else from set of paragraphs. Most hackers guess passwords from common terms like, hello, hellow, he11o3 etc. They take a string and try to replace letters in it, like hello, he33o, heiio, etc. Then these words are hashed and use against the password hash.

Brute Force attacks going to try out every possible of character combinations to a certain string length. It’s a very expensive computational process, But eventually it’s going to find out your password! That’s why we need lengthier passwords, So it will take long time to crack your passwords.

By hashing your passwords, We can’t prevent Dictionary attacks or Brute force attacks, But we can minimize them.

While Dictionary attacks and Brute force attacks are time consuming, Hackers has another kid in their block, It’s Lookup Table. In Lookup table, It’s going to precompute the hashes of passwords and used to store them in a dictionary file. So hundreds of guesses can be done in a second. It’s a very effective method to crack your passwords.

Rainbow Tables, Beware guys, it can crack any 8 characters lengthy MD5 password. Rainbow table is same as Lookup table. In here hash cracking speed is slower, compared to lookup table. But lookup table size is smaller, so more hashes can be stored in the same space. So Rainbow tables are more effective than Lookup tables.


2.4. Salted Password Hashing


If we use a salt with password hashing, It’s impossible to crack your passwords through Rainbow tables and lookup tables. In lookup tables, hackers are going to hash same list of passwords and try out in your system. Let’s say two users are having same password in your system. When we hash these passwords, It’s same password hash. In Salting, we are adding a random number along with hashed password. So two users never get same salted password hash. And mind you don’t use same salt with different user passwords, don’t repeat the salting. If new user registers into your system or else change password, generate a new salt. Use a new salt for every user password. If hacker is smart enough, He may be able to crack a one or two user passwords, But not more than that. Even though many users have same password, Hacker will not be able to crack their passwords using a lookup table. Don’t use shorter salt, Then hacker can create a lookup table to generate every possible salt.


2.5. Let’s see how we can generate a unique key


























public class AuthenticationValidator
 {
      KeyGeneratorContext context = new KeyGeneratorContext();
      public bool GenerateSubscriptionKey(string userName, int companyCode)
      {
          bool isSuccess = false;
          byte[] salt = GenerateSalt();
          Company company = context.Companies.Where(c => c.Code == companyCode).FirstOrDefault();
          User user = context.Users.Where(u => u.CompanyId == company.Id && u.UserName == userName).FirstOrDefault();
          string[] hashKeys = GenerateHashKey(userName, companyCode).Split(':');
          Rfc2898DeriveBytes value = new Rfc2898DeriveBytes(hashKeys[0] + hashKeys[1], salt);
          byte[] key = value.GetBytes(64);
          user.Subscription = key;
          user.SaltValue = salt;
          isSuccess = context.SaveChanges() > 0;
          return isSuccess;
   }
    private static byte[] GenerateSalt ()
    {
        int saltLength = 32;
        byte[] salt = new byte[saltLength];
        using (var random = new RNGCryptoServiceProvider())
        {
           random.GetNonZeroBytes(salt);
        }
       return salt;
   }
   private string GenerateHashKey(string userName, int companyCode)
   {
      string key = string.Empty;
      Company company = context.Companies.Where(c => c.Code == companyCode).FirstOrDefault();
      User user = context.Users.Where(u => u.CompanyId == company.Id && u.UserName == userName).FirstOrDefault();
      if (company != null && user != null)
         key = company.Name + ":" + user.UserGuid;
      return key;
    }

In this example, we are passing username and company code to generate a license key. Using GenerateSalt method, we can generate a random number. I used to create a 32 bytes length salt number using RNGCryptoServiceProvider class. Using Rfc289DeriveVytes class we can generate a salted hashing value. Along with the generated license key, we used to store salted number as well.


2.6. Let’s see how we can validate the license key



















public bool ValidateSubscriptionKey(string userName, int companyCode)
{
    bool isValid = false;
    byte[] subscription = new byte[64];
    byte[] saltValue = new byte[32];
    Company company = context.Companies.Where(c => c.Code == companyCode).FirstOrDefault();
    if (company != null)
     {
        User user = context.Users.Where(u => u.CompanyId == company.Id && u.UserName == userName).FirstOrDefault();
        if (user != null)
         {
            subscription = user.Subscription;
             saltValue = new byte[32];
          }
        string[] hashKeys = GenerateHashKey(userName, companyCode).Split(':');
        Rfc2898DeriveBytes value = new Rfc2898DeriveBytes(hashKeys[0] + hashKeys[1], saltValue);
        byte[] key = value.GetBytes(64);
        bool result = subscription.SequenceEqual(key);
        if (result && user.ExpiryDate >= DateTime.Now)
          isValid = true;
      }
     return isValid;
   }

I used 64 byte array as a license key and 32 byte array as a salted value. We can use SequenceEqual method to compare entered license key with stored license key as above.


3. Download

3.1. TechNet Gallery




3.2. GitHub




4. Conclusion


This article explains various mechanisms to secure valuable data. If you go through the code sample, It explains how to secure a license key using salted hashing mechanism.


5. References