RESTful Day #6: Request logging and Exception handling/logging in Web APIs using Action Filters, Exception Filters and NLog


Download Source Code from GitHub

Introduction

We have been learning a lot about WebAPI, its uses, implementations, and security aspects since last five articles of the series. This article of the series will explain how we can handle requests and log them for tracking and for the sake of debugging, how we can handle exceptions and log them. We’ll follow a centralized way of handling exceptions in WebAPI and write our custom classes to be mapped to the type of exception that we encounter and log the accordingly. I’ll use NLog to log requests and exceptions as well. We’ll leverage the capabilities of Exception Filters and Action Filters to centralize request logging and exception handling in WebAPI.

Roadmap

The following is the roadmap I have setup to learn WebAPI step by step,
I’ll purposely use Visual Studio 2010 and .NET Framework 4.0 because there are few implementations that are very hard to find in .NET Framework 4.0, but I’ll make it easy by showing how we can do it.

Request Logging

Since we are writing web services, we are exposing our end points. We must know where the requests are coming from and what requests are coming to our server. Logging could be very beneficial and helps us in a lot of ways like, debugging, tracing, monitoring and analytics.

We already have an existing design. If you open the solution, you’ll get to see the structure as mentioned below or one can also implement this approach in their existing solution as well.

Setup NLog in WebAPI

NLog serves various purposes but primarily logging. We’ll use NLog for logging into files and windows event as well. You can read more about NLog at http://NLog-project.org/
One can use the sample application that we used in Day#5 or can have any other application as well. I am using the existing sample application that we were following throughout all the parts of this series. Our application structure looks something like:

Step 1: Download NLog Package

Right click WebAPI project and select manage Nuget Packages from the list. When the Nuget Package Manager appears, search for NLog. You’ll get Nlog like shown in image below, just install it to our project.

After adding this you will find following NLog dll referenced in your application.

Step 2: Configuring NLog

To configure NLog with application add following settings in our existing WebAPI web.config file,

ConfigSection –

Configuration Section – I have added the section to configuration and defined the path and format dynamic target log file name, also added the eventlog source to Api Services.

As mentioned in above target path, I have also created to “APILog” folder in the base directory of application.

Now we have configured the NLog in our application, and it is ready to start work for request logging. Note that in the rules section we have defined rules for logging in files as well as in windows events log as well, you can choose both of them or can opt for one too. Let’s start with logging request in application, with action filters –

NLogger Class

Add a folder “Helpers” in the API, which will segregate the application code for readability, better understanding and maintainability.

To start add our main class “NLogger“, which will responsible for all types of errors and info logging, to same Helper folder. Here NLogger class implements ITraceWriter interface, which provides “Trace” method for the service request.
#region Using namespaces.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Tracing;
using NLog;
using System.Net.Http;
using System.Text;
using WebApi.ErrorHelper;
#endregion

namespace WebApi.Helpers
{
    /// <summary>
    /// Public class to log Error/info messages to the access log file
    /// </summary>
    public sealed class NLogger : ITraceWriter
    {
        #region Private member variables.
        private static readonly Logger ClassLogger = LogManager.GetCurrentClassLogger();

        private static readonly Lazy<Dictionary<TraceLevel, Action<string>>> LoggingMap = new Lazy<Dictionary<TraceLevel, Action<string>>>(() => new Dictionary<TraceLevel, Action<string>> { { TraceLevel.Info, ClassLogger.Info }, { TraceLevel.Debug, ClassLogger.Debug }, { TraceLevel.Error, ClassLogger.Error }, { TraceLevel.Fatal, ClassLogger.Fatal }, { TraceLevel.Warn, ClassLogger.Warn } });
        #endregion

        #region Private properties.
        /// <summary>
        /// Get property for Logger
        /// </summary>
        private Dictionary<TraceLevel, Action<string>> Logger
        {
            get { return LoggingMap.Value; }
        }
        #endregion

        #region Public member methods.
        /// <summary>
        /// Implementation of TraceWriter to trace the logs.
        /// </summary>
        /// <param name="request"></param>
        /// <param name="category"></param>
        /// <param name="level"></param>
        /// <param name="traceAction"></param>
        public void Trace(HttpRequestMessage request, string category, TraceLevel level, Action traceAction)
        {
            if (level != TraceLevel.Off)
            {
                if (traceAction != null && traceAction.Target != null)
                {
                    category = category + Environment.NewLine + "Action Parameters : " + traceAction.Target.ToJSON();
                }
                var record = new TraceRecord(request, category, level);
                if (traceAction != null) traceAction(record);
                Log(record);
            }
        }
        #endregion

        #region Private member methods.
        /// <summary>
        /// Logs info/Error to Log file
        /// </summary>
        /// <param name="record"></param>
        private void Log(TraceRecord record)
        {
            var message = new StringBuilder();

            if (!string.IsNullOrWhiteSpace(record.Message))
                message.Append("").Append(record.Message + Environment.NewLine);

            if (record.Request != null)
            {
                if (record.Request.Method != null)
                    message.Append("Method: " + record.Request.Method + Environment.NewLine);

                if (record.Request.RequestUri != null)
                    message.Append("").Append("URL: " + record.Request.RequestUri + Environment.NewLine);

                if (record.Request.Headers != null && record.Request.Headers.Contains("Token") && record.Request.Headers.GetValues("Token") != null && record.Request.Headers.GetValues("Token").FirstOrDefault() != null)
                    message.Append("").Append("Token: " + record.Request.Headers.GetValues("Token").FirstOrDefault() + Environment.NewLine);
            }

            if (!string.IsNullOrWhiteSpace(record.Category))
                message.Append("").Append(record.Category);

            if (!string.IsNullOrWhiteSpace(record.Operator))
                message.Append(" ").Append(record.Operator).Append(" ").Append(record.Operation);

            
            Logger[record.Level](Convert.ToString(message) + Environment.NewLine);
        }
        #endregion
    }
}

Adding Action Filter

Action filter will be responsible for handling all the incoming requests to our APIs and logging them using NLogger class. We have “OnActionExecuting” method that is implicitly called if we mark our controllers or global application to use that particular filter. So each time any action of any controller will be hit, our “OnActionExecuting” method will execute to log the request.

Step 1: Adding LoggingFilterAttribute class

Create a class LoggingFilterAttribute to “ActionFilters” folder and add following code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Filters;
using System.Web.Http.Controllers;
using System.Web.Http.Tracing;
using System.Web.Http;
using WebApi.Helpers;


namespace WebApi.ActionFilters
{
    public class LoggingFilterAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext filterContext)
        {
            GlobalConfiguration.Configuration.Services.Replace(typeof(ITraceWriter), new NLogger());
            var trace = GlobalConfiguration.Configuration.Services.GetTraceWriter();
            trace.Info(filterContext.Request, "Controller : " + filterContext.ControllerContext.ControllerDescriptor.ControllerType.FullName + Environment.NewLine + "Action : " + filterContext.ActionDescriptor.ActionName, "JSON", filterContext.ActionArguments);
        }
    }
}
The LoggingFilterAttribute class derived from ActionFilterAttribute, which is underSystem.Web.Http.Filters and overriding the OnActionExecuting method.
Here I have replaced the default “ITraceWriter” service with our NLogger class instance in the controller’s service container. Now GetTraceWriter() method will return our instance (instance NLogger class) and Info() will call trace() method of our NLogger class.
Note that the code below.
GlobalConfiguration.Configuration.Services.Replace(typeof(ITraceWriter), new NLogger());
is used to resolve dependency between ITaceWriter and NLogger class. Thereafter we use a variable namedtrace to get the instance and trace.Info() is used to log the request and whatever text we want to add along with that request.

Step 2: Registering Action Filter (LoggingFilterAttribute)

In order to register the created action filter to application’s filters, just add a new instance of your action filter toconfig.Filters in WebApiConfig class.
using System.Web.Http;
using WebApi.ActionFilters;

namespace WebApi.App_Start
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Filters.Add(new LoggingFilterAttribute());
        }
    }
}
Now this action filter is applicable to all the controllers and actions in our project. You may not believe but request logging is done. It’s time to run the application and validate our homework.

Running the application

Let’s run the application and try to make a call, using token based authorization, we have already covered authorization in day#5. You first need to authenticate your request using login service and then that service will return a token for making calls to other services. Use that token to make calls to other services. For more details you can read day 5 of this series.
Just run the application, we get
We already have our test client added, but for new readers, just go to Manage Nuget Packages, by right clicking WebAPI project and typing WebAPITestClient in searchbox in online packages
You’ll get “A simple Test Client for ASP.NET Web API”, just add it. You’ll get a help controller in Areas-> HelpPage like shown below:
I have already provided the database scripts and data in my previous article, you can use the same.
Append “/help” in the application url, and you’ll get the test client,
GET:
POST:
PUT:
DELETE:
You can test each service by clicking on it. Once you click on the service link, you’ll be redirected to test the service page of that particular service. On that page there is a button Test API in the right bottom corner, just press that button to test your service:
Service for Get All products:
In the below case, I have already generated the token and now I am using it to make call to fetch all the products from the products table in the database.

Here I have called allproducts API, Add the value for parameter Id and “Token” header with its current value and click to get the result:

Now let’s see what happens to our APILog folder in application. Here you find the API log has been created, with the same name we have configured in NLog configuration in web.config file. The log file contains all the supplied details like Timestamp, Method type, URL , Header information (Token), Controller name, action and action parameters. You can also add more details to this log which you deem important for your application.

Logging Done!

Exception Logging

Our logging setup is completed, now we’ll focus on centralizing exception logging as well, so that none of the exception escapes without logging itself. Logging exception is of very high importance, it keeps track of all the exceptions. No matter business or application or system exceptions, all of them have to be logged.

Implementing Exception logging

Step 1: Exception Filter Attribute

Now we will add an action filter in our application for logging the exceptions. For this create a class,GlobalExceptionAttribute to “ActionFilter” folder and add the code below, the class is derived fromExceptionFilterAttribute, which is under System.Web.Http.Filters.
I override the OnException() method and replace the default “ITraceWriter” service with our NLogger class instance in the controller’s service container, same as we have done in Action logging in above section. Now theGetTraceWriter() method will return our instance (instance NLogger class) and Info() will call trace()method of NLogger class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Filters;
using System.Web.Http;
using System.Web.Http.Tracing;
using WebApi.Helpers;
using System.ComponentModel.DataAnnotations;
using System.Net.Http;
using System.Net;

namespace WebApi.ActionFilters
{
    /// <summary>
    /// Action filter to handle for Global application errors.
    /// </summary>
    public class GlobalExceptionAttribute : ExceptionFilterAttribute
    {
        public override void OnException(HttpActionExecutedContext context)
        {
            GlobalConfiguration.Configuration.Services.Replace(typeof(ITraceWriter), new NLogger());
            var trace = GlobalConfiguration.Configuration.Services.GetTraceWriter();
            trace.Error(context.Request, "Controller : " + context.ActionContext.ControllerContext.ControllerDescriptor.ControllerType.FullName + Environment.NewLine + "Action : " + context.ActionContext.ActionDescriptor.ActionName, context.Exception);

            var exceptionType = context.Exception.GetType();

            if (exceptionType == typeof(ValidationException))
            {
                var resp = new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = new StringContent(context.Exception.Message), ReasonPhrase = "ValidationException", };
                throw new HttpResponseException(resp);

            }
            else if (exceptionType == typeof(UnauthorizedAccessException))
            {
                throw new HttpResponseException(context.Request.CreateResponse(HttpStatusCode.Unauthorized));
            }
            else
            {
                throw new HttpResponseException(context.Request.CreateResponse(HttpStatusCode.InternalServerError));
            }
        }
    }
}

Step 2: Modify NLogger Class

Our NLogger class is capable to log all info and events, I have done some changes in private method Log() to handle the exceptions
#region Private member methods.
/// <summary>
/// Logs info/Error to Log file
/// </summary>
/// <param name="record"></param>
private void Log(TraceRecord record)
{
var message = new StringBuilder();

if (!string.IsNullOrWhiteSpace(record.Message))
                message.Append("").Append(record.Message + Environment.NewLine);

      if (record.Request != null)
{
       if (record.Request.Method != null)
            message.Append("Method: " + record.Request.Method + Environment.NewLine);

                if (record.Request.RequestUri != null)
                    message.Append("").Append("URL: " + record.Request.RequestUri + Environment.NewLine);

                if (record.Request.Headers != null && record.Request.Headers.Contains("Token") && record.Request.Headers.GetValues("Token") != null && record.Request.Headers.GetValues("Token").FirstOrDefault() != null)
                    message.Append("").Append("Token: " + record.Request.Headers.GetValues("Token").FirstOrDefault() + Environment.NewLine);
            }

            if (!string.IsNullOrWhiteSpace(record.Category))
                message.Append("").Append(record.Category);

            if (!string.IsNullOrWhiteSpace(record.Operator))
                message.Append(" ").Append(record.Operator).Append(" ").Append(record.Operation);

            if (record.Exception != null && !string.IsNullOrWhiteSpace(record.Exception.GetBaseException().Message))
            {
                var exceptionType = record.Exception.GetType();
                message.Append(Environment.NewLine);
                message.Append("").Append("Error: " + record.Exception.GetBaseException().Message + Environment.NewLine);
            }

            Logger[record.Level](Convert.ToString(message) + Environment.NewLine);
        }

Step 3: Modify Controller for Exception

Our application is now ready to run, but there is no exception in our code, so I added a throw exception code inProductController, just the Get(int id) method so that it can throw exception for testing our exception logging mechanism. It will throw an exception if the product is not there in database with the provided id.
  // GET api/product/5
 [GET("productid/{id?}")]
 [GET("particularproduct/{id?}")]
 [GET("myproduct/{id:range(1, 3)}")]
 public HttpResponseMessage Get(int id)
 {
var product = _productServices.GetProductById(id);
      if (product != null)
       return Request.CreateResponse(HttpStatusCode.OK, product);

 throw new Exception("No product found for this id");
      //return Request.CreateErrorResponse(HttpStatusCode.NotFound,   "No product found for this id");
 }

Step 4: Run the application

Run the application and click on Product/all API
Add the parameter id value to 1 and header Token with it’s current value, click on send button to get the result:
Now we can see that the Status is 200/OK, and we also get a product with the provided id in the response body. Let’s see the API log now:
The log has captured the call of Product API, now provide a new product id as parameter, which is not there in database, I am using 12345 as product id and result is:

We can see there is an 500/Internal Server Error now in response status, let’s check the API Log:

Well, now the log has captured both the event and error of same call on the server, you can see call log details and the error with provided error message in the log.

Custom Exception logging

In the above section we have implemented exception logging, but there is default system response and status (i.e. 500/Internal Server Error). It will be always good to have your own custom response and exceptions for your API. That will be easier for client to consume and understand the API responses.

Step 1: Add Custom Exception Classes

Add “Error Helper” folder to application to maintain our custom exception classes separately and add “IApiExceptions” interface to newly created “ErrorHelper” folder –
Add following code the IApiExceptions interface, this will serve as a template for all exception classes, I have added four common properties for our custom classes to maintain Error Code, ErrorDescription, HttpStatus (Contains the values of status codes defined for HTTP) and ReasonPhrase.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;

namespace WebApi.ErrorHelper
{
    /// <summary>
    /// IApiExceptions Interface
    /// </summary>
    public interface IApiExceptions
    {
        /// <summary>
        /// ErrorCode
        /// </summary>
        int ErrorCode { get; set; }
        /// <summary>
        /// ErrorDescription
        /// </summary>
        string ErrorDescription { get; set; }
        /// <summary>
        /// HttpStatus
        /// </summary>
        HttpStatusCode HttpStatus { get; set; }
        /// <summary>
        /// ReasonPhrase
        /// </summary>
        string ReasonPhrase { get; set; }
    }
}
Here, I divided our exceptions in three categories:
  1. API Exceptions – for API level exceptions.
  2. Business Exceptions – for exceptions at business logic level.
  3. Data Exceptions – Data related exceptions.
To implement this create a three new classes ApiException.cs, ApiDataException.cs and ApiBusinessExceptionclasses to same folder which implements IApiExceptions interface with following code to the classes.
#region Using namespaces.
using System;
using System.Net;
using System.Runtime.Serialization;
#endregion


namespace WebApi.ErrorHelper
{
    /// <summary>
    /// Api Exception
    /// </summary>
    [Serializable]
    [DataContract]
    public class ApiException : Exception, IApiExceptions
    {
        #region Public Serializable properties.
        [DataMember]
        public int ErrorCode { get; set; }
        [DataMember]
        public string ErrorDescription { get; set; }
        [DataMember]
        public HttpStatusCode HttpStatus { get; set; }
        
        string reasonPhrase = "ApiException";

        [DataMember]
        public string ReasonPhrase
        {
            get { return this.reasonPhrase; }

            set { this.reasonPhrase = value; }
        }
        #endregion
    }
}
I have initialized ReasonPhrase property with different default values in these classes to differentiate the implementation, you can use implement your custom classes as per your application needs.
The directives applied on class as Serializable and DataContract to make sure that the class defines or implements a data contract is serializable and can be serialize by a serializer.
Note: Add reference of “System.Runtime.Serialization.dll” DLL if you facing any assembly issue.
In the same way add “ApiBusinessException” and “ApiDataException” classes into the same folder, with the following code –
#region Using namespaces.
using System;
using System.Net;
using System.Runtime.Serialization; 
#endregion

namespace WebApi.ErrorHelper
{
    /// <summary>
    /// Api Business Exception
    /// </summary>
    [Serializable]
    [DataContract]
    public class ApiBusinessException : Exception, IApiExceptions
    {
        #region Public Serializable properties.
        [DataMember]
        public int ErrorCode { get; set; }
        [DataMember]
        public string ErrorDescription { get; set; }
        [DataMember]
        public HttpStatusCode HttpStatus { get; set; }

        string reasonPhrase = "ApiBusinessException";

        [DataMember]
        public string ReasonPhrase
        {
            get { return this.reasonPhrase; }

            set { this.reasonPhrase = value; }
        }
        #endregion

