Friday, November 15, 2019

Web API


What is ASP.NET Web API ?
 ASP.NET Web API is a framework for building Web API’s, i.e. HTTP based services on top of the .NET Framework. The most common use case for using Web API is for building RESTful services. These services can then be consumed by a broad range of clients like
1. Browsers
2. Mobile applications
3. Desktop applications
4. IOTs

What are RESTful services
REST stands for Representational State Transfer. REST was first introduced in the year 2000 by Roy Fielding as part of his doctoral dissertation. REST is an architectural pattern for creating an API that uses HTTP as its underlying communication method. The REST architectural pattern specifies a set of constraints that a system should adhere to. Here are the REST constraints.
Client Server constraint - Client sends a request and the server sends a response. This separation of concerns supports the independent evolution of the client-side logic and server-side logic.

Stateless constraint - 
Cacheable constraint - 
Uniform Interface - The uniform interface constraint defines the interface between the client and the server. To understand the uniform interface constraint, we need to understand what a resource is and the HTTP verbs - GET, PUT, POST & DELETE.  Each resource is identified by a specific URI (Uniform Resource Identifier). The following table shows some typical requests that you see in an API
Another concept related to Uniform Interface is HATEOAS. HATEOAS stands for Hypermedia as the Engine of Application State. All this means is that in each request there will be set of hyperlinks that let's you know what other actions can be performed on the resource. 

we have ValuesController which inherits from ApiController class that is present in System.Web.Http namespace.
2. Notice in the ValuesController class we have methods (Get, Put, Post & Delete) that map to the HTTP verbs (GET, PUT, POST, DELETE) respectively.
WebApiConfig class
CRUD
HTTP Verb
Create
POST
Read
GET
Update
PUT
Delete
DELETE

Request Verbs : These HTTP verbs (GET, POST, PUT & DELETE) describe what should be done with the resource. For example do you want to create, read, update or delete an entity. GET, PUT, POST and DELETE http verbs are the most commonly used one's. For the complete list of the HTTP verbs, please check http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

Request Header : When a client sends request to the server, the request contains a header and a body. The request header contains additional information such as what type of response is required. For example, do you want the response to be in XML or JSON.

Request Body : Request Body contains the data to send to the server. For example, a POST request contains the data for the new item that you want to create. The data format may be in XML or JSON.

Response Body : The Response Body contains the data sent as response from the server. For example, if the request is for a specific product, the response body includes product details either in XML or JSON format.

Response Status codes : These are the HTTP status codes, that give the client details on the status of the request. Some of the common status codes are 200/OK, 404/Not Found, 204/No Content. For the complete list of HTTP status codes and what they mean, please visit 
http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
200 (OK) or 204 (No Content) 
201 (Created)
 303 (See Other) 
202 (Accepted) 
500 Internal Server Error. We get status code 500, because of a NULL reference exception
The requested resource does not support http method 'GET' with the status code 405 Method Not Allowed
If the value for gender is not Male, Female or All, then the service should return status code 400 Bad Request

Content Negotiation: One of the standards of the RESTful service is that, the client should have the ability to decide in which format they want the response - XML, JSON etc. A request that is sent to the server includes an Accept header. Using the Accept header the client can specify the format for the response. For example

Accept: application/xml returns XML
Accept: application/json returns JSON

Depending on the Accept header value in the request, the server sends the response. This is called Content Negotiation. 

Media type formatters. :- ASP.NET Web API is greatly extensible. This means we can also plugin our own formatters, for custom formatting the data.
It's also very easy to change the serialization settings of these formatters.
 WebApiConfig.cs file in App_Start folder.

config.Formatters.JsonFormatter.SerializerSettings.Formatting =
                            Newtonsoft.Json.Formatting.Indented;
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver =
    new CamelCasePropertyNamesContractResolver();

Accept: application/xml,application/json

