Create Server Project
Create ASP.NET Web Application and Select Web API Project in Visual Studio.
Entity Class
Create Models folder in server project. Create a entity class: Account.cs as below
Account.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace LearnASPNETWebAPIWithRealApps.Models
{
public class Account
{
public string Username
{
get;
set;
}
public string Password
{
get;
set;
}
public string []Roles
{
get;
set;
}
}
}
Models Class
Create a model class: AccountModel.cs in Models folder as below
AccountModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace LearnASPNETWebAPIWithRealApps.Models
{
public class AccountModel
{
private List<Account> accounts = new List<Account>();
public AccountModel()
{
accounts.Add(new Account { Username = "acc1", Password = "123", Roles = new string[] { "superadmin", "admin", "employee" } });
accounts.Add(new Account { Username = "acc2", Password = "123", Roles = new string[] { "admin", "employee" } });
accounts.Add(new Account { Username = "acc3", Password = "123", Roles = new string[] { "employee" } });
}
public Account find(string username)
{
return accounts.SingleOrDefault(acc => acc.Username.Equals(username));
}
public Account login(string username, string password)
{
return accounts.SingleOrDefault(acc => acc.Username.Equals(username) && acc.Password.Equals(password));
}
}
}
Security Classes
Create Security folder in server project. This folder contain classes need for security in ASP.NET Web API. Create classes: Credential.cs, MyAuthorize.cs and MyPrincipal.cs as below
Credential.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace LearnASPNETWebAPIWithRealApps.Security
{
public class Credential
{
public string Username
{
get;
set;
}
public string Password
{
get;
set;
}
}
}
MyAuthorize.cs
using LearnASPNETWebAPIWithRealApps.Security;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
namespace LearnASPNETWebAPIWithRealApps.Security
{
public class MyAuthorize : AuthorizeAttribute
{
private const string BasicAuthResponseHeader = "WWW-Authenticate";
private const string BasicAuthResponseHeaderValue = "Basic";
public override void OnAuthorization(HttpActionContext actionContext)
{
try
{
AuthenticationHeaderValue authValue = actionContext.Request.Headers.Authorization;
if (authValue != null && !String.IsNullOrWhiteSpace(authValue.Parameter) && authValue.Scheme == BasicAuthResponseHeaderValue)
{
Credential parsedCredentials = ParseAuthorizationHeader(authValue.Parameter);
var myPrincipal = new MyPrincipal(parsedCredentials.Username);
if (!myPrincipal.IsInRole(Roles))
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
actionContext.Response.Headers.Add(BasicAuthResponseHeader, BasicAuthResponseHeaderValue);
return;
}
}
else
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
actionContext.Response.Headers.Add(BasicAuthResponseHeader, BasicAuthResponseHeaderValue);
return;
}
}
catch (Exception ex)
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
actionContext.Response.Headers.Add(BasicAuthResponseHeader, BasicAuthResponseHeaderValue);
}
}
private Credential ParseAuthorizationHeader(string authHeader)
{
string[] credentials = Encoding.ASCII.GetString(Convert.FromBase64String(authHeader)).Split(new[] { ':' });
if (credentials.Length != 2 || string.IsNullOrEmpty(credentials[0]) || string.IsNullOrEmpty(credentials[1]))
return null;
return new Credential() { Username = credentials[0], Password = credentials[1], };
}
}
}
MyPrincipal.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Web;
using LearnASPNETWebAPIWithRealApps.Models;
namespace LearnASPNETWebAPIWithRealApps.Security
{
public class MyPrincipal : IPrincipal
{
private Account account;
private AccountModel accountModel = new AccountModel();
public MyPrincipal(string username)
{
this.Identity = new GenericIdentity(username);
this.account = accountModel.find(username);
}
public IIdentity Identity
{
get;
set;
}
public bool IsInRole(string role)
{
var roles = role.Split(new char[] { ',' });
return roles.Any(r => this.account.Roles.Contains(r));
}
}
}
Create Web API Controller
Create Web API Controller provides text/plain data for the client
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using LearnASPNETWebAPIWithRealApps.Security;
using System.Net.Http.Headers;
namespace LearnASPNETWebAPIWithRealApps.Controllers
{
[RoutePrefix("api/demo")]
public class DemoRestController : ApiController
{
[HttpGet]
[Route("work1")]
[AllowAnonymous]
public HttpResponseMessage Work1()
{
try
{
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StringContent("Work 1");
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
return response;
}
catch
{
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
}
[HttpGet]
[Route("work2")]
[MyAuthorize(Roles = "superadmin")]
public HttpResponseMessage Work2()
{
try
{
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StringContent("Work 2");
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
return response;
}
catch
{
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
}
[HttpGet]
[Route("work3")]
[MyAuthorize(Roles = "superadmin,admin")]
public HttpResponseMessage Work3()
{
try
{
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StringContent("Work 3");
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
return response;
}
catch
{
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
}
[HttpGet]
[Route("work4")]
[MyAuthorize(Roles = "superadmin,admin,employee")]
public HttpResponseMessage Work4()
{
try
{
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StringContent("Work 4");
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
return response;
}
catch
{
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
}
}
}
Testing Web API
Access Web API use the following url: http://localhost:64967/api/demo/work1
Output
Work 1
Access restful web services use the following url: http://localhost:64967/api/demo/work2
Output
Access restful web services use the following url: http://localhost:64967/api/demo/work3
Output
Access restful web services use the following url: http://localhost:64967/api/demo/work4
Output
Consume Web API from Console Application
Create Console Application Project in Visual Studio.
Create DemoRestClientModel
DemoRestClientModel class contain methods call Web API
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Headers;
namespace LearnASPNETWebAPIWithRealApps_Client
{
public class DemoRestClientModel
{
private string BASE_URL = "http://localhost:64967/api/demo/";
private string username = "acc2";
private string password = "123";
public Task<HttpResponseMessage> work1()
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(BASE_URL);
return client.GetAsync("work1");
}
catch
{
return null;
}
}
public Task<HttpResponseMessage> work2_without_account()
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(BASE_URL);
return client.GetAsync("work2");
}
catch
{
return null;
}
}
public Task<HttpResponseMessage> work2()
{
try
{
HttpClient client = new HttpClient();
var authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(this.username + ":" + this.password));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authInfo);
client.BaseAddress = new Uri(BASE_URL);
return client.GetAsync("work2");
}
catch
{
return null;
}
}
public Task<HttpResponseMessage> work3()
{
try
{
HttpClient client = new HttpClient();
var authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(this.username + ":" + this.password));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authInfo);
client.BaseAddress = new Uri(BASE_URL);
return client.GetAsync("work3");
}
catch
{
return null;
}
}
public Task<HttpResponseMessage> work4()
{
try
{
HttpClient client = new HttpClient();
var authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(this.username + ":" + this.password));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authInfo);
client.BaseAddress = new Uri(BASE_URL);
return client.GetAsync("work4");
}
catch
{
return null;
}
}
}
}
Run It
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace LearnASPNETWebAPIWithRealApps_Client
{
class Program
{
static void Main(string[] args)
{
DemoRestClientModel demoRestClientModel = new DemoRestClientModel();
Console.WriteLine("Test with work1 web method");
HttpResponseMessage httpResponseMessage1 = demoRestClientModel.work1().Result;
HttpStatusCode httpStatusCode1 = httpResponseMessage1.StatusCode;
Console.WriteLine("\tStatus Code: " + httpStatusCode1);
String result1 = httpResponseMessage1.Content.ReadAsStringAsync().Result;
Console.WriteLine("\tResult: " + result1);
Console.WriteLine("Test with work2 web method without account");
HttpResponseMessage httpResponseMessage2 = demoRestClientModel.work2_without_account().Result;
HttpStatusCode httpStatusCode2 = httpResponseMessage2.StatusCode;
Console.WriteLine("\tStatus Code: " + httpStatusCode2);
String result2 = httpResponseMessage2.Content.ReadAsStringAsync().Result;
Console.WriteLine("\tResult: " + result2);
Console.WriteLine("Test with acc2 have roles: admin and employee access work2 web method");
HttpResponseMessage httpResponseMessage3 = demoRestClientModel.work2().Result;
HttpStatusCode httpStatusCode3 = httpResponseMessage3.StatusCode;
Console.WriteLine("\tStatus Code: " + httpStatusCode3);
String result3 = httpResponseMessage3.Content.ReadAsStringAsync().Result;
Console.WriteLine("\tResult: " + result3);
Console.WriteLine("Test with acc2 have roles: admin and employee access work3 web method");
HttpResponseMessage httpResponseMessage4 = demoRestClientModel.work3().Result;
HttpStatusCode httpStatusCode4 = httpResponseMessage4.StatusCode;
Console.WriteLine("\tStatus Code: " + httpStatusCode4);
String result4 = httpResponseMessage4.Content.ReadAsStringAsync().Result;
Console.WriteLine("\tResult: " + result4);
Console.WriteLine("Test with acc2 have roles: admin and employee access work4 web method");
HttpResponseMessage httpResponseMessage5 = demoRestClientModel.work4().Result;
HttpStatusCode httpStatusCode5 = httpResponseMessage5.StatusCode;
Console.WriteLine("\tStatus Code: " + httpStatusCode5);
String result5 = httpResponseMessage5.Content.ReadAsStringAsync().Result;
Console.WriteLine("\tResult: " + result5);
Console.ReadLine();
}
}
}
Output
Test with work1 web method
Status Code: OK
Result: Work 1
Test with work2 web method without account
Status Code: Unauthorized
Result:
Test with acc2 have roles: admin and employee access work2 web method
Status Code: Unauthorized
Result:
Test with acc2 have roles: admin and employee access work3 web method
Status Code: OK
Result: Work 3
Test with acc2 have roles: admin and employee access work4 web method
Status Code: OK
Result: Work 4