        #region Public Constructor.
        /// <summary>
        /// Public constructor for Api Business Exception
        /// </summary>
        /// <param name="errorCode"></param>
        /// <param name="errorDescription"></param>
        /// <param name="httpStatus"></param>
        public ApiBusinessException(int errorCode, string errorDescription, HttpStatusCode httpStatus)
        {
            ErrorCode = errorCode;
            ErrorDescription = errorDescription;
            HttpStatus = httpStatus;
        } 
        #endregion

    }
}

#region Using namespaces.
using System;
using System.Net;
using System.Runtime.Serialization;
#endregion

namespace WebApi.ErrorHelper
{
    /// <summary>
    /// Api Data Exception
    /// </summary>
    [Serializable]
    [DataContract]
    public class ApiDataException : Exception, IApiExceptions
    {
        #region Public Serializable properties.
        [DataMember]
        public int ErrorCode { get; set; }
        [DataMember]
        public string ErrorDescription { get; set; }
        [DataMember]
        public HttpStatusCode HttpStatus { get; set; }

        string reasonPhrase = "ApiDataException";

        [DataMember]
        public string ReasonPhrase
        {
            get { return this.reasonPhrase; }

            set { this.reasonPhrase = value; }
        }

        #endregion

        #region Public Constructor.
        /// <summary>
        /// Public constructor for Api Data Exception
        /// </summary>
        /// <param name="errorCode"></param>
        /// <param name="errorDescription"></param>
        /// <param name="httpStatus"></param>
        public ApiDataException(int errorCode, string errorDescription, HttpStatusCode httpStatus)
        {
            ErrorCode = errorCode;
            ErrorDescription = errorDescription;
            HttpStatus = httpStatus;
        }
        #endregion
    }
}

JSon Serializers

There are some objects need to be serialized in JSON, to log and to transfer through the modules, for this I have add some extension methods to Object class.
For that add “System.Web.Extensions.dll” reference to project and add “JSONHelper” class to Helpers folder, with following code:
#region Using namespaces.
using System.Web.Script.Serialization;
using System.Data;
using System.Collections.Generic;
using System;

#endregion

namespace WebApi.Helpers
{
    public static class JSONHelper
    {
         #region Public extension methods.
        /// <summary>
        /// Extened method of object class, Converts an object to a json string.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string ToJSON(this object obj)
        {
            var serializer = new JavaScriptSerializer();
            try
            {
                return serializer.Serialize(obj);
            }
            catch(Exception ex)
            {
                return "";
            }
        }
         #endregion
    }
}
In the above code “ToJSON()” method is an extension of base Object class, which serializes supplied the object to a JSON string. The method using “JavaScriptSerializer” class which exists in “System.Web.Script.Serialization“.

Modify NLogger Class

For exception handling I have modified the Log() method of NLogger, which will now handle the different API exceptions.
/// <summary>
/// Logs info/Error to Log file
/// </summary>
/// <param name="record"></param>
private void Log(TraceRecord record)
{
var message = new StringBuilder();

      if (!string.IsNullOrWhiteSpace(record.Message))
                message.Append("").Append(record.Message + Environment.NewLine);

            if (record.Request != null)
            {
                if (record.Request.Method != null)
                    message.Append("Method: " + record.Request.Method + Environment.NewLine);

                if (record.Request.RequestUri != null)
                    message.Append("").Append("URL: " + record.Request.RequestUri + Environment.NewLine);

                if (record.Request.Headers != null && record.Request.Headers.Contains("Token") && record.Request.Headers.GetValues("Token") != null && record.Request.Headers.GetValues("Token").FirstOrDefault() != null)
                    message.Append("").Append("Token: " + record.Request.Headers.GetValues("Token").FirstOrDefault() + Environment.NewLine);
            }

            if (!string.IsNullOrWhiteSpace(record.Category))
                message.Append("").Append(record.Category);

            if (!string.IsNullOrWhiteSpace(record.Operator))
                message.Append(" ").Append(record.Operator).Append(" ").Append(record.Operation);

            if (record.Exception != null && !string.IsNullOrWhiteSpace(record.Exception.GetBaseException().Message))
            {
                var exceptionType = record.Exception.GetType();
                message.Append(Environment.NewLine);
                if (exceptionType == typeof(ApiException))
                {
                    var exception = record.Exception as ApiException;
                    if (exception != null)
                    {
                        message.Append("").Append("Error: " + exception.ErrorDescription + Environment.NewLine);
                        message.Append("").Append("Error Code: " + exception.ErrorCode + Environment.NewLine);
                    }
                }
                else if (exceptionType == typeof(ApiBusinessException))
                {
                    var exception = record.Exception as ApiBusinessException;
                    if (exception != null)
                    {
                        message.Append("").Append("Error: " + exception.ErrorDescription + Environment.NewLine);
                        message.Append("").Append("Error Code: " + exception.ErrorCode + Environment.NewLine);
                    }
                }
                else if (exceptionType == typeof(ApiDataException))
                {
                    var exception = record.Exception as ApiDataException;
                    if (exception != null)
                    {
                        message.Append("").Append("Error: " + exception.ErrorDescription + Environment.NewLine);
                        message.Append("").Append("Error Code: " + exception.ErrorCode + Environment.NewLine);
                    }
                }
                else
                    message.Append("").Append("Error: " + record.Exception.GetBaseException().Message + Environment.NewLine);
            }

            Logger[record.Level](Convert.ToString(message) + Environment.NewLine);
        }
The code above checks the exception object of TraceRecord and updates the logger as per the exception type.

Modify GlobalExceptionAttribute

As we have created GlobalExceptionAttribute to handle all exceptions and create response in case of any exception. Now I have added some new code to this in order to enable the GlobalExceptionAttribute class to handle custom exceptions. I am adding only modified method here for your reference .
public override void OnException(HttpActionExecutedContext context)
{
         GlobalConfiguration.Configuration.Services.Replace(typeof(ITraceWriter), new NLogger());
            var trace = GlobalConfiguration.Configuration.Services.GetTraceWriter();
            trace.Error(context.Request, "Controller : " + context.ActionContext.ControllerContext.ControllerDescriptor.ControllerType.FullName + Environment.NewLine + "Action : " + context.ActionContext.ActionDescriptor.ActionName, context.Exception);

            var exceptionType = context.Exception.GetType();

            if (exceptionType == typeof(ValidationException))
            {
                var resp = new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = new StringContent(context.Exception.Message), ReasonPhrase = "ValidationException", };
                throw new HttpResponseException(resp);

            }
            else if (exceptionType == typeof(UnauthorizedAccessException))
            {
                throw new HttpResponseException(context.Request.CreateResponse(HttpStatusCode.Unauthorized, new ServiceStatus() { StatusCode = (int)HttpStatusCode.Unauthorized, StatusMessage = "UnAuthorized", ReasonPhrase = "UnAuthorized Access" }));
            }
            else if (exceptionType == typeof(ApiException))
            {
                var webapiException = context.Exception as ApiException;
                if (webapiException != null)
                    throw new HttpResponseException(context.Request.CreateResponse(webapiException.HttpStatus, new ServiceStatus() { StatusCode = webapiException.ErrorCode, StatusMessage = webapiException.ErrorDescription, ReasonPhrase = webapiException.ReasonPhrase }));
            }
            else if (exceptionType == typeof(ApiBusinessException))
            {
                var businessException = context.Exception as ApiBusinessException;
                if (businessException != null)
                    throw new HttpResponseException(context.Request.CreateResponse(businessException.HttpStatus, new ServiceStatus() { StatusCode = businessException.ErrorCode, StatusMessage = businessException.ErrorDescription, ReasonPhrase = businessException.ReasonPhrase }));
            }
            else if (exceptionType == typeof(ApiDataException))
            {
                var dataException = context.Exception as ApiDataException;
                if (dataException != null)
                    throw new HttpResponseException(context.Request.CreateResponse(dataException.HttpStatus, new ServiceStatus() { StatusCode = dataException.ErrorCode, StatusMessage = dataException.ErrorDescription, ReasonPhrase = dataException.ReasonPhrase }));
            }
            else
            {
                throw new HttpResponseException(context.Request.CreateResponse(HttpStatusCode.InternalServerError));
            }
        }
In the above code I have modified the overrided method OnExeption() and created new Http response exception based on the different exception types.

Modify Product Controller

Now modify the Product controller to throw our custom exception form, please look into the Get method I have modified to throw the APIDataException in case if data is not found and APIException in any other kind of error.
// GET api/product/5
[GET("productid/{id?}")]
[GET("particularproduct/{id?}")]
[GET("myproduct/{id:range(1, 3)}")]
public HttpResponseMessage Get(int id)
{
if (id != null)
      {
       var product = _productServices.GetProductById(id);
            if (product != null)
             return Request.CreateResponse(HttpStatusCode.OK, product);

throw new ApiDataException(1001, "No product found for this id.", HttpStatusCode.NotFound);
      }
      throw new ApiException() { ErrorCode = (int)HttpStatusCode.BadRequest, ErrorDescription = "Bad Request..." };
}

Run the application

Run the application and click on Product/all API:
Add the parameter id value to 1 and header Token with its current value, click on send button to get the result:
Now we can see that the Status is 200/OK, and we also get a product with the provided id in the response body. Lets see the API log now –
The log has captured the call of Product API, now provide a new product id as parameter, which is not there in database, I am using 12345 as product id and result is:
We can see, now there is a custom error status code “1001” and messages “No product found for this id.” And the generic status code “500/Internal Server Error” is now replaced with our supplied code “404/ Not Found”, which is more meaningful for the client or consumer.
Lets see the APILog now:
Well, now the log has captured both the event and error of same call on the server, you can see call log details and the error with provided error message in the log with our custom error code, I have only captured error description and error code, but you can add more details in the log as per your application needs.

Update the controller for new Exception Handling

Following is the code for controllers with implementation of custom exception handling and logging:

Product Controller

using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using AttributeRouting;
using AttributeRouting.Web.Http;
using BusinessEntities;
using BusinessServices;
using WebApi.ActionFilters;
using WebApi.Filters;
using System;
using WebApi.ErrorHelper;

namespace WebApi.Controllers
{
    [AuthorizationRequired]
    [RoutePrefix("v1/Products/Product")]
    public class ProductController : ApiController
    {
        #region Private variable.

        private readonly IProductServices _productServices;

        #endregion

        #region Public Constructor

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

        #endregion

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

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

                throw new ApiDataException(1001, "No product found for this id.", HttpStatusCode.NotFound);
            }
            throw new ApiException() { ErrorCode = (int)HttpStatusCode.BadRequest, ErrorDescription = "Bad Request..." };
        }

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

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

        // DELETE api/product/5
        [DELETE("remove/productid/{id}")]
        [DELETE("clear/productid/{id}")]
        [PUT("delete/productid/{id}")]
        public bool Delete(int id)
        {
            if (id != null && id > 0)
            {
                var isSuccess = _productServices.DeleteProduct(id);
                if (isSuccess)
                {
                    return isSuccess;
                }
                throw new ApiDataException(1002, "Product is already deleted or not exist in system.", HttpStatusCode.NoContent );
            }
            throw new ApiException() {ErrorCode = (int) HttpStatusCode.BadRequest, ErrorDescription = "Bad Request..."};
        }
    }
}
Now you can see, our application is so rich and scalable that none of the exception or transaction can escapelogging.Once setup is inplaced, now you don’t have to worry about writing code each time for logging or requests and exceptions, but you can relax and focus on business logic only.

Conclusion

In this article we learnt about how to perform request logging and exception logging in WebPI. There could be numerous ways in which you can perform these operations but I tried to present this in as simple way as possible. My approach was to take our enterprise level to next level of development, where developers should not always be worried about exception handling and logging. Our solution provides a generic approach of centralizing the operations in one place; all the requests and exceptions are automatically taken care of. In my new articles, I’ll try to enhance the application by explaining unit testing in WebAPI and OData in WebAPI. You can download the complete source code of this article with packages from GitHub. Happy coding Smile | :)
Advertisements

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


Introduction

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

Roadmap

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

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

Security in WebAPI

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

Authentication

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

Authorization

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

Maintaining Session

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

Basic Authentication

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

Pros and Cons of Basic Authentication

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

Token Based Authorization

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

WebAPI with Basic Authentication and Token Based Authorization

Creating User Service

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

UserServices

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

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

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

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

Resolve dependency of UserService

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

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

Implementing Basic Authentication

Step 1: Create generic Authentication Filter

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

        private readonly bool _isActive = true;

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

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

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

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


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

Step 2: Create Basic Authentication Identity

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

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

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

Step 3: Create a Custom Authentication Filter

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

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

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

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

Step 4: Basic Authentication on Controller

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

        private readonly IProductServices _productServices;

        #endregion

        #region Public Constructor

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

        #endregion

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

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

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

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

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

Running the application

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

Design discrepancy

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

Implementing Token-based Authorization

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

Set Database

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

Set Business Services

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

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

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

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

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

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

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

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

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

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


#region Public member methods.

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

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

return tokenModel;
}

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

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

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

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

#endregion
}
}

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

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

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

        }
    }

Setup WebAPI/Controller

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

AuthenticateController

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

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

        private readonly ITokenServices _tokenServices;

        #endregion

        #region Public Constructor

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

        #endregion

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

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

Setup Authorization Action Filter

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

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

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

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

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

base.OnActionExecuting(filterContext);

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

Mark Controllers with Authorization filter

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

Maintaining Session using Token

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

Running the application

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

Test Authentication

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

Test Authorization

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

Conclusion

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

References

Read more:

Other Series

My other series of articles:

For more technical articles you can reach out to CodeTeddy.

RESTful Day #4: Custom URL Re-Writing/Routing using Attribute Routes in MVC 4 Web APIs


Download Source Code

Introduction

We have already learnt a lot on WebAPI. I have already explained how to create WebAPI, connect it with database using Entity Framework, resolving dependencies using Unity Container as well as using MEF. In all our sample applications we were using default route that MVC provides us for CRUD operations. In this article I’ll explain how to write your own custom routes using Attribute Routing. We’ll deal with Action level routing as well as Controller level routing. I’ll explain this in detail with the help of a sample application. My new readers can use any Web API sample they have, else you can also use the sample applications we developed in my previous articles.
Let’s revisit the road map that I started on Web API,
 Here is my roadmap for learning RESTful APIs,
I’ll purposely use Visual Studio 2010 and .NET Framework 4.0 because there are few implementations that are very hard to find in .NET Framework 4.0, but I’ll make it easy by showing how we can do it.

Routing

Routing in generic terms for any service, API, website is a kind of pattern defining system that tries to maps all request from the clients and resolves that request by providing some response to that request. In WebAPI we can define routes in WebAPIConfig file, these routes are defined in an internal Route Table. We can define multiple sets of Routes in that table.

Existing Design and Problem

We already have an existing design. If you open the solution, you’ll get to see the structure as mentioned below,
In our existing application, we created WebAPI with default routes as mentioned in the file named WebApiConfig in App_Start folder of WebApi project. The routes were mentioned in the Register method as,
config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
Do not get confused by MVC routes, since we are using MVC project we also get MVC routes defined inRouteConfig.cs file as,
public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }
We need to focus on the first one i.e. WebAPI route. As you can see in the following image, what each property signifies,
We have a route name, we have a common URL pattern for all routes, and option to provide optional parameters as well.
Since our application do not have particular different action names, and we were using HTTP VERBS as action names, we didn’t bother much about routes. Our Action names were like,
1. public HttpResponseMessage Get()
2. public HttpResponseMessage Get(int id)
3. public int Post([FromBody] ProductEntity productEntity)
4. public bool Put(int id, [FromBody]ProductEntity productEntity)
5. public bool Delete(int id)

Default route defined does not takes HTTP VERBS action names into consideration and treat them default actions, therefore it does not mentions {action} in routeTemplate. But that’s not limitation, we can have our own routes defined in WebApiConfig, for example, check out the following routes,

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

            config.Routes.MapHttpRoute(
               name: "ActionBased",
               routeTemplate: "api/{controller}/{action}/{id}",
               defaults: new { id = RouteParameter.Optional }
           );
            config.Routes.MapHttpRoute(
              name: "ActionBased",
              routeTemplate: "api/{controller}/action/{action}/{id}",
              defaults: new { id = RouteParameter.Optional }
          );
        }
And etc. In above mentioned routes, we can have action names as well, if we have custom actions.
So there is no limit to define routes in WebAPI. But there are few limitations to this, note we are talking about WebAPI 1 that we use with .NET Framework 4.0 in Visual Studio 2010. Web API 2 has overcome those limitations by including the solution that I’ll explain in this article. Let’s check out the limitations of these routes,
Yes, these are the limitations that I am talking about in Web API 1.
If we have route template like routeTemplate: “api/{controller}/{id}” or routeTemplate: “api/{controller}/{action}/{id}” or routeTemplate: “api/{controller}/action/{action}/{id}“,
We can never have custom routes and will have to slick to old route convention provided by MVC. Suppose your client of the project wants to expose multiple endpoints for the service, he can’t do so. We also can not have our own defined names for the routes, so lots of limitation.
Let’s suppose we want to have following kind of routes for my web API endpoints, where I can define versions too,
v1/Products/Product/allproducts
v1/Products/Product/productid/1
v1/Products/Product/particularproduct/4
v1/Products/Product/myproduct/
v1/Products/Product/create
v1/Products/Product/update/3
and so on, then we cannot achieve this with existing model.
Fortunately these things have been taken care of in WebAPI 2 with MVC 5, but for this situation we have AttributeRouting to resolve and overcome these limitations.

Attribute Routing

Attribute Routing is all about creating custom routes at controller level, action level. We can have multiple routes using Attribute Routing. We can have versions of routes as well, in short we have the solution for our exiting problems. Let’s straight away jump on how we can implement this in our exising project. I am not explaining on how to create a WebAPI, for that you can refer my first post of the series.
Step 1: Open the solution ,and open Package Manage Console like shown below in the figure,
Goto Tools->Library Packet manage-> Packet Manager Console
 
Step 2: In the package manager console window at left corner of Visual Studio type, Install-Package AttributeRouting.WebApi, and choose the project WebApi or your own API project if you are using any other code sample, then press enter.
 
Step 3: As soon as the package is installed, you’ll get a class named AttributeRoutingHttpConfig.cs in yourApp_Start folder.
This class has its own method to RegisterRoutes, which internally maps attribute routes. It has a start method that picks Routes defined from GlobalConfiguration and calls the RegisterRoutes method,
using System.Web.Http;
using AttributeRouting.Web.Http.WebHost;