What is MediaTypeFormatter
MediaTypeFormatter is an abstract class from which JsonMediaTypeFormatter and XmlMediaTypeFormatter classes inherit from. JsonMediaTypeFormatter handles JSON and XmlMediaTypeFormatter handles XML.

How to return only JSON from ASP.NET Web API Service irrespective of the Accept header value
Include the following line in Register() method of WebApiConfig.cs file in App_Start folder. This line of code completely removes XmlFormatter which forces ASP.NET Web API to always return JSON irrespective of the Accept header value in the client request. Use this technique when you want your service to support only JSON and not XML. 

With this change, irrespective of the Accept header value (application/xml or application/json), the Web API service is always going to return JSON.

config.Formatters.Remove(config.Formatters.XmlFormatter);

How to return only XML from ASP.NET Web API Service irrespective of the Accept header value

Include the following line in Register() method of WebApiConfig.cs file in App_Start folder. This line of code completely removes JsonFormatter which forces ASP.NET Web API to always return XML irrespective of the Accept header value in the client request. Use this technique when you want your service to support only XML and not JSON.

config.Formatters.Remove(config.Formatters.JsonFormatter);

With this change, irrespective of the Accept header value (application/xml or application/json), the Web API service is always going to return XML.

How to return JSON instead of XML from ASP.NET Web API Service when a request is made from the browser. 
So here is what we want the service to do
1. When a request is issued from the browser, the web API service should return JSON instead of XML. 
2. When a request is issued from a tool like fiddler the Accept header value should be respected. This means if the Accept header is set to application/xml the service should return XML and if it is set to application/json the service should return JSON.

There are 2 ways to achieve this

Approach 1 : Include the following line in Register() method of WebApiConfig.cs file in App_Start folder. This tells ASP.NET Web API to use JsonFormatter when a request is made for text/html which is the default for most browsers. The problem with this approach is that Content-Type header of the response is set to text/html which is misleading.

config.Formatters.JsonFormatter.SupportedMediaTypes
    .Add(new MediaTypeHeaderValue("text/html"));

Approach 2 : Include the following class in WebApiConfig.cs file in App_Start folder. 


public class CustomJsonFormatter : JsonMediaTypeFormatter
{
    public CustomJsonFormatter()
    {
        this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
    }

    public override void SetDefaultContentHeaders(Type type, HttpContentHeadersheaders, MediaTypeHeaderValue mediaType)
    {
        base.SetDefaultContentHeaders(type, headers, mediaType);
        headers.ContentType = new MediaTypeHeaderValue("application/json");
    }
}

Register the formatter: Place the following line in Register() method of WebApiConfig.cs file in App_Start folder
config.Formatters.Add(
new CustomJsonFormatter());

With these 2 changes, when a request is issued from the browser you will get JSON formatted data and the Content-Type header of the response is also set to application/json. If you are using tools like fiddler and if you set Accept header to application/xml you will still get XML formatted data.

ASP.NET Web API is an extinsible framework. This means you can also plugin your own custom formatter. For example, if you want the response to be in CSV format, you can create custom CSVMediaTypeFormatter that inherits from the base abstract class MediaTypeFormatter . The following article describes how to do this.

11. query string parameters in ASP.NET Web API
Query String
Data
http://localhost/api/employees?gender=All
All Employees
http://localhost/api/employees?gender=Male
Only Male Employees
http://localhost/api/employees?gender=Female
Only Female Employees