[assembly: WebActivator.PreApplicationStartMethod(typeof(WebApi.AttributeRoutingHttpConfig), "Start")]

namespace WebApi 
{
    public static class AttributeRoutingHttpConfig
 {
  public static void RegisterRoutes(HttpRouteCollection routes) 
  {    
   // See http://github.com/mccalltd/AttributeRouting/wiki for more options.
   // To debug routes locally using the built in ASP.NET development server, go to /routes.axd

            routes.MapHttpAttributeRoutes();
  }

        public static void Start() 
  {
            RegisterRoutes(GlobalConfiguration.Configuration.Routes);
        }
    }
}
We don’t even have to touch this class, our custom routes will automatically be taken care of using this class.We just need to focus on defining routes. No coding :-).  You can now use route specific stuff like route names, verbs, constraints, optional parameters, default parameters, methods, route areas, area mappings, route prefixes, route conventions etc.

Setup REST endpoint / WebAPI project to define Routes

Our 90% of the job is done.
We now need to setup or WebAPI project and define our routes.
Our existing ProductController class looks something like shown below,
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using BusinessEntities;
using BusinessServices;

namespace WebApi.Controllers
{
    public class ProductController : ApiController
    {

        private readonly IProductServices _productServices;

        #region Public Constructor

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

        #endregion

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

        // GET api/product/5
        public HttpResponseMessage Get(int id)
        {
            var product = _productServices.GetProductById(id);
            if (product != null)
                return Request.CreateResponse(HttpStatusCode.OK, product);
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No product found for this id");
        }

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

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

        // DELETE api/product/5
        public bool Delete(int id)
        {
            if (id > 0)
                return _productServices.DeleteProduct(id);
            return false;
        }
    }
}
Where we have a controller name Product and Action names as Verbs. When we run the application, we get following type of endpoints only (please ignore port and localhost setting. It’s because I run this application from my local environment),
Get All Products:
Get product By Id:
Create product :
Update product:
Delete product:
Step 1: Add two namespaces to your controller,
using AttributeRouting;
using AttributeRouting.Web.Http;
 

Step 2: Decorate your action with different routes,

Like in above image, I defined a route with name productid which taked id as a parameter. We also have to provide verb (GET, POST, PUT, DELETE, PATCH) along with the route like shown in image. So it is[GET("productid/{id?}")]. You can define whatever route you want for your Action like[GET("product/id/{id?}")], [GET("myproduct/id/{id?}")] and many more.
Now when I run the application and navigate to /help page, I get this,
i.e. I got one more route for Getting product by id. When you’ll test this service you’ll get your desired URL something like: http://localhost:55959/Product/productid/3, that sounds like real REST Smile | :)
Similarly decorate your Action with multiple routes like show below,
        // GET api/product/5
        [GET("productid/{id?}")]
        [GET("particularproduct/{id?}")]
        [GET("myproduct/{id:range(1, 3)}")]
        public HttpResponseMessage Get(int id)
        {
            var product = _productServices.GetProductById(id);
            if (product != null)
                return Request.CreateResponse(HttpStatusCode.OK, product);
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No product found for this id");
        }
Therefore we see, we can have our custom route names and as well as multiple endpoints for a single Action. That’s exciting.Each endpoint will be different but will serve same set of result.
  • {id?} : here ‘?’ means that parameter can be optional.
  • [GET(“myproduct/{id:range(1, 3)}”)], signifies that the product id’s falling in this range will only be shown.

More Routing Constraints

You can leverage numerous Routing Constraints provided by Attribute Routing. I am taking example of some of them,

Range

To get the product within range, we can define the value, on condition that it should exist in database.
        [GET("myproduct/{id:range(1, 3)}")]
        public HttpResponseMessage Get(int id)
        {
            var product = _productServices.GetProductById(id);
            if (product != null)
                return Request.CreateResponse(HttpStatusCode.OK, product);
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No product found for this id");
        }

Regular Expression

You can use it well for text/string parameters more efficiently.
        [GET(@"id/{e:regex(^[0-9]$)}")]
        public HttpResponseMessage Get(int id)
        {
            var product = _productServices.GetProductById(id);
            if (product != null)
                return Request.CreateResponse(HttpStatusCode.OK, product);
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No product found for this id");
        }

e.g. [GET(@"text/{e:regex(^[A-Z][a-z][0-9]$)}")]

Optional Parameters and Default Parameters

You can also mark the service parameters as optional in the route. For example you want to fetch an employee detail from the data base with his name,
[GET("employee/name/{firstname}/{lastname?}")]
public string GetEmployeeName(string firstname, string lastname="mittal")
{
   …………….
  ……………….
}
In the above mentioned code, I marked last name as optional by using question mark ‘?’ to fetch the employee detail. It’s my end user wish to provide the last name or not.
So the above endpoint could be accessed through GET verb with urls,
~/employee/name/akhil/mittal
~/employee/name/akhil
If a route parameter defined is marked optional, you must also provide a default value for that method parameter.
In the above example, I marked ‘lastname’ as an optional one and so provided a default value in the method parameter , if user doesn’t send any value, “mittal” will be used.
In .NET 4.5 Visual Studio > 2010 with WebAPI 2, you can define DefaultRoute as an attribute too, just try it by your own. Use attribute [DefaultRoute] to define default route values.
You can try giving custom routes to all your controller actions.
I marked my actions as,
        // GET api/product
        [GET("allproducts")]
        [GET("all")]
        public HttpResponseMessage Get()
        {
            var products = _productServices.GetAllProducts();
            var productEntities = products as List ?? products.ToList();
            if (productEntities.Any())
                return Request.CreateResponse(HttpStatusCode.OK, productEntities);
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Products not found");
        }

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

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

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

        // DELETE api/product/5
        [DELETE("remove/productid/{id}")]
        [DELETE("clear/productid/{id}")]
        [PUT("delete/productid/{id}")]
        public bool Delete(int id)
        {
            if (id > 0)
                return _productServices.DeleteProduct(id);
            return false;
        }
And therefore get the routes as,

GET

POST / PUT / DELETE

Check for more constraints here.
You must be seeing “v1/Products” in every route, that is due to RoutePrefix I have used at controller level. Let’s discuss RoutePrefix in detail.

RoutePrefix: Routing at Controller level

We were marking our actions with particular route, but guess what, we can mark our controllers too with certain route names, we can achieve this by using RoutePrefix attribute of AttributeRouting. Our controller was named Product, and I want to append Products/Product before my every action, there fore without duplicating the code at each and every action, I can decorate my Controller class with this name like shown below,
    [RoutePrefix("Products/Product")]
    public class ProductController : ApiController
    {
Now, since our controller is marked with this route, it will append the same to every action too. For e.g. route of following action,
        [GET("allproducts")]
        [GET("all")]
        public HttpResponseMessage Get()
        {
            var products = _productServices.GetAllProducts();
            var productEntities = products as List ?? products.ToList();
            if (productEntities.Any())
                return Request.CreateResponse(HttpStatusCode.OK, productEntities);
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Products not found");
        }
Now becomes,
~/Products/Product/allproducts
~/Products/Product/all

RoutePrefix: Versioning

Route prefix can also be used for versioning of the endpoints, like in my code I provided “v1” as version in my RoutePrefix as shown below,
    [RoutePrefix("v1/Products/Product")]
    public class ProductController : ApiController
    {
Therefore “v1” will be appended to every route / endpoint of the service. When we release next version, we can certainly maintain a change log separately and mark the endpoint as “v2” at controller level, that will append “v2” to all actions,
e.g.
~/v1/Products/Product/all

~/v2/Products/Product/allproducts
~/v2/Products/Product/all

RoutePrefix: Overriding

This functionality is present in .NET 4.5 with Visual Studio > 2010 with WebAPI 2. You can test it there.
There could be situations that we do not want to use RoutePrefix for each and every action. AttributeRoutingprovides such flexibility too, that despite of RoutePrefix present at controller level, an individual action could have its own route too. It just need to override the default route like shown below,

RoutePrefix at Controller

     [RoutePrefix("v1/Products/Product")]
    public class ProductController : ApiController
    {

Independent Route of Action

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

Disable Default Routes

You must be wondering that in the list of all the URL’s on service help page, we are getting some different/other routes that we have not defined through attribute routing starting like ~/api/Product. These routes are the outcome of default route provided in WebApiConfig file, remember? If you want to get rid of those unwanted routes, just go and comment everything written in Register method in WebApiConfig.cs file under Appi_Startfolder,
            //config.Routes.MapHttpRoute(
            //    name: "DefaultApi",
            //    routeTemplate: "api/{controller}/{id}",
            //    defaults: new { id = RouteParameter.Optional }
            //);
You can also remove the complete Register method, but for that you need to remove its calling too fromGlobal.asax file.

Running the application

Just run the application, we get,
We already have our test client added, but for new readers, just go to Manage Nuget Packages, by right clicking WebAPI project and type WebAPITestClient in searchbox in online packages,
You’ll get “A simple Test Client for ASP.NET Web API”, just add it. You’ll get a help controller in Areas-> HelpPage like shown below,
I have already provided the database scripts and data in my previous article, you can use the same.
Append “/help” in the application url, and you’ll get the test client,

GET

POST

PUT

DELETE

You can test each service by clicking on it. Once you click on the service link, you’ll be redirected to test the service page of that particular service. On that page there is a button Test API in the right bottom corner, just press that button to test your service,
Service for Get All products,
Likewise you can test all the service endpoints.

Conclusion

We now know how to define our custom endpoints and what its benefits are. Just to share that this library was introduced by Tim Call, author of http://attributerouting.net and Microsoft has included this in WebAPI 2 by default. My next article will explain token based authentication using ActionFilters in WepAPI. ’til then Happy Coding Smile | :) you can also download the complete source code from GitHub. Add the required packages, if they are missing in the source code.
Click Github Repository to browse for complete source code.

Download Source Code

References

My other series of articles:

RESTful Day #3: Resolve dependency of dependencies using Inversion of Control and dependency injection in ASP.NET Web APIs with Unity Container and Managed Extensibility Framework (MEF)


Download Source Code

Introduction

In my last two articles, I explained how to create a RESTful service using ASP.NET Web API working with Entity Framework and resolving dependencies using Unity Container. In this article, I’ll explain how to create a loosely coupled system with Unity Container and MEF (Managed Extensibility Framework) using Inversion of Control. I’ll not be explaining much theory but rather focus more on practical implementations. For the readers who are following this series, they can use their existing solution that they have created till time. For my new readers of this article, I have provided the download link for the previous source code and current source code as well.
For theory and understanding of DI and IOC you can follow the following links: Unity and Inversion of Control(IOC).

Roadmap

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

Existing Design and Problem

We already have an existing design. If you open the solution, you’ll get to see the structure as mentioned below,
We tried to design a loosely coupled architecture in the following way,
  • DataModel (responsible for communication with database) : Only talks to service layer.
  • Services (acts as a business logic layer between REST endpoint and data access) : Communicates between REST endpoint and DataModel.
  • REST API i.e. Controllers: Only talks to services via the interfaces exposed.
But when we tried to resolve the dependency of UnitOfWork from Services, we had to reference
DataModel dll in to our WebAPI project; this violated our system like shown in following image,
In this article we’ll try to resolve dependency (data model) of a dependency (services) from our existing solution. My controller depended on services and my services depended on data model. Now we’ll design an architecture in which components will be independent of each other in terms of object creation and instantiation. To achieve this we’ll make use of MEF(Managed Extensibility Framework) along with Unity Container and reflection.
Ideally, we should not be having the below code in our Bootstrapper class,
container.RegisterType().RegisterType(new HierarchicalLifetimeManager());

Managed Extensibility Framework (MEF)

You can have a read about Unity from msdn link. I am just quoting some lines from msdn,

“The Managed Extensibility Framework or MEF is a library for creating lightweight, extensible applications. It allows application developers to discover and use extensions with no configuration required. It also lets extension developers easily encapsulate code and avoid fragile hard dependencies. MEF not only allows extensions to be reused within applications, but across applications as well.”
“MEF is an integral part of the .NET Framework 4, and is available wherever the .NET Framework is used. You can use MEF in your client applications, whether they use Windows Forms, WPF, or any other technology, or in server applications that use ASP.NET.”

Creating a Dependency Resolver with Unity and MEF

Open your Visual studio, I am using VS 2010, you can use VS version 2010 or above. Load the solution.
Step 1: Right click solution explorer and add a new project named Resolver,
I have intentionally chosen this name, and you already know it why J
Step 2: Right click Resolver project and click on ManageNugetPackage, in the interface of adding new package, search Unity.MVC3 in online library,
Install the package to your solution.
Step 3: Right click resolver project and add a reference to System.ComponentModel.Composition.
You can find the dll into your GAC.I am using framework 4.0, so referring to the same version dll.
This DLL is the part of MEF and is already installed with .NET Framework 4.0 in the system GAC. This DLL provides classes that are very core of MEF.
Step 4: Just add an interface named IComponent to Resolver project that contains the initialization method named Setup. We’ll try to implement this interface into our Resolver class that we’ll create in our other projects like DataModel, Services and WebApI.
namespace Resolver
{
    /// <summary>
    /// Register underlying types with unity.
    /// </summary>
    public interface IComponent
    {
      
    }
}
Step 5: Before we declare our Setup method, just add one more interface responsible for serving as a contract to register types. I name this interface as IRegisterComponent,
namespace Resolver
{
    /// <summary>
    /// Responsible for registering types in unity configuration by implementing IComponent
    /// </summary>
    public interface IRegisterComponent
    {
        /// <summary>
        /// Register type method
        /// </summary>
        /// <typeparam name="TFrom"></typeparam>
        /// <typeparam name="TTo"></typeparam>
        /// <param name="withInterception"></param>
        void RegisterType(bool withInterception = false) where TTo : TFrom;
 
        /// <summary>
        /// Register type with container controlled life time manager
        /// </summary>
        /// <typeparam name="TFrom"></typeparam>
        /// <typeparam name="TTo"></typeparam>
        /// <param name="withInterception"></param>
        void RegisterTypeWithControlledLifeTime(bool withInterception = false) where TTo : TFrom;
    }
}
In this interface I have declared two methods, one RegisterType and other in to RegisterType with Controlled life time of the object, i.e. the life time of an object will be hierarchal in manner. This is kind of same like we do in Unity.
Step 6: Now declare Setup method on our previously created IComponent interface, that takes instance ofIRegisterComponent as a parameter,
void SetUp(IRegisterComponent registerComponent);
So our IComponent interface becomes,
namespace Resolver
{
    /// <summary>
    /// Register underlying types with unity.
    /// </summary>
    public interface IComponent
    {
        void SetUp(IRegisterComponent registerComponent);
    }
}
Step 6: Now we’ll write a packager or you can say a wrapper over MEF and Unity to register types/ components. This is the core MEF implementation. Create a class named ComponentLoader, and add following code to it,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
using System.Reflection;
 
namespace Resolver
{
    public static class ComponentLoader
    {
        public static void LoadContainer(IUnityContainer container, string path, string pattern)
        {
            var dirCat = new DirectoryCatalog(path, pattern);
            var importDef = BuildImportDefinition();
            try
            {
                using (var aggregateCatalog = new AggregateCatalog())
                {
                    aggregateCatalog.Catalogs.Add(dirCat);
 
                    using (var componsitionContainer = new CompositionContainer(aggregateCatalog))
                    {
                        IEnumerable exports = componsitionContainer.GetExports(importDef);
 
                        IEnumerable modules =
                            exports.Select(export => export.Value as IComponent).Where(m => m != null);
 
                        var registerComponent = new RegisterComponent(container);
                        foreach (IComponent module in modules)
                        {
                            module.SetUp(registerComponent);
                        }
                    }
                }
            }
            catch (ReflectionTypeLoadException typeLoadException)
            {
                var builder = new StringBuilder();
                foreach (Exception loaderException in typeLoadException.LoaderExceptions)
                {
                    builder.AppendFormat("{0}\n", loaderException.Message);
                }
 
                throw new TypeLoadException(builder.ToString(), typeLoadException);
            }
        }
 
        private static ImportDefinition BuildImportDefinition()
        {
            return new ImportDefinition(
                def => true, typeof(IComponent).FullName, ImportCardinality.ZeroOrMore, false, false);
        }
    }
 
    internal class RegisterComponent : IRegisterComponent
    {
        private readonly IUnityContainer _container;
 
        public RegisterComponent(IUnityContainer container)
        {
            this._container = container;
            //Register interception behaviour if any
        }
 
        public void RegisterType(bool withInterception = false) where TTo : TFrom
        {
            if (withInterception)
            {
                //register with interception
            }
            else
            {
                this._container.RegisterType();
            }
        }
 
        public void RegisterTypeWithControlledLifeTime(bool withInterception = false) where TTo : TFrom
        {
            this._container.RegisterType(new ContainerControlledLifetimeManager());
        }
    }
}
Step 7: Now our Resolver wrapper is ready. Build the project and add its reference to DataModel, BusinessServices and WebApi project like shown below,

Setup Business Services

We already have added reference of Resolver in BusinessServices project. We agreed to implement IComponent interface in each of our project.
So create a class named DependencyResolver and implement IComponent interface into it, we make use of reflection too to import IComponent type. So add a class and add following code to that DependencyResolverclass,
using System.ComponentModel.Composition;
using DataModel;
using DataModel.UnitOfWork;
using Resolver;
 
namespace BusinessServices
{
    [Export(typeof(IComponent))]
    public class DependencyResolver : IComponent
    {
        public void SetUp(IRegisterComponent registerComponent)
        {
            registerComponent.RegisterType();
 
        }
    }
}
Note that we have implemented SetUp method and in the same method we registered type for my ProductService.
All of the existing code base remains same. We don’t need to touch the IProductServices interface or ProductServices class.

Setup DataModel

We have added Resolver project reference to DataModel project as well. So we’ll try to register the type of UnitOfWork in this project. We proceed in same fashion, just add a DependencyResolver class and implement its Setup method to register type of UnitOfWork. To make the code more readable and standard, I made a change.I just added an interface for UnitOfWork and named it IUnitOfWork. Now my UnitOfWork class derives from this, you can do this exercise in earlier versions of projects we discussed in first two articles.
So my IUnitOfWork contains declaration of a single public method in UnitOfWork,
namespace DataModel.UnitOfWork
{
    public interface IUnitOfWork
    {
        /// <summary>
        /// Save method.
        /// </summary>
        void Save();
    }
}
Now register the type for UnitOfWork in DepenencyResolver class, our class becomes as shown below,
using System.ComponentModel.Composition;
using System.Data.Entity;
using DataModel.UnitOfWork;
using Resolver;
 
namespace DataModel
{
    [Export(typeof(IComponent))]
    public class DependencyResolver : IComponent
    {
        public void SetUp(IRegisterComponent registerComponent)
        {
            registerComponent.RegisterType();
        }
    }
}
Again, no need to touch any existing code of this project.

Setup REST endpoint / WebAPI project

Our 90% of the job is done.
We now need to setup or WebAPI project. We’ll not add any DependencyResolver class in this project. We’ll invert the calling mechanism of layers in Bootstrapper class that we already have, so when you open your bootstrapper class, you’ll get the code something like,
using System.Web.Http;
using System.Web.Mvc;
using BusinessServices;
using DataModel.UnitOfWork;
using Microsoft.Practices.Unity;
using Unity.Mvc3;
 
namespace WebApi
{
    public static class Bootstrapper
    {
        public static void Initialise()
        {
            var container = BuildUnityContainer();
 
            DependencyResolver.SetResolver(new UnityDependencyResolver(container));
 
            // register dependency resolver for WebAPI RC
            GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
        }
 
        private static IUnityContainer BuildUnityContainer()
        {
            var container = new UnityContainer();
 
            // register all your components with the container here
            // it is NOT necessary to register your controllers
           
            // e.g. container.RegisterType();       
            container.RegisterType().RegisterType(new HierarchicalLifetimeManager());
 
            return container;
        }
    }
}
Now, we need to change the code base a bit to make our system loosely coupled.Just remove the reference of DataModel from WebAPI project.
We don’t want our DataModel to be exposed to WebAPI project, that was our aim though, so we cut down the dependency of DataModel project now.
Add following code of Bootstrapper class to the existing Bootstarpper class,
using System.Web.Http;
//using DataModel.UnitOfWork;
using Microsoft.Practices.Unity;
using Resolver;
using Unity.Mvc3;
 
namespace WebApi
{
    public static class Bootstrapper
    {
        public static void  Initialise()
        {
            var container = BuildUnityContainer();
 
            System.Web.Mvc.DependencyResolver.SetResolver(new UnityDependencyResolver(container));
 
            // register dependency resolver for WebAPI RC
            GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
        }
 
        private static IUnityContainer BuildUnityContainer()
        {
            var container = new UnityContainer();
 
            // register all your components with the container here
            // it is NOT necessary to register your controllers
           
            // e.g. container.RegisterType();       
           // container.RegisterType().RegisterType(new HierarchicalLifetimeManager());
 
            RegisterTypes(container);
 
            return container;
        }
 
        public static void RegisterTypes(IUnityContainer container)
        {
 
            //Component initialization via MEF
            ComponentLoader.LoadContainer(container, ".\\bin", "WebApi.dll");
            ComponentLoader.LoadContainer(container, ".\\bin", "BusinessServices.dll");
 
        }
    }
}
It is kind of redefining Bootstrapper class without touching our existing controller methods. We now don’t even have to register type for ProductServices as well, we already did this in BusinessServices project.
Note that in RegisterTypes method we load components/dlls through reflection making use of ComponentLoader.We wrote two lines, first to load WebAPI.dll and another one to load Business Services.dll.
Had the name of BusinessServicess.dll be WebAPI.Services.dll, then we would have only written one line of code to load both the WebAPI and BusinessService dll like shown below,
ComponentLoader.LoadContainer(container, ".\\bin", "WebApi*.dll");
Yes we can make use of Regex.

Running the application

Just run the application, we get,
We already have our test client added, but for new readers, just go to Manage Nuget Packages, by right clicking WebAPI project and type WebAPITestClient in searchbox in online packages,
You’ll get “A simple Test Client for ASP.NET Web API”, just add it. You’ll get a help controller in Areas-> HelpPage like shown below,
I have already provided the database scripts and data in my previous article, you can use the same.
Append “/help” in the application url, and you’ll get the test client,
You can test each service by clicking on it. Once you click on the service link, you’ll be redirected to test the service page of that particular service. On that page there is a button Test API in the right bottom corner, just press that button to test your service,
Service for GetAllProduct,
For Create a new product,
In database, we get new product,
Update product:
We get in database,
Delete product:
In database:

Advantages of this design

In my earlier articles I focussed more on design flaws, but our current design have emerged with few added advantages,
  1. We got an extensible and loosely coupled application design that can go far with more new components added in the same way.
  2. Registering types automatically through reflection. Suppose we want to register any Interface implementation to our REST endpoint, we just need to load that dll in our Bootstrapper class, or if dll’s are of common suffix names then we just have to place that DLL in bin folder, and that will automatically be loaded at run time.
  3. Database transactions or any of such module is now not exposed to the service endpoint, this makes our service more secure and maintains the design structure too.

Conclusion

We now know how to use Unity container to resolve dependency and perform inversion of control using MEF too. In my next article I’ll try to explain how we can open multiple endpoints to our REST service and create custom url’s in the true REST fashion in my WebAPI. Till then Happy Coding Smile | :) You can also download the source code from GitHub. Add the required packages, if they are missing in the source code.

Download Source Code

RESTful Day #1: Enterprise Level Application Architecture with Web API’s using Entity Framework, Generic Repository Pattern and Unit of Work


Introduction

I have been practicing, reading a lot about RESTful services for past few days. To my surprise I could not find a complete series of practical implementations of ASP.NET Web API’s on the web. My effort in this series will be to focus on how we can develop basic enterprise level application architecture with Web API’s.
We’ll be discussing less theory and doing more practical to understand how RESTful services can be created using an ORM, we choose Entity Framework here. My first article in the series is to set up a basic architecture of REST service based application. Later on in my upcoming articles, I’ll explain how we can follow best standards to achieve enterprise level architecture.

Roadmap

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

REST

Here is an extract from Wikipedia,
Unlike SOAP-based web services, there is no “official” standard for RESTful web APIs. This is because REST is an architectural style, while SOAP is a protocol. Even though REST is not a standard per se, most RESTful implementations make use of standards such as HTTP, URI, JSON, and XML.
I agree to it . Let’s do some coding.

Setup database

I am using SQL Server 2008 as a database server. I have provided the sql scripts to create the database in Sql Server, you can use the same to create one.I have given WebApiDb as my database name. My database contains three tables for now, Products, Tokens, User. In this tutorial we’ll only be dealing with product table to perform CURD operations using Web API and Entity framework. We’ll use Tokens and User in my upcoming article. For those who fail to create database through scripts, here is the structure you can follow,

Web API project

Open your Visual Studio, I am using VS 2010, You can use VS version 2010 or above.
Step 1: Create a new Project in your visual studio,
Step 2: There after choose to create ASP.NET MVC 4 Web application, and give it a name of your choice, I gave itWebAPI.
Step 3: Out of different type of project templates shown to you, choose Web API project,
Once done, you’ll get a project structure like shown below, with a default Home and Values controller.
You can choose to delete this ValuesController, as we’ll be using our own controller to learn.

Setup Data Access Layer

Let’s setup or data access layer first. We’ll be using Entity Framework 5.0 to talk to database. We’ll use Generic Repository Pattern and Unit of work pattern to standardize our layer.
Let’s have a look at the standard definition of Entity Framework given by Microsoft:
“The Microsoft ADO.NET Entity Framework is an Object/Relational Mapping (ORM) framework that enables developers to work with relational data as domain-specific objects, eliminating the need for most of the data access plumbing code that developers usually need to write. Using the Entity Framework, developers issue queries using LINQ, then retrieve and manipulate data as strongly typed objects. The Entity Framework’s ORM implementation provides services like change tracking, identity resolution, lazy loading, and query translation so that developers can focus on their application-specific business logic rather than the data access fundamentals.”
In simple language, Entity framework is an Object/Relational Mapping (ORM) framework. It is an enhancement to ADO.NET, an upper layer to ADO.NET that gives developers an automated mechanism for accessing and storing the data in the database.
Step 1 : Create a new class library in your visual studio, and name it DataModel as shown below,
Step2: In the same way, create one more project i.e. again a class library and call it BusinessEntities,
I’ll explain the use of this class library soon.
Step 3: Move on to your DataModel project , right click on it and add a new item, in the list shown, choose ADO.NET Data Model, and name it WebApiDataModel.edmx.
The file .edmx will contain the database information of our database that we created earlier, let’s set up this. You’ll be presented a wizard like follows,
Choose, generate from database. Choose Microsoft SQl Server like shown in the following image,
Click continue, then provide the credentials of your database, i.e. WebAPIdb, and connect it,
You’ll get a screen, showing the connection string of the database we chose,
Provide the name of the connection string as WebApiDbEntities and click Next.
Choose all the database objects, check all the check boxes, and provide a name for the model. I gave it a name WebApiDbModel.
Once you finish this wizard, you’ll get the schema ready in your datamodel project as follows,
We’ve got our schema in-place using Entity Framework. But few work is still remaining. We need our data context class and entities through which we’ll communicate with database.
So, moving on to next step.
Step 3: Click on tools in Visual Studio and open Extension manager. We need to get db context generator for our datamodel. We can also do it using default code generation item by right clicking in the edmx view and add code generation item, but that will generate object context class and that is heavier than db context. I want light weighted db context class to be created, so we’ll use extension manager to add a package and then create a db context class.
Search for Entity Framework Dbcontext generator in online gallery and select the one for EF 5.x like below,
I guess you need to restart Visual studio to get that into your templates.
Step 4 : Now right click in the .edmx file schema designer and choose “Add Code Generation Item..”.
Step 5 : Now you’ll see that we have got the template for the extension that we added, select that EF 5.x DbContext Generator and click Add.
After adding this we’ll get the db context class and its properties, this class is responsible for all database transactions that we need to perform, so our structure looks like as shown below,
Wow, we ended up in errors. But we got our db context class and our entity models, You can see them in our DataModel project. Errors? Nothing to worry about, it’s just we did not reference entity framework in our project. We’ll do it right away.
Step 6 : Go to Tools -> Library Packet Manager->Packet manager Console. You’ll get the console in left bottom of Visual studio.
Select dataModel project and write a command “Install-Package EntityFramework –Version 5.0.0” to install Entity Framework 5 in our DataModel project.
Press enter. And all the errors get resolved.

Generic Repository and Unit of Work

You can read about repository pattern and creating a repository in detail from my article :https://codeteddy.com/2013/09/03/learning-mvc-part-5repository-pattern-in-mvc3-application-with-entity-framework/.
Just to list down the benefits of Repository pattern,
  • It centralizes the data logic or Web service access logic.
  • It provides a substitution point for the unit tests.
  • It provides a flexible architecture that can be adapted as the overall design of the application evolves.
We’ll create a generic repository that works for all our entities. Creating repositories for each and every entity may result in lots of duplicate code in large projects.For creating Generic Repository you can follow : https://codeteddy.com/2013/09/03/learning-mvc-part-6-generic-repository-pattern-in-mvc3-application-with-entity-framework/
Step 1: Add a folder named GenericRepository in DataModel project and to that folder add a class named Generic Repository. Add following code to that class, that servers as a template based generic code for all the entities that will interact with database,
#region Using Namespaces...

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;

#endregion

namespace DataModel.GenericRepository
{
/// <summary>
    /// Generic Repository class for Entity Operations
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public class GenericRepository where TEntity : class
    {
#region Private member variables...
internal WebApiDbEntities Context;
internal DbSet DbSet;
#endregion

#region Public Constructor...
/// <summary>
        /// Public Constructor,initializes privately declared local variables.
        /// </summary>
        /// <param name="context"></param>
        public GenericRepository(WebApiDbEntities context)
        {
this.Context = context;
this.DbSet = context.Set();
        }
#endregion

#region Public member methods...

/// <summary>
        /// generic Get method for Entities
        /// </summary>
        /// <returns></returns>
        public virtual IEnumerable Get()
        {
            IQueryable query = DbSet;
return query.ToList();
        }

/// <summary>
        /// Generic get method on the basis of id for Entities.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual TEntity GetByID(object id)
        {
return DbSet.Find(id);
        }

/// <summary>
        /// generic Insert method for the entities
        /// </summary>
        /// <param name="entity"></param>
        public virtual void Insert(TEntity entity)
        {
            DbSet.Add(entity);
        }

/// <summary>
        /// Generic Delete method for the entities
        /// </summary>
        /// <param name="id"></param>
        public virtual void Delete(object id)
        {
            TEntity entityToDelete = DbSet.Find(id);
            Delete(entityToDelete);
        }

/// <summary>
        /// Generic Delete method for the entities
        /// </summary>
        /// <param name="entityToDelete"></param>
        public virtual void Delete(TEntity entityToDelete)
        {
if (Context.Entry(entityToDelete).State == EntityState.Detached)
            {
                DbSet.Attach(entityToDelete);
            }
            DbSet.Remove(entityToDelete);
        }

/// <summary>
        /// Generic update method for the entities
        /// </summary>
        /// <param name="entityToUpdate"></param>
        public virtual void Update(TEntity entityToUpdate)
        {
            DbSet.Attach(entityToUpdate);
            Context.Entry(entityToUpdate).State = EntityState.Modified;
        }

/// <summary>
        /// generic method to get many record on the basis of a condition.
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public virtual IEnumerable GetMany(Func<TEntity, bool> where)
        {
return DbSet.Where(where).ToList();
        }

/// <summary>
        /// generic method to get many record on the basis of a condition but query able.
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public virtual IQueryable GetManyQueryable(Func<TEntity, bool> where)
        {
return DbSet.Where(where).AsQueryable();
        }

/// <summary>
        /// generic get method , fetches data for the entities on the basis of condition.
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public TEntity Get(Func<TEntity, Boolean> where)
        {
return DbSet.Where(where).FirstOrDefault();
        }

/// <summary>
        /// generic delete method , deletes data for the entities on the basis of condition.
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public void Delete(Func<TEntity, Boolean> where)
        {
            IQueryable objects = DbSet.Where(where).AsQueryable();
foreach (TEntity obj in objects)
                DbSet.Remove(obj);
        }

/// <summary>
        /// generic method to fetch all the records from db
        /// </summary>
        /// <returns></returns>
        public virtual IEnumerable GetAll()
        {
return DbSet.ToList();
        }

/// <summary>
        /// Inclue multiple
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="include"></param>
        /// <returns></returns>
        public IQueryable GetWithInclude(
            System.Linq.Expressions.Expression<Func<TEntity, 
bool>> predicate, params string[] include)
        {
            IQueryable query = this.DbSet;
            query = include.Aggregate(query, (current, inc) => current.Include(inc));
return query.Where(predicate);
        }

/// <summary>
        /// Generic method to check if entity exists
        /// </summary>
        /// <param name="primaryKey"></param>
        /// <returns></returns>
        public bool Exists(object primaryKey)
        {
return DbSet.Find(primaryKey) != null;
        }

/// <summary>
        /// Gets a single record by the specified criteria (usually the unique identifier)
        /// </summary>
        /// <param name="predicate">Criteria to match on</param>
        /// <returns>A single record that matches the specified criteria</returns>
        public TEntity GetSingle(Func<TEntity, bool> predicate)
        {
return DbSet.Single(predicate);
        }

/// <summary>
        /// The first record matching the specified criteria
        /// </summary>
        /// <param name="predicate">Criteria to match on</param>
        /// <returns>A single record containing the first record matching the specified criteria</returns>
        public TEntity GetFirst(Func<TEntity, bool> predicate)
        {
return DbSet.First(predicate);
        }


#endregion
    }
}

Unit of Work

Again I’ll not explain in detail what Unit of Work is. You can google about the theory or follow my existing article on MVC with Unit of Work.
To give a heads up, again from my existing article, the important responsibilities of Unit of Work are,
  • To manage transactions.
  • To order the database inserts, deletes, and updates.
  • To prevent duplicate updates. Inside a single usage of a Unit of Work object, different parts of the code may mark the same Invoice object as changed, but the Unit of Work class will only issue a single UPDATE command to the database.
The value of using a Unit of Work pattern is to free the rest of our code from these concerns so that you can otherwise concentrate on business logic.
Step 1: Create a folder named UnitOfWork, add a class to that folder named UnitOfWork.cs,
Add GenericRepository properties for all the three entities that we got. The class also implementsIDisposableinterface and it’s method Dispose to free up connections and objects. The class will be as follows,
#region Using Namespaces...

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Data.Entity.Validation;
using DataModel.GenericRepository;

#endregion

namespace DataModel.UnitOfWork
{
/// <summary>
    /// Unit of Work class responsible for DB transactions
    /// </summary>
    public class UnitOfWork : IDisposable
    {
#region Private member variables...

private WebApiDbEntities _context = null;
private GenericRepository _userRepository;
private GenericRepository _productRepository;
private GenericRepository _tokenRepository;
#endregion

public UnitOfWork()
        {
            _context = new WebApiDbEntities();
        }

#region Public Repository Creation properties...

/// <summary>
        /// Get/Set Property for product repository.
        /// </summary>
        public GenericRepository ProductRepository
        {
get
            {
if (this._productRepository == null)
this._productRepository = new GenericRepository(_context);
return _productRepository;
            }
        }

/// <summary>
        /// Get/Set Property for user repository.
        /// </summary>
        public GenericRepository UserRepository
        {
get
            {
if (this._userRepository == null)
this._userRepository = new GenericRepository(_context);
return _userRepository;
            }
        }

/// <summary>
        /// Get/Set Property for token repository.
        /// </summary>
        public GenericRepository TokenRepository
        {
get
            {
if (this._tokenRepository == null)
this._tokenRepository = new GenericRepository(_context);
return _tokenRepository;
            }
        }
#endregion

#region Public member methods...
/// <summary>
        /// Save method.
        /// </summary>
        public void Save()
        {
try
            {
                _context.SaveChanges();
            }
catch (DbEntityValidationException e)
            {

var outputLines = new List<string>();
foreach (var eve in e.EntityValidationErrors)
                {
                    outputLines.Add(string.Format(
"{0}: Entity of type \"{1}\" in state \"{2}\" has the following validation errors:", DateTime.Now, 
                        eve.Entry.Entity.GetType().Name, eve.Entry.State));
foreach (var ve in eve.ValidationErrors)
                    {
                        outputLines.Add(string.Format("- Property: \"{0}\", Error: \"{1}\"", ve.PropertyName, ve.ErrorMessage));
                    }
                }
                System.IO.File.AppendAllLines(@"C:\errors.txt", outputLines);

throw e;
            }

        }

#endregion

#region Implementing IDiosposable...

#region private dispose variable declaration...
private bool disposed = false; 
#endregion

/// <summary>
        /// Protected Virtual Dispose method
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void Dispose(bool disposing)
        {
if (!this.disposed)
            {
if (disposing)
                {
                    Debug.WriteLine("UnitOfWork is being disposed");
                    _context.Dispose();
                }
            }
this.disposed = true;
        }

/// <summary>
        /// Dispose method
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        } 
#endregion
    }
}
Now we have completely set up our data access layer, and our project structure looks like as shown below,

Setup Business Entities

Remember, we created a business entities project. You may wonder, we already have database entities to interact with database then why do we need Business Entities? The answer is as simple as that, we are trying to follow a proper structure of communication, and one would never want to expose the database entities to the end client, in our case is Web API, it involves lot of risk. Hackers may manipulate the details and get accessto your database.Instead we’ll use database entities in our business logic layer and use Business Entities as transfer objects to communicate between business logic and Web API project. So business entities may have different names but, their properties remains same as database entities. In our case we’ll add same name business entity classes appendint word “Entity” to them in our BusinessEntity project. So we’ll end up having three classes as follows,

Product entity

public class ProductEntity
    {
public int ProductId { get; set; }
public string ProductName { get; set; }
    }

Token entity

public class TokenEntity
    {
public int TokenId { get; set; }
public int UserId { get; set; }
public string AuthToken { get; set; }
public System.DateTime IssuedOn { get; set; }
public System.DateTime ExpiresOn { get; set; }
    }

User entity

public class UserEntity
    {
public int UserId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string Name { get; set; }
    }

Setup Business Services Project

Add a new class library to the solution named BusinessServices. This layer will act as our business logic layer. Note that, we can make use of our API controllers to write business logic, but I am trying to segregate my business logic in an extra layer so that if in future I want to use WCF, MVC, ASP.NET Web Pages or any other application as my presentation layer then I can easily integrate my Business logic layer in it.
We’ll make this layer testable, so we need to create an interface in and declare CURD operations that we need to perform over product table.Before we proceed, add the reference of BusinessEntities project and DataModel project to this newly created project
Step 1 : Create an interface named IProductServices and add following code to it for CURD operations methods,
using System.Collections.Generic;
using BusinessEntities;

namespace BusinessServices
{
/// <summary>
    /// Product Service Contract
    /// </summary>
    public interface IProductServices
    {
        ProductEntity GetProductById(int productId);
        IEnumerable GetAllProducts();
int CreateProduct(ProductEntity productEntity);
bool UpdateProduct(int productId,ProductEntity productEntity);
bool DeleteProduct(int productId);
    }
}
Step 2 : Create a class to implement this interface.name that class ProductServices,
The class contains a private variable of UnitOfWork and a constructor to initialize that variable,
private readonly UnitOfWork _unitOfWork;

/// <summary>
        /// Public constructor.
        /// </summary>
        public ProductServices()
        {
            _unitOfWork = new UnitOfWork();
        }
We have decided not to expose our db entities to Web API project, so we need something to map the db entities data to my business entity classes. We’ll make use of AutoMapper.You can read about AutoMapper in my this article.
Step 3: Just right click project-> Extension manager, search for AutoMapper in online galary and add to BusinessServices project,
Step 4: Implement methods in ProductServices class,
Add following code to the class,
using System.Collections.Generic;
using System.Linq;
using System.Transactions;
using AutoMapper;
using BusinessEntities;
using DataModel;
using DataModel.UnitOfWork;

namespace BusinessServices
{
/// <summary>
    /// Offers services for product specific CRUD operations
    /// </summary>
    public class ProductServices:IProductServices
    {
private readonly UnitOfWork _unitOfWork;

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

/// <summary>
        /// Fetches product details by id
        /// </summary>
        /// <param name="productId"></param>
        /// <returns></returns>
        public BusinessEntities.ProductEntity GetProductById(int productId)
        {
var product = _unitOfWork.ProductRepository.GetByID(productId);
if (product != null)
            {
                Mapper.CreateMap();
var productModel = Mapper.Map(product);
return productModel;
            }
return null;
        }

/// <summary>
        /// Fetches all the products.
        /// </summary>
        /// <returns></returns>
        public IEnumerable GetAllProducts()
        {
var products = _unitOfWork.ProductRepository.GetAll().ToList();
if (products.Any())
            {
                Mapper.CreateMap();
var productsModel = Mapper.Map<List, List>(products);
return productsModel;
            }
return null;
        }

/// <summary>
        /// Creates a product
        /// </summary>
        /// <param name="productEntity"></param>
        /// <returns></returns>
        public int CreateProduct(BusinessEntities.ProductEntity productEntity)
        {
using (var scope = new TransactionScope())
            {
var product = new Product
                {
                    ProductName = productEntity.ProductName
                };
                _unitOfWork.ProductRepository.Insert(product);
                _unitOfWork.Save();
                scope.Complete();
return product.ProductId;
            }
        }

/// <summary>
        /// Updates a product
        /// </summary>
        /// <param name="productId"></param>
        /// <param name="productEntity"></param>
        /// <returns></returns>
        public bool UpdateProduct(int productId, BusinessEntities.ProductEntity productEntity)
        {
var success = false;
if (productEntity != null)
            {
using (var scope = new TransactionScope())
                {
var product = _unitOfWork.ProductRepository.GetByID(productId);
if (product != null)
                    {
                        product.ProductName = productEntity.ProductName;
                        _unitOfWork.ProductRepository.Update(product);
                        _unitOfWork.Save();
                        scope.Complete();
                        success = true;
                    }
                }
            }
return success;
        }

/// <summary>
        /// Deletes a particular product
        /// </summary>
        /// <param name="productId"></param>
        /// <returns></returns>
        public bool DeleteProduct(int productId)
        {
var success = false;
if (productId > 0)
            {
using (var scope = new TransactionScope())
                {
var product = _unitOfWork.ProductRepository.GetByID(productId);
if (product != null)
                    {

                        _unitOfWork.ProductRepository.Delete(product);
                        _unitOfWork.Save();
                        scope.Complete();
                        success = true;
                    }
                }
            }
return success;
        }
    }
}
Let me explain the idea of the code. We have 5 methods as follows,
  1. To get product by id ( GetproductById ) : We call repository to get the product by id. Id comes as a parameter from the calling method to that service method. It returns the product entity from the database. Note that it will not return the exact db entity, instead we’ll map it with our business entity usingAutoMapper and return it to calling method.
    /// <summary>
            /// Fetches product details by id
            /// </summary>
            /// <param name="productId"></param>
            /// <returns></returns>
            public BusinessEntities.ProductEntity GetProductById(int productId)
            {
    var product = _unitOfWork.ProductRepository.GetByID(productId);
    if (product != null)
                {
                    Mapper.CreateMap();
    var productModel = Mapper.Map(product);
    return productModel;
                }
    return null;
            }
  2. Get all products from database (GetAllProducts) : This method returns all the products residing in database, again we make use of AutoMapper to map the list and return back.
    /// <summary>
            /// Fetches all the products.
            /// </summary>
            /// <returns></returns>
            public IEnumerable GetAllProducts()
            {
    var products = _unitOfWork.ProductRepository.GetAll().ToList();
    if (products.Any())
                {
                    Mapper.CreateMap();
    var productsModel = Mapper.Map<List, List>(products);
    return productsModel;
                }
    return null;
            }
  3. Create a new product (CreateProduct) : This method takes productBusinessEntity as an argument and creates a new object of actual database entity and insert it using unit of work.
    /// <summary>
            /// Creates a product
            /// </summary>
            /// <param name="productEntity"></param>
            /// <returns></returns>
            public int CreateProduct(BusinessEntities.ProductEntity productEntity)
            {
    using (var scope = new TransactionScope())
                {
    var product = new Product
                    {
                        ProductName = productEntity.ProductName
                    };
                    _unitOfWork.ProductRepository.Insert(product);
                    _unitOfWork.Save();
                    scope.Complete();
    return product.ProductId;
                }
            }
I guess you can now write update and delete methods. So I am writing the code of complete class,
using System.Collections.Generic;
using System.Linq;
using System.Transactions;
using AutoMapper;
using BusinessEntities;
using DataModel;
using DataModel.UnitOfWork;

namespace BusinessServices
{
/// <summary>
    /// Offers services for product specific CRUD operations
    /// </summary>
    public class ProductServices:IProductServices
    {
private readonly UnitOfWork _unitOfWork;

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

/// <summary>
        /// Fetches product details by id
        /// </summary>
        /// <param name="productId"></param>
        /// <returns></returns>
        public BusinessEntities.ProductEntity GetProductById(int productId)
        {
var product = _unitOfWork.ProductRepository.GetByID(productId);
if (product != null)
            {
                Mapper.CreateMap();
var productModel = Mapper.Map(product);
return productModel;
            }
return null;
        }

/// <summary>
        /// Fetches all the products.
        /// </summary>
        /// <returns></returns>
        public IEnumerable GetAllProducts()
        {
var products = _unitOfWork.ProductRepository.GetAll().ToList();
if (products.Any())
            {
                Mapper.CreateMap();
var productsModel = Mapper.Map<List, List>(products);
return productsModel;
            }
return null;
        }

/// <summary>
        /// Creates a product
        /// </summary>
        /// <param name="productEntity"></param>
        /// <returns></returns>
        public int CreateProduct(BusinessEntities.ProductEntity productEntity)
        {
using (var scope = new TransactionScope())
            {
var product = new Product
                {
                    ProductName = productEntity.ProductName
                };
                _unitOfWork.ProductRepository.Insert(product);
                _unitOfWork.Save();
                scope.Complete();
return product.ProductId;
            }
        }

/// <summary>
        /// Updates a product
        /// </summary>
        /// <param name="productId"></param>
        /// <param name="productEntity"></param>
        /// <returns></returns>
        public bool UpdateProduct(int productId, BusinessEntities.ProductEntity productEntity)
        {
var success = false;
if (productEntity != null)
            {
using (var scope = new TransactionScope())
                {
var product = _unitOfWork.ProductRepository.GetByID(productId);
if (product != null)
                    {
                        product.ProductName = productEntity.ProductName;
                        _unitOfWork.ProductRepository.Update(product);
                        _unitOfWork.Save();
                        scope.Complete();
                        success = true;
                    }
                }
            }
return success;
        }

/// <summary>
        /// Deletes a particular product
        /// </summary>
        /// <param name="productId"></param>
        /// <returns></returns>
        public bool DeleteProduct(int productId)
        {
var success = false;
if (productId > 0)
            {
using (var scope = new TransactionScope())
                {
var product = _unitOfWork.ProductRepository.GetByID(productId);
if (product != null)
                    {

                        _unitOfWork.ProductRepository.Delete(product);
                        _unitOfWork.Save();
                        scope.Complete();
                        success = true;
                    }
                }
            }
return success;
        }
    }
}
Job done at business service level. Let’s move on to API controller to call these methods.

Setup WebAPI project

Step1 : Just add the reference of BusinessEntity and BusinessService in the WebAPI project, our architecture becomes like this,
Step 2: Add a new WebAPI controller in Controller folder. Right click Controller folder and add a new controller.
We get a controller as follows,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace WebApi.Controllers
{
public class ProductController : ApiController
    {
// GET api/product
        public IEnumerable<string> Get()
        {
return new string[] { "value1", "value2" };
        }

// GET api/product/5
        public string Get(int id)
        {
return "value";
        }

// POST api/product
        public void Post([FromBody]string value)
        {
        }

// PUT api/product/5
        public void Put(int id, [FromBody]string value)
        {
        }

// DELETE api/product/5
        public void Delete(int id)
        {
        }
    }
}
We get HTTP VERBS as method names. Web API is smart enough to recognize request with the name of the VERB itself. In our case we are doing CRUD operations, so we don’t need to change the names of the method, we just needed this. We only have to write calling logic inside these methods. In my upcoming articles of the series, we will figure out how we can define new routes and provide method names of our choice with those routes.
Step 3: Add logic to call Business Service methods, just make an object of Business Service and call its respective methods, our Controller class becomes like,
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using BusinessEntities;
using BusinessServices;

namespace WebApi.Controllers
{
public class ProductController : ApiController
    {

private readonly IProductServices _productServices;

#region Public Constructor

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

#endregion

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

// GET api/product/5
        public HttpResponseMessage Get(int id)
        {
var product = _productServices.GetProductById(id);
if (product != null)
return Request.CreateResponse(HttpStatusCode.OK, product);
return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No product found for this id");
        }

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

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

// DELETE api/product/5
        public bool Delete(int id)
        {
if (id > 0)
return _productServices.DeleteProduct(id);
return false;
        }
    }
}
Just run the application, we get,
But now how do we test our API? We don’t have client. Guys, we’ll not be writing a client now to test it.We’ll add a package that will do all our work.
Just go to Manage Nuget Packages, by right clicking WebAPI project and type WebAPITestClient in searchbox in online packages,
You’ll get “A simple Test Client for ASP.NET Web API”, just add it. You’ll get a help controller in Areas-> HelpPage like shown below,

Running the Application

Before running the application, I have put some test data in our product table.
Just hit F5, you get the same page as you got earlier, just append “/help” in its url, and you’ll get the test client,
You can test each service by clicking on it.
Service for GetAllProduct,
For Create a new product,
In database, we get new product,
Update product:
We get in database,
Delete product:
In database:
Job done.

Design Flaws

  1. Architecture is tightly coupled. IOC (Inversion of Control) needs to be there.
  2. We cannot define our own routes.
  3. No exception handling and logging.
  4. No unit tetsts.

Conclusion

We now know how to create a WebAPI and perform CRUD operations using n layered architecture.
But still there are some flaws in this design.In my next two articles I’ll explain how to make the system loosely coupled using Dependency Injection Principle. We’ll also cover all the design flaws to make our design better and stronger. Till then Happy Coding J You can also download the source code from GitHub.

Web Services and Windows Services Interview Questions


WebServices And Windows Services

Can you give an example of when it would be appropriate to use a web service as opposed to non-serviced .NET component
Web service is one of main component in Service Oriented Architecture. You could use web services when your clients and servers are running on different networks and also different platforms. This provides a loosely coupled system. And also if the client is behind the firewall it would be easy to use web service since it runs on port 80 (by default) instead of having some thing else in Service Oriented Architecture applications.
What is the standard you use to wrap up a call to a Web service
“SOAP.

What is the transport protocol you use to call a Web service SOAP HTTP with SOAP
What does WSDL stand for? “WSDL stands for Web Services Dsescription Langauge. There is WSDL.exe that creates a .wsdl Files which defines how an XML Web service behaves and instructs clients as to how to interact with the service.
eg: wsdl http://LocalHost/WebServiceName.asmx
Where on the Internet would you look for Web Services?http://www.uddi.org

What does WSDL stand for? Web Services Description Language

True or False: To test a Web service you must create a windows application or Web application to consume this service? False.

What are the various ways of accessing a web service ?

1.Asynchronous Call
Application can make a call to the Webservice and then continue todo watever oit  wants to do.When the service is ready it will notify the application.Application  can use BEGIN and END method to make asynchronous call to the webmethod.We can use  either a WaitHandle or a Delegate object when making asynchronous call.
The WaitHandle class share resources between several objects. It provides several  methods which will wait for the resources to become available
The easiest and most powerful way to to implement an asynchronous call is using a  delegate object. A delegate object wraps up a callback function. The idea is to  pass a method in the invocation of the web method. When the webmethod has finished  it will call this callback function to process the result
2.Synchronous Call
Application has to wait until execution has completed.
 Note: Few of the references are taken from other sites/sources
 
What are VSDISCO files?VSDISCO files are DISCO files that support dynamic discovery of Web services. If you place the following VSDISCO file in a directory on your Web server, for example, it returns   references to all ASMX and DISCO files in the host directory and any subdirectories not noted in elements:
                <DYNAMICDISCOVERY
                  xmlns="urn:schemas-dynamicdiscovery:disco.2000-03-17">
                  <EXCLUDE path="_vti_cnf" />
                  <EXCLUDE path="_vti_pvt" />
                  <EXCLUDE path="_vti_log" />
                  <EXCLUDE path="_vti_script" />
                  <EXCLUDE path="_vti_txt" />
                </DYNAMICDISCOVERY>
 
How does dynamic discovery work?ASP.NET maps the file name extension VSDISCO to an HTTP handler that scans the host  directory and subdirectories for ASMX and DISCO files and returns a dynamically generated DISCO document. A client who requests a VSDISCO file gets back what appears to be a static DISCO document.
Note that VSDISCO files are disabled in the release version of ASP.NET. You can reenable them by uncommenting the line   in the section of Machine.config that maps *.vsdisco to System.Web.Services.Discovery.DiscoveryRequestHandler and granting the ASPNET  user account permission to read the IIS metabase. However, Microsoft is actively discouraging the use of VSDISCO files because they could represent a threat to Web server security.
 
Is it possible to prevent a browser from caching an ASPX page?
Just call SetNoStore on the HttpCachePolicy object exposed through the Response object’s Cache property, as demonstrated here:
        <%@ Page Language="C#" %>

<%
Response.Cache.SetNoStore ();
Response.Write (DateTime.Now.ToLongTimeString ());
%>

SetNoStore works by returning a Cache-Control: private, no-store header in the HTTP response. In this example, it prevents caching of a Web page that shows the current time.
What does AspCompat=”true” mean and when should I use it?
AspCompat is an aid in migrating ASP pages to ASPX pages. It defaults to false but should be set to true in any ASPX file that creates apartment-threaded COM objects–that is, COM objects registered ThreadingModel=Apartment. That includes all COM objects written with  Visual Basic 6.0. AspCompat should also be set to true (regardless of threading  model)  if the page creates COM objects that access intrinsic ASP objects such as Request and Response. The following directive sets AspCompat to true:
 <%@ Page AspCompat="true" %>
Setting AspCompat to true does two things. First, it makes intrinsic ASP objects available      to the COM components by placing unmanaged wrappers around the equivalent ASP.NET objects. Second, it improves the performance of calls that the page places to apartment- threaded COM objects by ensuring that the page (actually, the thread that processes the  request for the page) and the COM objects it creates share an apartment. AspCompat=”true” forces ASP.NET request threads into single-threaded apartments (STAs). If those threads create COM objects marked ThreadingModel=Apartment, then the objects are created in the same STAs as the threads that created them. Without AspCompat=”true,” request threads run in a multithreaded apartment (MTA) and each call to an STA-based COM object incurs a performance hit when it’s  marshaled across apartment boundaries.
Do not set AspCompat to true if your page uses no COM objects or if it uses COM objects that don’t access ASP intrinsic objects and that are registered ThreadingModel=Free or  ThreadingModel=Both.
Can two different programming languages be mixed in a single ASMX file?
No.
 
What namespaces are imported by default in ASMX files?
The following namespaces are imported by default. Other namespaces must be imported manually.· System, System.Collections,System.ComponentModel,System.Data, System.Diagnostics,System.Web,System.Web.Services
How do I provide information to the Web Service when the information is required as a SOAP Header?
The key here is the Web Service proxy you created using wsdl.exe or through Visual Studio .NET’s Add Web Reference menu option. If you happen to download a WSDL file for a Web Service that requires a SOAP header, .NET will create a SoapHeader class in the proxy source file. Using the previous example:
      public class Service1 : System.Web.Services.Protocols.SoapHttpClientProtocol
        {   
            public AuthToken AuthTokenValue;

[System.Xml.Serialization.XmlRootAttribute(Namespace=http://tempuri.org/&#8221;, IsNullable=false)]
public class AuthToken : SoapHeader { public string Token; }}

In this case, when you create an instance of the proxy in your main application file, you’ll also create an instance of the AuthToken class and assign the string:

     Service1 objSvc = new Service1();
     processingobjSvc.AuthTokenValue = new AuthToken();
     objSvc.AuthTokenValue.Token = <ACTUAL token value>;
     Web Servicestring strResult = objSvc.MyBillableWebMethod();
 
What is WSDL?
WSDL is the Web Service Description Language, and it is implemented as a specific XML vocabulary. While it’s very much more complex than what can be described here, there are two important aspects to WSDL with which you should be aware. First, WSDL provides instructions to consumers of Web Services to describe the layout and contents of the SOAP packets  the Web Service intends to issue. It’s an interface description document, of sorts. And second, it isn’t intended that you  read and interpret the WSDL. Rather, WSDL should be processed by machine, typically to generate proxy source code (.NET) or create dynamic proxies on the fly (the SOAP Toolkit or Web Service Behavior).
What is a Windows Service and how does its lifecycle differ from a “standard” EXE?
Windows service is a application that runs in the background. It is equivalent to a NT service.
The executable created is not a Windows application, and hence you can’t just click and run it . it needs to be installed as a service, VB.Net has a facility where we can add an installer to our program and then use a utility to install the service. Where as this is not the case with standard exe

How can a win service developed in .NET be installed or used in Win98?
Windows service cannot be installed on Win9x machines even though the .NET framework runs on machine.

 
Can you debug a Windows Service? How ? 
Yes we can debug a Windows Service.
Attach the WinDbg debugger to a service after the service starts
This method is similar to the method that you can use to attach a debugger to a process and then debug a process.
Use the process ID of the process that hosts the service that you want to debug
  1. To determine the process ID (PID) of the process that hosts the service that you want to debug, use one of the following methods.
    • Method 1: Use the Task Manager
      1. Right-click the taskbar, and then click Task Manager. The Windows Task Manager dialog box appears.
      2. Click the Processes tab of the Windows Task Manager dialog box.
      3. Under Image Name, click the image name of the process that hosts the service that you want to debug. Note the process ID of this process as specified by the value of the corresponding PID field.
    • Method 2: Use the Task List Utility (tlist.exe)
      1. Click Start, and then click Run. The Run dialog box appears.
      2. In the Open box, type cmd, and then click OK.
      3. At the command prompt, change the directory path to reflect the location of the tlist.exe file on your computer.Note The tlist.exe file is typically located in the following directory: C:\Program Files\Debugging Tools for Windows
      4. At the command prompt, type tlist to list the image names and the process IDs of all processes that are currently running on your computer.

    Note Make a note of the process ID of the process that hosts the service that you want to debug.

  2. At a command prompt, change the directory path to reflect the location of the windbg.exe file on your computer.Note If a command prompt is not open, follow steps a and b of Method 1. The windbg.exe file is typically located in the following directory: C:\Program Files\Debugging Tools for Windows.
  3. At the command prompt, type windbg –p ProcessID to attach the WinDbg debugger to the process that hosts the service that you want to debug.
Note ProcessID is a placeholder for the process ID of the process that hosts the service that you want to debug.

Use the image name of the process that hosts the service that you want to debug

You can use this method only if there is exactly one running instance of the process that hosts the service that you want to run. To do this, follow these steps:

  1. Click Start, and then click Run. The Run dialog box appears.
  2. In the Open box, type cmd, and then click OK to open a command prompt.
  3. At the command prompt, change the directory path to reflect the location of the windbg.exe file on your computer.Note The windbg.exe file is typically located in the following directory: C:\Program Files\Debugging Tools for Windows.
  4. At the command prompt, type windbg –pn ImageName to attach the WinDbg debugger to the process that hosts the service that you want to debug.
NoteImageName is a placeholder for the image name of the process that hosts the service that you want to debug. The “-pn” command-line option specifies that the ImageName command-line argument is the image name of a process. back to the top
Start the WinDbg debugger and attach to the process that hosts the service that you want to debug
  1. Start Windows Explorer.
  2. Locate the windbg.exe file on your computer.Note The windbg.exe file is typically located in the following directory: C:\Program Files\Debugging Tools for Windows
  3. Run the windbg.exe file to start the WinDbg debugger.
  4. On the File menu, click Attach to a Process to display the Attach to Process dialog box.
  5. Click to select the node that corresponds to the process that hosts the service that you want to debug, and then click OK.
  6. In the dialog box that appears, click Yes to save base workspace information. Notice that you can now debug the disassembled code of your service.
Configure a service to start with the WinDbg debugger attached
You can use this method to debug services if you want to troubleshoot service-startup-related problems.
1 Configure the “Image File Execution” options. To do this, use one of the following methods:
  • Method 1: Use the Global Flags Editor (gflags.exe)
    1. Start Windows Explorer.
    2. Locate the gflags.exe file on your computer.Note The gflags.exe file is typically located in the following directory: C:\Program Files\Debugging Tools for Windows.
    3. Run the gflags.exe file to start the Global Flags Editor.
    4. In the Image File Name text box, type the image name of the process that hosts the service that you want to debug. For example, if you want to debug a service that is hosted by a process that has MyService.exe as the image name, type MyService.exe.
    5. Under Destination, click to select the Image File Options option.
    6. Under Image Debugger Options, click to select the Debugger check box.
    7. In the Debugger text box, type the full path of the debugger that you want to use. For example, if you want to use the WinDbg debugger to debug a service, you can type a full path that is similar to the following: C:\Program Files\Debugging Tools for Windows\windbg.exe
      h. Click Apply, and then click OK to quit the Global Flags Editor.
  • Method 2: Use Registry Editor
    1. Click Start, and then click Run. The Run dialog box appears.
    2. In the Open box, type regedit, and then click OK to start Registry Editor.
    3. Warning If you use Registry Editor incorrectly, you may cause serious problems that may require you to reinstall your operating system. Microsoft cannot guarantee that you can solve problems that result from using Registry Editor incorrectly. Use Registry Editor at your own risk.In Registry Editor, locate, and then right-click the following registry subkey:
      HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
    4. Point to New, and then click Key. In the left pane of Registry Editor, notice that New Key #1 (the name of a new registry subkey) is selected for editing.
    5. Type ImageName to replace New Key #1, and then press ENTER.Note ImageName is a placeholder for the image name of the process that hosts the service that you want to debug. For example, if you want to debug a service that is hosted by a process that has MyService.exe as the image name, type MyService.exe.
    6. Right-click the registry subkey that you created in step e.
    7. Point to New, and then click String Value. In the right pane of Registry Editor, notice that New Value #1, the name of a new registry entry, is selected for editing.
    8. Replace New Value #1 with Debugger, and then press ENTER.
    9. Right-click the Debugger registry entry that you created in step h, and then click Modify. The Edit String dialog box appears.
    10. In the Value data text box, type DebuggerPath, and then click OK.

    Note DebuggerPath is a placeholder for the full path of the debugger that you want to use. For example, if you want to use the WinDbg debugger to debug a service, you can type a full path that is similar to the following: C:\Program Files\Debugging Tools for Windows\windbg.exe

2 For the debugger window to appear on your desktop, and to interact with the debugger, make your service interactive. If you do not make your service interactive, the debugger will start but you cannot see it and you cannot issue commands. To make your service interactive, use one of the following methods:
  • Method 1: Use the Services console
    1. Click Start, and then point to Programs.
    2. On the Programs menu, point to Administrative Tools, and then click Services. The Services console appears.
    3. In the right pane of the Services console, right-click ServiceName, and then click Properties.Note ServiceName is a placeholder for the name of the service that you want to debug.
    4. On the Log On tab, click to select the Allow service to interact with desktop check box under Local System account, and then click OK.
  • Method 2: Use Registry Editor
    1. In Registry Editor, locate, and then click the following registry subkey:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ServiceName
      Note Replace ServiceName with the name of the service that you want to debug. For example, if you want to debug a service named MyService, locate and then click the following registry key:
      HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MyService
    2. Under the Name field in the right pane of Registry Editor, right-click Type, and then click Modify. The Edit DWORD Value dialog box appears.
    3. Change the text in the Value data text box to the result of the binary OR operation with the binary value of the current text and the binary value, 0x00000100, as the two operands. The binary value, 0x00000100, corresponds to the SERVICE_INTERACTIVE_PROCESS constant that is defined in the WinNT.h header file on your computer. This constant specifies that a service is interactive in nature.
3 When a service starts, the service communicates to the Service Control Manager how long the service must have to start (the time-out period for the service). If the Service Control Manager does not receive a “service started” notice from the service within this time-out period, the Service Control Manager terminates the process that hosts the service. This time-out period is typically less than 30 seconds. If you do not adjust this time-out period, the Service Control Manager ends the process and the attached debugger while you are trying to debug. To adjust this time-out period, follow these steps:
  1. In Registry Editor, locate, and then right-click the following registry subkey: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
  2. Point to New, and then click DWORD Value. In the right pane of Registry Editor, notice that New Value #1 (the name of a new registry entry) is selected for editing.
  3. Type ServicesPipeTimeout to replace New Value #1, and then press ENTER.
  4. Right-click the ServicesPipeTimeout registry entry that you created in step c, and then click Modify. The Edit DWORD Value dialog box appears.
  5. In the Value data text box, type TimeoutPeriod, and then click OKNote TimeoutPeriod is a placeholder for the value of the time-out period (in milliseconds) that you want to set for the service. For example, if you want to set the time-out period to 24 hours (86400000 milliseconds), type 86400000.
  6. Restart the computer. You must restart the computer for Service Control Manager to apply this change.
4 Start your Windows service. To do this, follow these steps:
  1. Click Start, and then point to Programs.
  2. On the Programs menu, point to Administrative Tools, and then click Services. The Services console appears.
  3. In the right pane of the Services console, right-click ServiceName, and then click Start.
Note ServiceName is a placeholder for the name of the service that you want to debug.
 Note: Few of the references are taken from other sites/sources
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=3631&lngWId=10

C# and Asp.Net Questions (All in one)


Introduction

My this article provides a collection of numerous .Net, C#, ADO.NET, Web Services, .Net Framework questions and answers for which a reader has to look around for entire internet on different community web sites. Most of the questions and answers you must have already read. The purpose of this article is to consolidate at the most study material related to .Net at one single place.

ASP.NET

What is view state and use of it?The current property settings of an ASP.NET page and those of any ASP.NET server controls contained within the page. ASP.NET can detect when a form is requested for the first time versus when the form is posted (sent to the server), which  allows you to program accordingly.

What are user controls and custom controls?Custom controls:
 A control authored by a user or a third-party software vendor that does not belong to   the .NET Framework class library. This is a generic term that includes user controls. A  custom server control is used in Web Forms (ASP.NET pages). A custom client control is used  in Windows Forms applications.

User Controls:
In ASP.NET: A user-authored server control that enables an ASP.NET page to be re-used   as a server control. An ASP.NET user control is authored declaratively  and persisted as a  text file with an .ascx extension. The ASP.NET page framework compiles a user control on  the fly to a class that derives from the        System.Web.UI.UserControl class.

What are the validation controls?A set of server controls included with ASP.NET that test user input in HTML and Web server  controls for programmer-defined requirements. Validation controls perform input checking in server code. If the user is working with a browser that supports DHTML, the validation  controls can also perform validation using client script.

What’s the difference between Response.Write() andResponse.Output.Write()?The latter one allows you to write formattedoutput.

What methods are fired during the page load? Init () When the page is instantiated, Load() – when the page is loaded into server  memory,PreRender () – the brief moment before the page is displayed to the user  as HTML, Unload() – when page finishes loading.

Where does the Web page belong in the .NET Framework class hierarchy?System.Web.UI.Page

Where do you store the information about the user’s locale?System.Web.UI.Page.Culture

What’s the difference between Codebehind=”MyCode.aspx.cs” and Src=”MyCode.aspx.cs”?CodeBehind is relevant to Visual Studio.NET only.

What’s a bubbled event?
When you have a complex control, like DataGrid, writing an event processing routine for each object (cell, button,row, etc.) is quite tedious. The controls can bubble up their eventhandlers, allowing the main DataGrid event handler to take care of its constituents.
Suppose you want a certain ASP.NET function executed on MouseOver over a certain button.

Where do you add an event handler?It’s the Attributesproperty, the Add function inside that property.            
e.g. btnSubmit.Attributes.Add(“onMouseOver”,”someClientCode();”)

What data type does the RangeValidator control support?Integer,String and Date.

What are the different types of caching?
Caching is a technique widely used in computing to increase performance by keeping frequently accessed or expensive data in memory. In context of web application, caching is used to retain the pages or data across HTTP requests and reuse them without the expense of recreating them.ASP.NET has 3 kinds of caching strategiesOutput CachingFragment CachingData    

CachingOutput Caching: Caches the dynamic output generated by a request. Some times it is useful to cache  the output of a website even for a minute, which will result in a better  performance. For caching the whole page the page should have OutputCache directive.
Fragment Caching: Caches the portion of the  page generated by the request. Some times it is not practical to cache the entire page, in such cases we can cache a portion of page

Data Caching: Caches the objects programmatically. For     data caching asp.net provides a cache object for eg: cache[“States”] = dsStates;

What do you mean by authentication and authorization?Authentication is the process of validating a user on the credentials (username and     password) and authorization performs after authentication. After Authentication a user will     be verified for performing the various tasks, It access is limited it is known as       authorization.

What are different types of directives in .NET?
@Page: Defines page-specific attributes used by the ASP.NET page parser and compiler. Can       be included only in .aspx files   
@Control:Defines control-specific attributes used by the ASP.NET page parser and        compiler. Can be included only in .ascx files.
@Import: Explicitly imports a namespace into a page or user control. The Import         directive cannot have more than one namespace attribute. To import multiple     namespaces,     use multiple @Import directives.
@Implements: Indicates that the current page or user control implements the specified .NET      framework interface.
@Register: Associates aliases with namespaces and class names for concise notation in   custom server control syntax.
@Assembly: Links an assembly to the current page during compilation, making all         the     assembly’s classes and interfaces available for use on the      page.
@OutputCache: Declaratively controls the output caching policies of an ASP.NET page or a        user control contained in a page
@Reference: Declaratively indicates that another user control or page source file               should be dynamically compiled and linked against the page in which this directive is   declared.

Note: Few of the references are taken from other sites/sources


How do I debug an ASP.NET application that wasn’t written with Visual Studio.NET and that doesn’t use code-behind?Start the DbgClr debugger that comes with the .NET Framework SDK, open the file containing      the code you want to debug, and set your breakpoints. Start the ASP.NET application. Go back to DbgClr, choose Debug Processes from the Tools menu, and select  aspnet_wp.exe from  the list of processes. (If aspnet_wp.exe doesn’t appear in the list,check the “Show system      processes” box.) Click the Attach button to attach to aspnet_wp.exe and begin debugging.
Be sure to enable debugging in the ASPX file before debugging it with DbgClr. You can   enable tell ASP.NET to build debug executables by placing a
   statement at the top of an ASPX file or a   statement in a Web.config file.

Can a user browsing my Web site read my Web.config or Global.asax files?
No. The section of Machine.config, which holds the master configuration  settings for ASP.NET, contains entries that map ASAX files, CONFIG files, and selected  other file types to an HTTP handler named HttpForbiddenHandler, which fails attempts to retrieve the associated file. You can modify it by editing  Machine.config or including an section in a local Web.config file.

What’s the difference between Page.RegisterClientScriptBlock and Page.RegisterStartupScript?RegisterClientScriptBlock is for returning blocks of client-side script containing functions. RegisterStartupScript is for returning blocks of client-script not   packaged in functions-in other words, code that’s to execute when the page is loaded. The latter positions script blocks near the end of the document so elements on the page that the script interacts are loaded before the script runs.

Is it necessary to lock application state before accessing it?Only if you’re performing a multistep update and want the update to be treated as an atomic     operation. Here’s an example:

Application.Lock ();
                Application["ItemsSold"] = (int) Application["ItemsSold"] + 1;
                Application["ItemsLeft"] = (int) Application["ItemsLeft"] - 1;
                Application.UnLock ();


By locking application state before updating it and unlocking it afterwards, you ensure  that another request being processed on another thread doesn’t read application state   at exactly the wrong time and see an inconsistent view of it. If I update session state, should I lock it, too? Are concurrent accesses by multiple requests executing on multiple threads a concern with session state?
Concurrent accesses aren’t an issue with session state, for two reasons. One, it’s unlikely that two requests from the same user will overlap. Two, if they do overlap, ASP.NET locks down session state during request processing so that two threads can’t touch it at once. Session state is locked down when the HttpApplication instance that’s processing the request fires an AcquireRequestState event and unlocked when it fires a ReleaseRequestState event.

Do ASP.NET forms authentication cookies provide any protection against replay attacks? Do they, for example, include the client’s IP  address or anything else that would distinguish the real client from an attacker?
No. If an authentication cookie is stolen, it can be used by an attacker. It’s up to you to     prevent this from happening by using an encrypted communications channel (HTTPS). Authentication cookies issued as session cookies, do, however,include a time-out valid that     limits their lifetime. So a stolen session cookie can only be used in replay attacks as long as the ticket inside the cookie is valid. The default time-out interval is 30 minutes.You can change that by modifying the timeout attribute accompanying the element in Machine.config or a local Web.config file. Persistent authentication cookies do not  time-out and therefore are a more serious security threat if stolen.
How do I send e-mail from an ASP.NET application?
MailMessage message = new MailMessage ();
        message.From = ;
        message.To = ;
        message.Subject = "Scheduled Power Outage";
        message.Body = "Our servers will be down tonight.";
        SmtpMail.SmtpServer = "localhost";
        SmtpMail.Send (message);
 MailMessage and SmtpMail are classes defined in the .NET Framework Class Library’s  System.Web.Mail namespace. Due to a security change made to ASP.NET just before it shipped,  you need to set SmtpMail’s SmtpServer property to “localhost” even though “localhost” is  the default. In addition, you must use the IIS configuration applet to enable localhost  (127.0.0.1) to relay messages through the local SMTP service.
What are VSDISCO files?
VSDISCO files are DISCO files that support dynamic discovery of Web services. If you place the following VSDISCO file in a directory on your Web server, for example, it returns   references to all ASMX and DISCO files in the host directory and any subdirectories not         noted in elements:
<?xml version="1.0" ?>
<dynamicDiscovery
xmlns="urn:schemas-dynamicdiscovery:disco.2000-03-17">
<exclude path="_vti_cnf" />
<exclude path="_vti_pvt" />
<exclude path="_vti_log" />
<exclude path="_vti_script" />
<exclude path="_vti_txt" />
</dynamicDiscovery>
 

How does dynamic discovery work?
ASP.NET maps the file name extension VSDISCO to an HTTP handler that scans the host  directory and subdirectories for ASMX and DISCO files and returns a dynamically generated DISCO document. A client who requests a VSDISCO file gets back what appears to be a static DISCO document.
Note that VSDISCO files are disabled in the release version of ASP.NET. You can reenable them by uncommenting the line   in the section of Machine.config that maps *.vsdisco to System.Web.Services.Discovery.DiscoveryRequestHandler and granting the ASPNET  user account permission to read the IIS metabase. However, Microsoft is actively discouraging the use of VSDISCO files because they could represent a threat to Web server security.

Is it possible to prevent a browser from caching an ASPX page?
Just call SetNoStore on the HttpCachePolicy object exposed through the Response object’s Cache property, as demonstrated here:

<%@ Page Language="C#" %>
<html>
<body>
<%
              Response.Cache.SetNoStore ();
              Response.Write (DateTime.Now.ToLongTimeString ());
%>
</body>
</html>
SetNoStore works by returning a Cache-Control: private, no-store header in the HTTP response. In this example, it prevents caching of a Web page that shows the current time.
 
What does AspCompat=”true” mean and when should I use it?
AspCompat is an aid in migrating ASP pages to ASPX pages. It defaults to false but should be set to true in any ASPX file that creates apartment-threaded COM objects–that is, COM objects registered ThreadingModel=Apartment. That includes all COM objects written with  Visual Basic 6.0. AspCompat should also be set to true (regardless of threading  model)  if the page creates COM objects that access intrinsic ASP objects such as Request and Response. The following directive sets AspCompat to true:
<%@ Page AspCompat="true" %>
Setting AspCompat to true does two things. First, it makes intrinsic ASP objects available      to the COM components by placing unmanaged wrappers around the equivalent ASP.NET objects. Second, it improves the performance of calls that the page places to apartment- threaded COM objects by ensuring that the page (actually, the thread that processes the  request for the page) and the COM objects it creates share an apartment. AspCompat=”true” forces ASP.NET request threads into single-threaded apartments (STAs). If those threads create COM objects marked ThreadingModel=Apartment, then the objects are created in the same STAs as the threads that created them. Without AspCompat=”true,” request threads run in a multithreaded apartment (MTA) and each call to an STA-based COM object incurs a performance hit when it’s  marshaled across apartment boundaries.
Do not set AspCompat to true if your page uses no COM objects or if it uses COM objects that don’t access ASP intrinsic objects and that are registered ThreadingModel=Free or  ThreadingModel=Both.


Explain the differences between Server-side and Client-side code? Server side scripting means that all the script will be executed by the server and  interpreted as needed. ASP doesn’t have some of the functionality like sockets, uploading,  etc. For these you have to make a custom components usually in VB or VC++. Client side  scripting means that the script will be executed immediately in the browser such as form field validation, clock, email validation, etc. Client side scripting is usually done in  VBScript or JavaScript. Download time, browser compatibility, and visible code – since  JavaScript and VBScript code is included in the HTML page, then anyone can see the code by viewing the page source. Also a possible security hazards for the client computer.

 
What type of code (server or client) is found in a Code-Behind class?
C#


Should validation (did the user enter a real date) occur server-side or client-side? Why?Client-side validation because there is no need to request a server side date when you  could obtain a date from the client machine.

What are ASP.NET Web Forms? How is this technology different than what is available though ASP?
Web Forms are the heart and soul of ASP.NET. Web Forms are the User Interface (UI) elements that give your Web applications their look and feel. Web Forms are similar to Windows Forms in that they provide properties, methods, and events for the controls that are placed onto  them. However, these UI elements render themselves in the appropriate markup language   required by the request, e.g. HTML. If you use Microsoft Visual Studio .NET, you will also get the familiar drag-and-drop interface used to create your UI for your Web application.

 
What is the difference between Server.Transfer and Response.Redirect? Why would I choose one over the other?
In earlier versions of IIS, if we wanted to send a user to a new Web page, the only option we had was Response.Redirect. While this method does accomplish our goal, it has several important drawbacks. The biggest problem is that this method causes each page to be treated as a separate transaction. Besides making it difficult to maintain your transactional   integrity, Response.Redirect introduces some additional headaches. First, it prevents good encapsulation of code. Second, you lose access to all of the properties in the Request  object. Sure, there are workarounds, but they’re difficult. Finally, Response.Redirect  necessitates a round trip to the client, which, on high-volume sites, causes scalability problems.
As you might suspect, Server.Transfer fixes all of these problems. It does this by performing the transfer on the server without requiring a roundtrip to the client.


How can you provide an alternating color scheme in a Repeater control?
AlternatingItemTemplate Like the ItemTemplate element, but rendered for every other row (alternating items) in the Repeater control. You can specify a different appearance for the AlternatingItemTemplate element by setting its style properties.

 
Which template must you provide, in order to display data in a Repeater control?
ItemTemplate


What event handlers can I include in Global.asax?

Application_Start,Application_End, Application_AcquireRequestState, Application_AuthenticateRequest, Application_AuthorizeRequest, Application_BeginRequest, Application_Disposed,  Application_EndRequest, Application_Error, Application_PostRequestHandlerExecute, Application_PreRequestHandlerExecute,
Application_PreSendRequestContent, Application_PreSendRequestHeaders, Application_ReleaseRequestState, Application_ResolveRequestCache, Application_UpdateRequestCache, Session_Start,Session_End
You can optionally include “On” in any of method names. For example, you can name a BeginRequest event handler.Application_BeginRequest or Application_OnBeginRequest.You can also include event handlers in Global.asax for events fired by custom HTTP modules.Note that not all of the event handlers make sense for Web Services (they’re designed for ASP.NET applications in general, whereas .NET XML Web Services are specialized instances of an ASP.NET app). For example, the Application_AuthenticateRequest and Application_AuthorizeRequest events are designed to be used with ASP.NET Forms authentication.
 
What is different b/w  webconfig.xml & Machineconfig.xml
Web.config & machine.config both are configuration files.Web.config contains settings specific to an application where as machine.config contains settings to a computer. The Configuration system first searches settings in machine.config file & then looks in application configuration  files.Web.config, can appear in multiple directories on an ASP.NET Web application server. Each Web.config file applies configuration settings to its own directory and all child directories below it. There is only Machine.config file on a web server.
If I’m developing an application that must accomodate multiple security levels though secure login and my ASP.NET web appplication is spanned across three web-servers (using round-robbin load balancing) what would be the best approach to maintain login-in state for the users?
Use the state server or store the state in the database. This can be easily done through simple setting change in the web.config.
<SESSIONSTATE
StateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1; user id=sa; password="
cookieless="false"
timeout="30"
/>
You can specify mode as “stateserver” or “sqlserver”.
Where would you use an iHTTPModule, and what are the limitations of any approach you might take in implementing one
“One of ASP.NET’s most useful features is the extensibility of the HTTP pipeline, the path that data takes between client and server. You can use them to extend your ASP.NET applications by adding pre- and post-processing to each HTTP request coming into your application. For example, if you wanted custom authentication facilities for your application, the best technique would be to intercept the request when it comes in and process the request in a custom HTTP module.
 
How do you turn off cookies for one page in your site?
Since no Page Level directive is present, I am afraid that cant be done.


How do you create a permanent cookie? Permanent cookies are available until a specified expiration date, and are stored on the hard disk.So Set the ‘Expires’ property any value greater than DataTime.MinValue with respect to the current datetime. If u want the cookie which never expires set its Expires property equal to DateTime.maxValue.
Which method do you use to redirect the user to another page without performing a round trip to the client?
Server.Transfer and Server.Execute

 
What property do you have to set to tell the grid which page to go to when using the Pager object?
CurrentPageIndex


Should validation (did the user enter a real date) occur server-side or client-side? Why? It should occur both at client-side and Server side.By using expression validator control with the specified expression ie.. the regular expression provides the facility of only validatating the date specified is in the correct format or not. But for checking the date where it is the real data or not should be done at the server side, by getting the system date ranges and checking the date whether it is in between that range or not.

 
What does the “EnableViewState” property do? Why would I want it on or off? 
Enable ViewState turns on the automatic state management feature that enables server controls to re-populate their values on a round trip without requiring you to write any code. This feature is not free however, since the state of a control is passed to and from the server in a hidden form field. You should be aware of when ViewState is helping you and when it is not. For example, if you are binding a control to data on every round trip, then you do not need the control to maintain it’s view state, since you will wipe out any re-populated data in any case. ViewState is enabled for all server controls by default. To disable it, set the EnableViewState property of the control to false.


What is the difference between Server.Transfer and Response.Redirect? Why would I choose one over the other? 
Server.Transfer() : client is shown as it is on the requesting page only, but the all the content is of the requested page. Data can be persist accros the pages using Context.Item collection, which is one of the best way to transfer data from one page to another keeping the page state alive.

Response.Redirect() :client know the physical location (page name and query string as well). Context.Items loses the persisitance when nevigate to destination page. In earlier versions of IIS, if we wanted to send a user to a new Web page, the only option we had was Response.Redirect. While this method does accomplish our goal, it has several important drawbacks. The biggest problem is that this method causes each page to be treated as a separate transaction. Besides making it difficult to maintain your transactional integrity, Response.Redirect introduces some additional headaches. First, it prevents good encapsulation of code. Second, you lose access to all of the properties in the Request object. Sure, there are workarounds, but they’re difficult. Finally, Response.Redirect necessitates a round trip to the client, which, on high-volume sites, causes scalability problems. As you might suspect, Server.Transfer fixes all of these problems. It does this by performing the transfer on the server without requiring a roundtrip to the client.


Can you give an example of when it would be appropriate to use a web service as opposed to a non-serviced .NET component? 

  • Communicating through a Firewall When building a distributed application with 100s/1000s of users spread over multiple locations, there is always the problem of communicating between client and server because of firewalls and proxy servers. Exposing your middle tier components as Web Services and invoking the directly from a Windows UI is a very valid option.
  • Application Integration When integrating applications written in various languages and running on disparate systems. Or even applications running on the same platform that have been written by separate vendors.
  • Business-to-Business Integration This is an enabler for B2B intergtation which allows one to expose vital business processes to authorized supplier and customers. An example would be exposing electronic ordering and invoicing, allowing customers to send you purchase orders and suppliers to send you invoices electronically.
  • Software Reuse This takes place at multiple levels. Code Reuse at the Source code level or binary componet-based resuse. The limiting factor here is that you can reuse the code but not the data behind it. Webservice overcome this limitation. A scenario could be when you are building an app that aggregates the functionality of serveral other Applicatons. Each of these functions could be performed by individual apps, but there is value in perhaps combining the the multiple apps to present a unifiend view in a Portal or Intranet.
  • When not to use Web Services: Single machine Applicatons When the apps are running on the same machine and need to communicate with each other use a native API. You also have the options of using component technologies such as COM or .NET Componets as there is very little overhead.
  • Homogeneous Applications on a LAN If you have Win32 or Winforms apps that want to communicate to their server counterpart. It is much more efficient to use DCOM in the case of Win32 apps and .NET Remoting in the case of .NET Apps
Can you give an example of what might be best suited to place in the Application_Start and Session_Start subroutines? The Application_Start event is guaranteed to occur only once throughout the lifetime of the application. It’s a good place to initialize global variables. For example, you might want to retrieve a list of products from a database table and place the list in application state or the Cache object. SessionStateModule exposes both Session_Start and Session_End events.


What are the advantages and  disadvantages of viewstate?The primary advantages of the ViewState feature in ASP.NET are:

  1. Simplicity. There is no need to write possibly complex code to store form data between page submissions.
  2. Flexibility. It is possible to enable, configure, and disable ViewState on a control-by-control basis, choosing to persist the values of some fields but not others.
There are, however a few disadvantages that are worth pointing out:
  1. Does not track across pages. ViewState information does not automatically transfer from page to page. With the session approach, values can be stored in the session and accessed from other pages. This is not possible with ViewState, so storing data into the session must be done explicitly.
  2. ViewState is not suitable for transferring data for back-end systems. That is, data still has to be transferred to the back end using some form of data object.

Describe session handling in a webfarm, how does it work and what are the limits? ASP.NET Session supports storing of session data in 3 ways, i] in In-Process ( in the same memory that ASP.NET uses) , ii] out-of-process using Windows NT Service )in separate memory from ASP.NET ) or iii] in SQL Server (persistent storage). Both the Windows Service and SQL Server solution support a webfarm scenario where all the web-servers can be configured to share common session state store.