public HttpResponseMessage Put(int id, [FromBody]Employee employee)
{
    try
    {
        using (EmployeeDBEntities entities = new EmployeeDBEntities())
        {
            var entity = entities.Employees.FirstOrDefault(e => e.ID == id);
            if (entity == null)
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound,
                    "Employee with Id " + id.ToString() + " not found to update");
            }
            else
            {
                entity.FirstName = employee.FirstName;
                entity.LastName = employee.LastName;
                entity.Gender = employee.Gender;
                entity.Salary = employee.Salary;

                entities.SaveChanges();

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

Attributes that are used to map your custom named methods in the controller class to GET, POST, PUT and DELETE http verbs. 

Attribute
Maps to http verb
[HttpGet]
GET
[HttpPost]
POST
[HttpPut]
PUT
[HttpDelete]
DELETE

HttpResponseMessage .???????????????????????

public HttpResponseMessage Get(string gender = "All")
{
    using (EmployeeDBEntities entities = new EmployeeDBEntities())
    {
        switch (gender.ToLower())
        {
            case "all":
                return Request.CreateResponse(HttpStatusCode.OK,
                    entities.Employees.ToList());
            case "male":
                return Request.CreateResponse(HttpStatusCode.OK,
                    entities.Employees.Where(e => e.Gender.ToLower() == "male").ToList());
            case "female":
                return Request.CreateResponse(HttpStatusCode.OK,
                    entities.Employees.Where(e => e.Gender.ToLower() == "female").ToList());
            default:
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest,
                    "Value for gender must be Male, Female or All. " + gender + " is invalid.");
        }
    }
}

 12. use of FromBody and FromUri attributes
.
Web API maps the data in the request to the PUT method parameters in the EmployeesController. This process is called Parameter Binding.

public HttpResponseMessage Put([FromBody]int id, [FromUri]Employee employee)
{
    try
    {
        using (EmployeeDBEntities entities = new EmployeeDBEntities())
        {
            var entity = entities.Employees.FirstOrDefault(e => e.ID == id);
            if (entity == null)
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound,
                    "Employee with Id " + id.ToString() + " not found to update");
            }
            else
            {
                entity.FirstName = employee.FirstName;
                entity.LastName = employee.LastName;
                entity.Gender = employee.Gender;
                entity.Salary = employee.Salary;

                entities.SaveChanges();

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


What is same origin policy
Browsers allow a web page to make AJAX requests only with in the same domain. Browser security prevents a web page from making AJAX requests to another domain. This is called same origin policy. 
The following 2 URLs have the same origin
http://localhost:1234/api/employees
http://localhost:1234/Employees.html

So this proves, browsers does not allow cross domain ajax requests. There are 2 ways to get around this problem

·                     Using JSONP (JSON with Padding) 
·                     Enabling CORS (Cross Origin Resource Sharing)

So what is JSONP and what does it do?
JSONP stands for JSON with Padding. All JSONP does is wraps the data in a function. So for example, if you have the following JSON object
{
    "FirstName" : "Mark",
    "LastName"  : "Hastings",
    "Gender"    : "Male",
}

JSONP will wrap the data in a function as shown below
CallbackFunction({
    "FirstName" : "Mark",
    "LastName"  : "Hastings",
    "Gender"    : "Male",
})

Browsers allow to consume JavaScript that is present in a different domain but not data. Since the data is wrapped in a JavaScript function, this can be consumed by a web page that is present in a different domain.

Steps to make ASP.NET Web API Service to return JSONP formatted data and consume it from a cross domain ajax request
Step 1 : To support JSONP format, execute the following command using NuGet Package Manager Console which installs WebApiContrib.Formatting.Jsonp package.
Install-Package WebApiContrib.Formatting.Jsonp

Step 2 : Include the following 2 lines of code in Register() method of WebApiConfig class in WebApiConfig.cs file in App_Start folder

var jsonpFormatter = newJsonpMediaTypeFormatter(config.Formatters.JsonFormatter);
config.Formatters.Insert(0, jsonpFormatter);

Step 3 : In the ClientApplication, set the dataType option of the jQuery ajax function to jsonp 

dataType: 'jsonp'

15enable CORS 

To allow cross domain ajax calls by enabling CORS
Step 1 : Install Microsoft.AspNet.WebApi.Cors package. Execute the following command using NuGet Package Manager Console. Make sure to select "EmployeeService" project from "Default project" dropdown.
Install-Package Microsoft.AspNet.WebApi.Cors 

Step 2 : Include the following 2 lines of code in Register() method of WebApiConfig class in WebApiConfig.cs file in App_Start folder

EnableCorsAttribute cors = new EnableCorsAttribute("*""*""*");
config.EnableCors();

Step 3 : In the ClientApplication, set the dataType option of the jQuery ajax function to json

dataType: 'json'

Parameters of EnableCorsAttribute 
Parameter
Description
origins
Comma-separated list of origins that are allowed to access the resource. For example "http://www.pragimtech.com,http://www.mywebsite.com" will only allow ajax calls from these 2 websites. All the others will be blocked. Use "*" to allow all
headers
Comma-separated list of headers that are supported by the resource. For example "accept,content-type,origin" will only allow these 3 headers. Use "*" to allow all. Use null or empty string to allow none
methods
Comma-separated list of methods that are supported by the resource. For example "GET,POST" only allows Get and Post and blocks the rest of the methods. Use "*" to allow all. Use null or empty string to allow none

The following 2 lines of code in Register() method of WebApiConfig.cs file in App_Start folder, enables CORS globally for the entire application i.e for all controllers and action methods 

EnableCorsAttribute cors = new EnableCorsAttribute("*""*""*");
config.EnableCors();

EnableCors attribute can be applied on a specific controller or controller method. 

If applied at a controller level then it is applicable for all methods in the controller. To apply it at the controller level

1. There is no need to create an instance of 
EnableCorsAttribute in Register() method of WebApiConfig.cs file. Call the EnableCors() method without any parameter values.

config.EnableCors();


2. Apply the  EnableCorsAttribute on the controller class
[EnableCorsAttribute("*""*""*")]
public class EmployeesController : ApiController
{
}

In the same manner, you can also apply it at a method level if you wish to do so.


To disable CORS for a specific action apply [
DisableCors] on that specific action


What is Attribute Routing
Using the [Route] attribute to define routes is called Attribute Routing

What are the advantages of using Attribute Routing
Attribute routing gives us more control over the URIs than convention-based routing. Creating URI patterns like hierarchies of resources (For example, students have courses, Departments have employees) is very difficult with convention-based routing. With attribute routing all you have to do is use the [Route] attribute as shown below.

How to enable Attribute Routing
In ASP.NET Web API 2, Attribute Routing is enabled by default. The following line of code in WebApiConfig.cs file enables Attribute Routing.

config.MapHttpAttributeRoutes();


Can we use both Attribute Routing and Convention-based routing in a single Web API project
Yes, both the routing mechanisms can be combined in a single Web API project. The controller action methods that have the [Route] attribute uses Attribute Routing, and the others without [Route] attribute uses Convention-based routing. 

What is the use of RoutePrefix attribute
RoutePrefix attribute is used to specify the common route prefix at the controller level to eliminate the need to repeat that common route prefix on every controller action method

How to override the route prefix 
Use ~ character to override the route prefix 

Get Link

public HttpResponseMessage Post(Student student)
{
    students.Add(student);
    var response = Request.CreateResponse(HttpStatusCode.Created);
    response.Headers.Location = new Uri(Request.RequestUri + student.Id.ToString());
    return response;
}











In Web API 1, we have HttpResponseMessage type that a controller action method returns. A new type called "IHttpActionResult" is introduced in Web API 2 that can be returned from a controller action method. Instead of returning HttpResponseMessage from a controller action, we can now return IHttpActionResult. There are 2 main advantages of using the IHttpActionResult interface.

1.                   The code is cleaner and easier to read
2.                   Unit testing controller action methods is much simpler. We will discuss, how easy it is to unit test a method that returns IHttpActionResult instead of HttpResponseMessage in a later video


Consider the following StudentsController. Notice both the Get() methods return HttpResponseMessage. To create the HttpResponseMessage, we either use CreateResponse() or Cre           ateErrorResponse() methods of the Request object. 

public class StudentsController : ApiController
{
    static List<Student> students = new List<Student>()
    {
        new Student() { Id = 1, Name = "Tom" },
        new Student() { Id = 2, Name = "Sam" },
        new Student() { Id = 3, Name = "John" }
    };

    public HttpResponseMessage Get()
    {
        return Request.CreateResponse(students);
    }

    public HttpResponseMessage Get(int id)
    {
        var student = students.FirstOrDefault(s => s.Id == id);
        if (student == null)
        {
            return Request.CreateErrorResponse(HttpStatusCode.NotFound,
                "Student not found");
        }

        return Request.CreateResponse(student);
    }
}



In the following example, we have replaced both instances of HttpResponseMessage with IHttpActionResult. To return status code 200, we used Ok() helper method and to return status code 404, we used NotFound() method. To the Ok() method we have passed the type we want to return from the action method. Also notice, the code is now much cleaner and simpler to read. 

public class StudentsController : ApiController
{
    static List<Student> students = new List<Student>()
    {
        new Student() { Id = 1, Name = "Tom" },
        new Student() { Id = 2, Name = "Sam" },
        new Student() { Id = 3, Name = "John" }
    };

    public IHttpActionResult Get()
    {
        return Ok(students);
    }

    public IHttpActionResult Get(int id)
    {
        var student = students.FirstOrDefault(s => s.Id == id);
        if (student == null)
        {
            //return NotFound();
            return Content(HttpStatusCode.NotFound, "Student not found");
        }

        return Ok(student);
    }
}

In addition to Ok() and NotFound() helper methods, we have the following methods that we can use depending on what we want to return from our controller action method. All these methods return a type, that implements 
IHttpActionResult interface.

·                     BadRequest()
·                     Conflict()
·                     Created()
·                     InternalServerError()
·                     Redirect()
·                     Unauthorized()


Why is versioning required in Web API?

·                     Once a Web API service is made public, different client applications start using your Web API services.
·                     As the business grows and requirements change, we may have to change the services as well, but the changes to the services should be done in way that does not break any existing client applications.
·                     This is when Web API versioning helps. We keep the existing services as is, so we are not breaking the existing client applications, and develop a new version of the service that new client applications can start using.


Different options available to version Web API services : Versioning can be implemented using
1. URI's
2. Query String
3. Version Header
4. Accept Header
5. Media Type 






ApiControllerMethod
Description
BadRequest()
Creates a BadRequestResult object with status code 400.
Conflict()
Creates a ConflictResult object with status code 409.
Content()
Creates a NegotiatedContentResult with the specified status code and data.
Created()
Creates a CreatedNegotiatedContentResult with status code 201 Created.
CreatedAtRoute()
Creates a CreatedAtRouteNegotiatedContentResult with status code 201 created.
InternalServerError()
Creates an InternalServerErrorResult with status code 500 Internal server error.
NotFound()
Creates a NotFoundResult with status code404.
Ok()
Creates an OkResult with status code 200.
Redirect()
Creates a RedirectResult with status code 302.
RedirectToRoute()
Creates a RedirectToRouteResult with status code 302.
ResponseMessage()
Creates a ResponseMessageResult with the specified HttpResponseMessage.
StatusCode()
Creates a StatusCodeResult with the specified http status code.
Unauthorized()
Creates an UnauthorizedResult with status code 401.
























Web API Filters

Web API includes filters to add extra logic before or after action method executes. Filters can be used to provide cross-cutting features such as logging, exception handling, performance measurement, authentication and authorization.
Filters are actually attributes that can be applied on the Web API controller or one or more action methods. Every filter attribute class must implement IFilter interface included in System.Web.Http.Filters namespace. However, System.Web.Http.Filters includes other interfaces and classes that can be used to create filter for specific purpose.
The following table lists important interfaces and classes that can be used to create Web API filters.
Filter Type
Interface
Class
Description
Simple Filter
IFilter
-
Defines the methods that are used in a filter
Action Filter
IActionFilter
ActionFilterAttribute
Used to add extra logic before or after action methods execute.
Authentication Filter
IAuthenticationFilter
-
Used to force users or clients to be authenticated before action methods execute.
Authorization Filter
IAuthorizationFilter
AuthorizationFilterAttribute
Used to restrict access to action methods to specific users or groups.
Exception Filter
IExceptionFilter
ExceptionFilterAttribute
Used to handle all unhandled exception in Web API.
Override Filter
IOverrideFilter
-
Used to customize the behaviour of other filter for individual action method.
As you can see, the above table includes class as well as interface for some of the filter types. Interfaces include methods that must be implemented in your custom attribute class whereas filter class has already implemented necessary interfaces and provides virtual methods, so that they can be overridden to add extra logic. For example, ActionFilterAttribute class includes methods that can be overridden. We just need to override methods which we are interested in, whereas if you use IActionFilter attribute than you must implement all the methods.



Web API Request/Response Data Formats

Media Type

Media type (aka MIME type) specifies the format of the data as type/subtype e.g. text/html, text/xml, application/json, image/jpeg etc.
In HTTP request, MIME type is specified in the request header using Accept and Content-Type attribute. The Accept header attribute specifies the format of response data which the client expects and the Content-Type header attribute specifies the format of the data in the request body so that receiver can parse it into appropriate format.
For example, if a client wants response data in JSON format then it will send following GET HTTP request with Accept header to the Web API.

HTTP GET Request:  Accept : application \ json
HTTP POST Request: Content-Type : application \ json

ASP.NET Web API: Media-Type Formatters

As you have seen in the previous section that Web API handles JSON and XML formats based on Accept and Content-Type headers. But, how does it handle these different formats? The answer is: By using Media-Type formatters.
Media type formatters are classes responsible for serializing request/response data so that Web API can understand the request data format and send data in the format which client expects.
Web API includes following built-in media type formatters.
Media Type Formatter Class
MIME Type
Description
JsonMediaTypeFormatter
application/json, text/json
Handles JSON format
XmlMediaTypeFormatter
application/xml, text/json
Handles XML format
FormUrlEncodedMediaTypeFormatter
application/x-www-form-urlencoded
Handles HTML form URL-encoded data
JQueryMvcFormUrlEncodedFormatter
application/x-www-form-urlencoded
Handles model-bound HTML form URL-encoded data

Parameter Binding

In the previous section we learned how Web API routes HTTP request to a controller and action method. Here, we will learn how Web API binds HTTP request data to the parameters of an action method.
Action methods in Web API controller can have one or more parameters of different types. It can be either primitive type or complex type. Web API binds action method parameters either with URL's query string or with request body depending on the parameter type. By default, if parameter type is of .NET primitive type such as int, bool, double, string, GUID, DateTime, decimal or any other type that can be converted from string type then it sets the value of a parameter from the query string. And if the parameter type is complex type then Web API tries to get the value from request body by default.

Action Results Type

ASP.NET Web API converts the return value from a controller action into an HTTP response message.

A Web API controller action can return any of the following:
1.      void
2.      HttpResponseMessage
3.      IHttpActionResult
4.      Some other type
Depending on which of these is returned, Web API uses a different mechanism to create the HTTP response.

Return type
How Web API creates the response
Void
Return empty 204 (No Content)
HttpResponseMessage
Convert directly to an HTTP response message.
IHttpActionResult
Call ExecuteAsync to create an HttpResponseMessage, then convert to an HTTP response message.
Other type
Write the serialized return value into the response body; return 200 (OK).

void
If the return type is void, Web API simply returns an empty HTTP response with status code 204 (No Content).




No comments:

Post a Comment

Create JSON file and auto download in c#

 public void ConvertJson()     {         string _JsonFileName = string.Empty;         GSTInvoiceMaster _GST = new GSTInvoiceMaster(); ...