1. Windows Service :
We can start this service by Start | Control Panel | Administrative Tools | Services | . In that we service names  ASP.NET State Service. We can start or stop service by manually or configure to start automatically. Then we have to configure our web.config file

<CONFIGURATION><configuration>
<system.web>
<SessionState
mode = “StateServer”
stateConnectionString = “tcpip=127.0.0.1:42424”
stateNetworkTimeout = “10”
sqlConnectionString=”data source = 127.0.0.1; uid=sa;pwd=”
cookieless =”Flase”
timeout= “20” />
</system.web>
</configuration> </SYSTEM.WEB>
</CONFIGURATION>


Here ASP.Net Session is directed to use Windows Service for state management on local server (address : 127.0.0.1 is TCP/IP loop-back address). The default port is 42424. we can configure to any port but for that we have to manually edit the registry.
 Follow these simple steps

  • In a webfarm make sure you have the same config file in all your web servers.
  • Also make sure your objects are serializable.
  • For session state to be maintained across different web servers in the webfarm, the application path of the web-site in the IIS Metabase should be identical in all the web-servers in the webfarm.

Which template must you provide, in order to display data in a Repeater control? You have to use the ItemTemplate to Display data. Syntax is as follows,

< ItemTemplate >
< div class =”rItem” >
< img src=”images/<%# Container.DataItem(“ImageURL”)%>”  hspace=”10” />
< b > <% # Container.DataItem(“Title”)%>
< /div >
< ItemTemplate >
How can you provide an alternating color scheme in a Repeater control? 
Using the AlternatintItemTemplate


What property must you set, and what method must you call in your code, in order to bind the data from some data source to the Repeater control?
 Set the DataMember property to the name of the table to bind to. (If this property is not set, by default the first table in the dataset is used.)
DataBind method, use this method to bind data from a source to a server control. This method is commonly used after retrieving a data set through a database query.

What method do you use to explicitly kill a user s session?You can dump (Kill) the session yourself by calling the method Session.Abandon.

ASP.NET automatically deletes a user’s Session object, dumping its contents, after it has been idle for a configurable timeout interval. This interval, in minutes, is set in the section of the web.config file. The default is 20 minutes.
 
How do you turn off cookies for one page in your site? 
Use Cookie.Discard property, Gets or sets the discard flag set by the server. When true, this property instructs the client application not to save the Cookie on the user’s hard disk when a session ends.


Which two properties are on every validation control? We have two common properties for every validation controls

  1. Control to Validate,
  2. Error Message.
What tags do you need to add within the asp:datagrid tags to bind columns manually?
< asp:DataGrid id="dgCart" AutoGenerateColumns="False" CellPadding="4" Width="448px" runat="server"  >
< Columns >
< asp:ButtonColumn HeaderText="SELECT" Text="SELECT" CommandName="select" >< /asp:ButtonColumn >
< asp:BoundColumn DataField="ProductId" HeaderText="Product ID" >< /asp:BoundColumn >
< asp:BoundColumn DataField="ProductName" HeaderText="Product Name" >< /asp:BoundColumn >
< asp:BoundColumn DataField="UnitPrice" HeaderText="UnitPrice" >< /asp:BoundColumn >
< /Columns >
< /asp:DataGrid >
 
How do you create a permanent cookie? 
Permanent cookies are the ones that are most useful. Permanent cookies are available until a specified expiration date, and are stored on the hard disk. The location of cookies differs with each browser, but this doesn’t matter, as this is all handled by your browser and the server. If you want to create a permanent cookie called Name with a value of Nigel, which expires in one month, you’d use the following code
Response.Cookies ("Name") = "Nigel"
Response.Cookies ("Name"). Expires = DateAdd ("m", 1, Now ())


What tag do you use to add a hyperlink column to the DataGrid?

< asp:HyperLinkColumn > </ asp:HyperLinkColumn>


Which method do you use to redirect the user to another page without performing a round trip to the client?

Server.transfer
 
What is the transport protocol you use to call a Web service SOAP ?
HTTP Protocol
 
Explain role based security ?
Role Based Security lets you identify groups of users to allow or deny based on their role in the organization.In Windows NT and Windows XP, roles map to names used to identify user groups. Windows defines several built-in groups, including Administrators, Users, and Guests.To allow or deny access to certain groups of users, add the element to the authorization list in your Web application’s Web.config file.e.g.
<AUTHORIZATION>< authorization >
< allow roles="Domain Name\Administrators" / >   < !-- Allow Administrators in domain. -- >
< deny users="*"  / >                            < !-- Deny anyone else. -- >
< /authorization >
 
How do you register JavaScript for webcontrols ?
You can register javascript for controls using Attribtues.Add(scriptname,scripttext) method.
 
When do you set “” ?
Identity is a webconfig declaration under System.web, which helps to control the application Identity of the web applicaton. Which can be at any level(Machine,Site,application,subdirectory,or page), attribute impersonate with “true” as value specifies that client impersonation is used.


What are different templates available in Repeater,DataList and Datagrid ?

Templates enable one to apply complicated formatting to each of the items displayed by a control.Repeater control supports five types of templates.HeaderTemplate controls  how the header of the repeater control is formatted.ItemTemplate controls the formatting of each  item displayed.AlternatingItemTemplate controls how alternate items are formatted and the  SeparatorTemplate displays a separator between each item displyed.FooterTemplate is used for  controlling how the footer of the repeater control is formatted.The DataList and Datagrid supports two templates in addition to the above five.SelectedItem Template controls how a selected item is  formatted and EditItemTemplate controls how an item selected for editing is formatted.
 
What is ViewState ? and how it is managed ?
ASP.NET ViewState is a new kind of state service that developers can use to track  UI state on a per-user basis. Internally it uses an an old Web programming trick-roundtripping  state in a hidden form field and bakes it right into the page-processing framework.It needs less code to write and maintain state in your Web-based forms.
 
What is web.config file ?
Web.config file is the configuration file for the Asp.net web application. There is one web.config  file for one asp.net application which configures
the particular application. Web.config file is  written in XML with specific tags having specific meanings.It includes databa which includes
connections,Session States,Error Handling,Security etc.
For example :
< configuration >
< appSettings >
< add key="ConnectionString"
value="server=localhost;uid=sa;pwd=;database=MyDB" / >
< /appSettings >
< /configuration >
 
What is advantage of viewstate and what are benefits?
When a form is submitted in classic ASP, all form values are cleared. Suppose you have submitted a  form with a lot of information and the server comes back with an error. You will have to go back to  the form and correct the information. You click the back button, and what happens…….ALL form values are CLEARED, and you will have to start all over again! The site did not maintain your  ViewState.With ASP .NET, the form reappears in the browser window together with all form  values.This is because ASP .NET maintains your ViewState. The ViewState indicates the status of the  page when submitted to the server.
 
What tags do you need to add within the asp:datagrid tags to bind columns manually?
Set AutoGenerateColumns Property to false on the datagrid tag and then use Column tag and an ASP:databound tag
< asp:DataGrid runat="server" id="ManualColumnBinding" AutoGenerateColumns="False" >
< Columns >
< asp:BoundColumn HeaderText="Column1" DataField="Column1"/ >
< asp:BoundColumn HeaderText="Column2" DataField="Column2"/ >
< /Columns >
< /asp:DataGrid >
<asp:DataGrid id=ManualColumnBinding runat="server" AutoGenerateColumns="False">
<COLUMNS>   <asp:BoundColumn HeaderText="Column2" DataField="Column2"></asp:BoundColumn>
</asp:DataGrid>
 
Which property on a Combo Box do you set with a column name, prior to setting the DataSource, to display data in the combo box? 
DataTextField and  DataValueField


Which control would you use if you needed to make sure the values in two different controls matched?

CompareValidator is used to ensure that two fields are identical.
 
What is validationsummary server control?where it is used?.
The ValidationSummary control allows you to summarize the error messages from all validation controls on a Web page in a single location. The summary can be displayed as a list, a bulleted list, or a single paragraph, based on the value of the DisplayMode property. The error message displayed in the ValidationSummary control for each validation control on the page is specified by the ErrorMessage property of each validation control. If the ErrorMessage property of the validation control is not set, no error message is displayed in the ValidationSummary control for that validation control. You can also specify a custom title in the heading section of the ValidationSummary control by setting the HeaderText property.
You can control whether the ValidationSummary control is displayed or hidden by setting the ShowSummary property. The summary can also be displayed in a message box by setting the ShowMessageBox property to true.


What is the sequence of operation takes place when a page is loaded?BeginTranaction  – only if the request is transacted
Init    – every time a page is processed
LoadViewState  – Only on postback
ProcessPostData1  – Only on postback
Load    – every time
ProcessData2   – Only on Postback
RaiseChangedEvent  – Only on Postback
RaisePostBackEvent  – Only on Postback
PreRender   – everytime
BuildTraceTree  – only if tracing is enabled
SaveViewState  – every time
Render   – Everytime
End Transaction  – only if the request is transacted
Trace.EndRequest  – only when tracing is enabled
UnloadRecursive  – Every request

 
Difference between asp and asp.net?.
“ASP (Active Server Pages) and ASP.NET are both server side technologies for building web sites and web applications, ASP.NET is Managed compiled code – asp is interpreted. and ASP.net is fully Object oriented. ASP.NET has been entirely re-architected to provide a highly productive programming experience based on the .NET Framework, and a robust infrastructure for building reliable and scalable web
applications.”


Name the validation control available in asp.net?.RequiredField, RangeValidator,RegularExpression,Custom validator,compare Validator

What are the various ways of securing a web site that could prevent from hacking etc .. ?

  1. Authentication/Authorization
  2. Encryption/Decryption
  3. Maintaining web servers outside the corporate firewall. etc.,
What is the difference between in-proc and out-of-proc? 
An inproc is one which runs in the same process area as that of the client giving tha advantage of speed but the disadvantage of stability becoz if it crashes it takes the client application also with it.Outproc is one which works outside the clients memory thus giving stability to the client, but we have to compromise a bit on speed.
 
When you’re running a component within ASP.NET, what process is it running within on Windows XP? Windows 2000? Windows 2003?
On Windows 2003 (IIS 6.0) running in native mode, the component is running within the w3wp.exe process associated with the application pool which has been configured for the web application containing the component.
On Windows 2003 in IIS 5.0 emulation mode, 2000, or XP, it’s running within the IIS helper process whose name I do not remember, it being quite a while since I last used IIS 5.0.
 
What does aspnet_regiis -i do ?

Aspnet_regiis.exe is The ASP.NET IIS Registration tool allows an administrator or installation program to easily update the script maps for an ASP.NET application to point to the ASP.NET ISAPI version associated with the tool. The tool can also be used to display the status of all installed versions of ASP. NET, register the ASP.NET version coupled with the tool, create client-script directories, and perform other configuration operations.

When multiple versions of the .NET Framework are executing side-by-side on a single computer, the ASP.NET ISAPI version mapped to an ASP.NET application determines which version of the common language runtime is used for the application.

The tool can be launched with a set of optional parameters. Option “i” Installs the version of ASP.NET associated with Aspnet_regiis.exe and updates the script maps at the IIS metabase root and below. Note that only applications that are currently mapped to an earlier version of ASP.NET are affected

 
What is a PostBack? 
The process in which a Web page sends data back to the same page on the server.


What is ViewState? How is it encoded? Is it encrypted? Who uses ViewState? ViewState is the mechanism ASP.NET uses to keep track of server control state values that don’t otherwise post back as part of the HTTP form. ViewState Maintains the UI State of a Page
  ViewState is base64-encoded. 
 It is not encrypted but it can be encrypted by setting EnableViewStatMAC=”true” & setting the machineKey validation type to 3DES.  If you want to NOT maintain the ViewState, include the directive at the top of an .aspx page or add the attribute EnableViewState=”false” to any control.\

 
What is the element and what two ASP.NET technologies is it used for?
Configures keys to use for encryption and decryption of forms authentication cookie data and view state data, and for verification of out-of-process session state identification.There fore 2 ASP.NET technique in which it is used are Encryption/Decryption & Verification
 
What three Session State providers are available in ASP.NET 1.1? What are the pros and cons of each?
ASP.NET provides three distinct ways to store session data for your application: in-process session state, out-of-process session state as a Windows service, and out-of-process session state in a SQL Server database. Each has it advantages.
  1. In-process session-state mode
    Limitations:
    * When using the in-process session-state mode, session-state data is lost if aspnet_wp.exe or the application domain restarts.
    * If you enable Web garden mode in the element of the application’s Web.config file, do not use in-process session-state mode. Otherwise, random data loss can occur.
    Advantage:
    * in-process session state is by far the fastest solution. If you are storing only small amounts of volatile data in session state, it is recommended that you use the in-process provider.
  2. The State Server simply stores session state in memory when in out-of-proc mode. In this mode the worker process talks directly to the State Server
  3. SQL mode, session states are stored in a SQL Server database and the worker process talks directly to SQL. The ASP.NET worker processes are then able to take advantage of this simple storage service by serializing and saving (using .NET serialization services) all objects within a client’s Session collection at the end of each Web request
    Both these out-of-process solutions are useful primarily if you scale your application across multiple processors or multiple computers, or where data cannot be lost if a server or process is restarted.
What is the difference between HTTP-Post and HTTP-Get?
As their names imply, both HTTP GET and HTTP POST use HTTP as their underlying protocol. Both of these methods encode request parameters as name/value pairs in the HTTP request.
The GET method creates a query string and appends it to the script’s URL on the server that handles the request.
The POST method creates a name/value pairs that are passed in the body of the HTTP request message.
 
Name and describe some HTTP Status Codes and what they express to the requesting client.
When users try to access content on a server that is running Internet Information Services (IIS) through HTTP or File Transfer Protocol (FTP), IIS returns a numeric code that indicates the status of the request. This status code is recorded in the IIS log, and it may also be displayed in the Web browser or FTP client. The status code can indicate whether a particular request is successful or unsuccessful and can also reveal the exact reason why a request is unsuccessful. There are 5 groups ranging from 1xx – 5xx of http status codes exists.
101 – Switching protocols.
200 – OK. The client request has succeeded
302 – Object moved.
400 – Bad request.
500.13 – Web server is too busy.
 
Explain and the usage of VaryByParam, VaryByHeader.
OutputCache is used to control the caching policies of an ASP.NET page or user control. To cache a page @OutputCache directive should be defined as follows
VaryByParam: A semicolon-separated list of strings used to vary the output cache. By default, these strings correspond to a query string value sent with GET method attributes, or a parameter sent using the POST method. When this attribute is set to multiple parameters, the output cache contains a different version of the requested document for each specified parameter. Possible values include none, *, and any valid query string or POST parameter name.
VaryByHeader: A semicolon-separated list of HTTP headers used to vary the output cache. When this attribute is set to multiple headers, the output cache contains a different version of the requested document for each specified header.
 
What is the difference between repeater over datalist and datagrid?
The Repeater class is not derived from the WebControl class, like the DataGrid and DataList. Therefore, the Repeater lacks the stylistic properties common to both the DataGrid and DataList. What this boils down to is that if you want to format the data displayed in the Repeater, you must do so in the HTML markup.
The Repeater control provides the maximum amount of flexibility over the HTML produced. Whereas the DataGrid wraps the DataSource contents in an HTML
, and the DataList wraps the contents in either an HTMLor tags (depending on the DataList’s RepeatLayout property), the Repeater adds absolutely no HTML content other than what you explicitly specify in the templates.While using Repeater control, If we wanted to display the employee names in a bold font we’d have to alter the “ItemTemplate” to include an HTML bold tag, Whereas with the DataGrid or DataList, we could have made the text appear in a bold font by setting the control’s ItemStyle-Font-Bold property to True.The Repeater’s lack of stylistic properties can drastically add to the development time metric. For example, imagine that you decide to use the Repeater to display data that needs to be bold, centered, and displayed in a particular font-face with a particular background color. While all this can be specified using a few HTML tags, these tags will quickly clutter the Repeater’s templates. Such clutter makes it much harder to change the look at a later date. Along with its increased development time, the Repeater also lacks any built-in functionality to assist in supporting paging, editing, or editing of data. Due to this lack of feature-support, the Repeater scores poorly on the usability scale.
However, The Repeater’s performance is slightly better than that of the DataList’s, and is more noticeably better than that of the DataGrid’s. Following figure shows the number of requests per second the Repeater could handle versus the DataGrid and DataList
 
Can we handle the error and redirect to some pages using web.config?
Yes, we can do this, but to handle errors, we must know the error codes; only then we can take the user to a proper error message page, else it may confuse the user.
CustomErrors Configuration section in web.config file:
The default configuration is:
< customErrors mode="RemoteOnly"
defaultRedirect="Customerror.aspx" >
< error statusCode="404" redirect="Notfound.aspx" / >
< /customErrors >
If mode is set to Off, custom error messages will be disabled. Users will receive detailed exception error messages.
If mode is set to On, custom error messages will be enabled.
If mode is set to RemoteOnly, then users will receive custom errors, but users accessing the site locally will receive detailed error messages.
Add an tag for each error you want to handle. The error tag will redirect the user to the Notfound.aspx page when the site returns the 404 (Page not found) error.
[Example]
There is a page MainForm.aspx
Private
Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles MyBase.Load
'Put user code to initialize the
page here
Dim str As System.Text.StringBuilder
str.Append("hi") ' Error Line as str is not instantiated
Response.Write(str.ToString)
End Sub
[Web.Config]
‘ a simple redirect will take the user to Error.aspx [user defined] error file.
< customErrors mode="RemoteOnly" defaultRedirect="Customerror.aspx" >
< error statusCode="404" redirect="Notfound.aspx" / >
< /customErrors >
'This will take the user to NotFound.aspx defined in IIS.
 
How do you implement Paging in .Net?
The DataGrid provides the means to display a group of records from the data source (for example, the first 10), and then navigate to the “page” containing the next 10 records, and so on through the data.
Using Ado.Net we can explicit control over the number of records returned from the data source, as well as how much data is to be cached locally in the DataSet.
  1. Using DataAdapter.fill method give the value of ‘Maxrecords’ parameter
    (Note: – Don’t use it because query will return all records but fill the dataset based on value of ‘maxrecords’ parameter).
  2. For SQL server database, combines a WHERE clause and a ORDER BY clause with TOP predicate.
  3. If Data does not change often just cache records locally in DataSet and just take some records from the DataSet to display.
What is the difference between Server.Transfer and Response.Redirect?
Server.Transfer() : client is shown as it is on the requesting page only, but the all the content is of the requested page. Data can be persist across the pages using Context.Item collection, which is one of the best way to transfer data from one page to another keeping the page state alive.
Response.Dedirect() :client knows the physical location (page name and query string as well). Context.Items loses the persistence when navigate to destination page. In earlier versions of IIS, if we wanted to send a user to a new Web page, the only option we had was Response.Redirect. While this method does accomplish our goal, it has several important drawbacks. The biggest problem is that this method causes each page to be treated as a separate transaction. Besides making it difficult to maintain your transactional integrity, Response.Redirect introduces some additional headaches. First, it prevents good encapsulation of code. Second, you lose access to all of the properties in the Request object. Sure, there are workarounds, but they’re difficult. Finally, Response.Redirect necessitates a round trip to the client, which, on high-volume sites, causes scalability problems. As you might suspect, Server.Transfer fixes all of these problems. It does this by performing the transfer on the server without requiring a roundtrip to the client.
Response.Redirect sends a response to the client browser instructing it to request the second page. This requires a round-trip to the client, and the client initiates the Request for the second page. Server.Transfer transfers the process to the second page without making a round-trip to the client. It also transfers the HttpContext to the second page, enabling the second page access to all the values in the HttpContext of the first page.
 
Can you create an app domain?
Yes, We can create user app domain by calling on of the following overload static methods of the System.AppDomain class
  1. Public static AppDomain CreateDomain(String friendlyName)
  2. Public static AppDomain CreateDomain(String friendlyName, Evidence securityInfo)
  3. Public static AppDomain CreateDomain(String friendlyName, Evidence securityInfo, AppDomainSetup info)
  4. Public static AppDomain CreateDomain(String friendlyName, Evidence securityInfo, String appBasePath, String appRelativeSearchPath, bool shadowCopyFiles)
What are the various security methods which IIS Provides apart from .NET ?
The various security methods which IIS provides are
  1. Authentication Modes
  2. IP Address and Domain Name Restriction
  3. DNS Lookups DNS Lookups
  4. The Network ID and Subnet Mask
  5. SSL
What is Web Gardening? How would using it affect a design?  
The Web Garden Model
The Web garden model is configurable through the section of the machine.config file. Notice that the section is the only configuration section that cannot be placed in an application-specific web.config file. This means that the Web garden mode applies to all applications running on the machine. However, by using the node in the machine.config source, you can adapt machine-wide settings on a per-application basis.
Two attributes in the section affect the Web garden model. They are webGarden and cpuMask. The webGarden attribute takes a Boolean value that indicates whether or not multiple worker processes (one per each affinitized CPU) have to be used. The attribute is set to false by default. The cpuMask attribute stores a DWORD value whose binary representation provides a bit mask for the CPUs that are eligible to run the ASP.NET worker process. The default value is -1 (0xFFFFFF), which means that all available CPUs can be used. The contents of the cpuMask attribute is ignored when the webGarden attribute is false. The cpuMask attribute also sets an upper bound to the number of copies of aspnet_wp.exe that are running.
Web gardening enables multiple worker processes to run at the same time. However, you should note that all processes will have their own copy of application state, in-process session state, ASP.NET cache, static data, and all that is needed to run applications. When the Web garden mode is enabled, the ASP.NET ISAPI launches as many worker processes as there are CPUs, each a full clone of the next (and each affinitized with the corresponding CPU). To balance the workload, incoming requests are partitioned among running processes in a round-robin manner. Worker processes get recycled as in the single processor case. Note that ASP.NET inherits any CPU usage restriction from the operating system and doesn’t include any custom semantics for doing this.