-
Notifications
You must be signed in to change notification settings - Fork 39
RESTful, Objects and JSON
HTTP stands for Hyper Text Transfer Protocol. It is a set of rules that enable us to send any kind of hypermedia document: json, xml, txt, html or even a movie over the internet.
Client - sends a request. Usually it is a browser (website client), but can be any running program (android app, desktop app).
Server - receives a request and sends a response back to the client. Usually consists of: one ore more computers and database(s).
Client by itself has nothing and is only able to request something: page (html), styling (css), code (js), data (json). The exact file formats will differ, but the idea of requesting something from a server and getting a response back is the same in almost all scenarios.
Web Service is what you can call a server. It is one or more computers hosted somehwere on the internet for one purpose only- process client requests.
REST has a scary definition- REpresentational State Transfer. Though in a nutshell, it is a kind of web service which serves a JSON.
REST is the most common kind of web service and therefore will be the focus for the rest of this chapter.
Locating resources in REST is very intuitive. A resource will sit on a server in any case, let's say mycoolserver.com
. Along with a web service, a client (website) might also be hosted on that server. Therefore, it's often a good idea to suffix REST part with /api
in order to segregate api from a website. Here is how to do typical REST query:
-
mycoolserver.com/api/people
- gets all people; -
mycoolserver.com/api/people/tom
- gets person named "tom" -
mycoolserver.com/api/people/tom/pets
- gets all pets which Tom has.
As you can see, REST allows us to neately provide endpoints for both different and related resources.
SOAP or Simple Object Access Protocol- is a kind of web service which serves XML.
This is an old one and mostly no longer used format for the new web services, therefore we will not talk much about it in the future.
HTTP request method or a verb is used to specify a kind of request. Here is a list of the most common ones.
All HTTP requests require a URL- a link to a server and endpoint which can process the request. Some requests also support sending a body- for example a text for a server to save.
Request body is something which is usually sent with POST, PUT or PATCH requests. It is usaully a JSON or XML. These days, the dominating request body format is JSON.
Let's say we have 2 people. One of them is Tom- male, 28 years, id 1. Another one is Juliet- female, 26 years, id 2. Tom has a single pet- a dog named Mouser, however it is not known what pets does Juliet have. You need to store them both in a request body.
JSON - stands for JavaScript Object Notation. It's the most lightweight way of transfering structured data.
{}
- marks an object
""
- property name or its text(or date) value
[]
- array
:
- property:value delimiter
,
- property seperator
null
- unknown
For example, representing Tom and Juliet in JSON looks like this:
[
{
"Id": 1,
"Name": "Tom",
"Gender": "Male",
"Age": 28,
"Pets": [
{
"Type": "Dog",
"Name": "Mouser"
}
]
},
{
"Id": 2,
"Name": "Juliet",
"Gender": "Female",
"Age": 26,
"Pets": null
}
]
JSON does not support comments. If you really need to write one, you can always use an ignored field, for example "_comment": "This is not very recommended"
.
XML - stands for Extensible Markup Language. It's the file format used most widely in a request body prior to JSON. It does have way more overhead, because of the way tags are organized and for the fact that it supports more than just having data in it (there is a capability of running actual scripts inside).
XML is very similar to HTML in that every property has an opening and a closing tag and a value in between. Like this: <mytag>My value</mytag>
.
For example:
<?xml version="1.0" encoding="UTF-8"?>
<People>
<Person>
<Id>1</Id>
<Age>28</Age>
<Gender>Male</Gender>
<Name>Tom</Name>
<Pets>
<Pet>
<Name>Mouser</Name>
<Type>Dog</Type>
</Pet>
</Pets>
</Person>
<Person>
<Id>2</Id>
<Age>26</Age>
<Gender>Female</Gender>
<Name>Juliet</Name>
<Pets null="true" />
</Person>
</People>
As you can see for yourself, the XML format is taking up way more characters (419) compared to the JSON one (332).
Gets a specified resource. Requests using GET should only retrieve data.
GET https://myfancyserver.com/people
Gets all people.
Submits an entity to the specified resource, often causing a change in state or side effects on the server. Sending POST twice often results in a duplicate. Usually used for creating a resource. Sometimes is also used for sending complicated queries to get something.
POST https://myfancyserver.com/people
[
{
"Id": 3,
"Name": "Domiiii",
"Gender": "Female",
"Age": 25,
"Pets": null
}
Creates a new person.
Applies full modifications (replaces existing values with values from payload) to a resource. Sending PUT multiple times should result in the same outcome (update with the same values). Usually used for updating a resource.
PUT https://myfancyserver.com/people/1
{
{
"Name": "Tom",
"Gender": "Male",
"Age": 30,
"Pets": []
}
}
Updates person of Id 1- they no longer have any pets and their age is now 30.
Applies partial modifications to a resource. Running PATCH multiple times maybe either yield the same results or not.
PUT https://myfancyserver.com/people/1
{
"Age": 31
}
Sets the age of a person of id 1 to 31.
Deletes the specified resource. Running DELETE twice should result in an error.
DELETE https://myfancyserver.com/people/3
Deletes person with Id 3.
HTTP headers carry additional information sent with requests. By themselves, headers don't really do anything, however, different tools and client libraries use them differently and therefore it's important to stick to conventional ways of adding them. Some headers are universal (works with any HTTP verb) others are specific to some response, request or content. Custom HTTP headers can also be sent. Here is the list of the most common headers. However, I would like to emphasise a few.
Which content types the client can process; if the field is empty, these are all content types.
Most common for us: application/json
.
Which compressed formats the client supports.
Most common for us: gzip, deflate, br
.
Authentication data (e.g. for a login)
We will only use this later in the course. A few months later.
We will use JWT (bearer token) there it will look something like: Bearer dfgd1ga756sdj3g7khg8k5jhfshrhef4fsdf
Usually autogenerated, species the length of request payload (body).
Specifies the type of body we send.
We will be mostly sending JSON, therefore: application/json
. Note that this is the same as Accept
.
Every HTTP Request will result in some HTTP Response. There almost a hundred of HTTP Status codes which indicate the outcome of a request. Let's have a look at the most common ones:
Request succeeded.
Request did not even start being executed, it's bad in some way.
Request itself is fine, but server failed executing it.
Is a tool to send HTTP requests. You can download it for free here.
-
Create a new workspace "Home"
-
Create a new collection "Testing 3rd Party
There is a list of public APIs which you can access for free, at any time.
Let's create a 2 requests to play around with 2 different APIs.
-
Create a new request and name it "Get sentimental analysis".
-
Select HTTP Method:
POST
-
Copy
https://sentim-api.herokuapp.com/api/v1/
and paste it right next to an HTTP verb. -
Click on
Body
tab and paste the following:{ "text": "My lesson is going GREAT!" }
-
Hit "Send" button
-
You should see a response evaluating the sentimental power of your text.
For this example, you will need an API key requested in https://developer.nytimes.com/my-apps/. API-Key is how many API providers allow random people to access their API in a controlled way. Through those keys, they can identify their callers, charge them or block them (for too many calls).
-
Create a new request and name it "Get Critics".
-
Select HTTP Method:
GET
-
Copy
https://api.nytimes.com/svc/movies/v2/critics/all.json
and paste it right next to HTTP verb. -
Click an
Authorization
tab and selectType
to beAPI Key
. Assign the following: Key: api-key
Value: paste your api key
Add to: query params (that's what that API's specification requires) -
Hit "Send" button
-
You should see a response returning all the movie critics.
Before we continue, we should take a step back into the world of C#. We already know that request body is often of JSON format- a way to structure data as an "object". What is an object?
Object- is a holder of logic and data. For requests and responses- we model objects to hold data-only.
What relation does a class have with an object? Class- is a blueprint: it defines what an object has (data) and what it can do (logic). In other words, using classes, we can create new objects.
We will never expose data directly, it will always be done through {get;set}
methods- properties. A framework also usually does some magic using properties and not fields (no get;set methods), therefore it is not just a nice way of saying what you can do with a field. For example, if you don't make model fields as properties- you won't be read/send the body sent by the server.
For example, creating people based on data of before will require a Person
class:
class Person
{
public int Id {get;set;}
public string Name{get;set;}
public int Age{get;set;}
public Pet[] Pets {get;set;}
}
class Pet
{
public string Type {get;set;}
public string Name {get;set;}
}
And creating 2 individuals: Tom and Juliet will be as simple as:
Person tom = new Person()
// Writing "tom." means we access properties of tom object.
tom.Id = 1;
tom.Name = "Tom";
tom.Age = 28;
tom.Pets = new Pet[]{new Pet{Type = "Dog", Name = "Mouser"}};
// Oject initialization - a way to assign properties during the creation of an object. Won't need juliet.Prop...
Person juliet = new Person
{
Id = 2,
Name = "Juliet",
Age = 25
}
How to, for example, print information about these two people?
Let's try calling Console.WriteLine(juliet);
.
Ohhh... It printed a class name instead of the data which the object has.
C# is not designed to print data of class objects. There are ways how you can achieve that, but for now we will do it manually: Console.WriteLine($"Name: {juliet.Name}, Age: {juliet.Age}");
Note: Will will talk a lot more about Object-Oriented Programming (OOP), but for now it's enough to understand what is an object, the difference from a class and how are they useful.
Objects allow us to group the related data and logic per short-lived instances. That's quite a difference compared with static- which causes a class to have a global state- "one" object.
In many cases, there is more than just one big thing and we won't keep track of multiple objects simultaneously. There is more than 1 person in the world, more than 1 book, etc...
A serialization is an act of making conversions from/to and object from/to a stream of bytes (for example a JSON or XML).
In .NET, there are multiple ways to achieve it, but 2 ways stick out:
- Using System.Text.Json - the native way in .NET of doing it
- Using Newtonsoft.Json library- the most popular way of doing it- happened before .NET had a native way of serializing data.
Takes an object and converts it to a string (for example JSON).
JsonSerializer.Serialize(obj);
JsonConvert.SerializeObject(object);
Take a string (for example JSON) and attempts to convert it back to an object.
JsonSerializer.Deserialize<ObjectType>(json);
JsonConvert.DeserializeObject<ObjectType>(json);
ASP.NET Core is a framework that enables the making of all kinds of web applications including websites and web services. Specifically, WebApi is a template used for making RESTful web services.
Create a new project using the WebApi template. Call it "ShoppingListApi". Select API template in the next window.
A new project will be created. Delete the existing controller and anything WeatherForecast
-related.
A controller is what defines endpoints accessible from an HTTP request. It's the in-between HTTP and business logic. The purpose of a controller is to take an HTTP request, forward that to a component that can handle it and return the results back in an HTTP response.
Create a new controller. It's just a class that derives from (:
) a ControllerBase
and has some attributes on it. Call it ShoppingListController
.
[ApiController]
[Route("api/[controller]")]
public class ShoppingListController : ControllerBase
{
}
[ApiController]
- ASP.NET Core identifies this class as such and adds API-specific behaviour.
[Route("api/[controller]")]
- controller endpoints will start with api/shoppinglist
.
: ControllerBase
- enables the use of controller-specific methods.
Add a method to create a shopping list:
[HttpPost]
public IActionResult Create(ShoppingList shoppingList)
{
return Ok();
}
IActionResult
- is used in order to return any kind of HTTP message. Sometimes, it might be Ok
with a body, sometimes an empty okay, in other cases a bad request or internal server error. IActionResult gives us flexibility and returns different response types, rather than having to be coupled to just one. Therefore, always apply this type over any other specific type. For example, if we were to return a Person when getting one- we would not be able to return a specific error if something went wrong (other than internal server error).
[HttpPost]
will require POST
as an HTTP verb.
Add a method to get a shopping list:
[HttpGet]
public IActionResult Get()
{
// Code
}
[HttpGet]
will require GET
as an HTTP verb.
Add a method to delete a shopping list:
[HttpDelete("{id}")]
public IActionResult Delete(int shoppingListId)
{
// code
}
[HttpDelete]
will require DELETE
as an HTTP verb.
Use the Person
and Pet
classes from before, but this time also add a SpouseId property. Also add a method: public void Marry(Person other person)
which marries two people (hint- requirement 6 below).
Create an endpoint for each operation:
- Add person
- Add a pet to an existing person
- Remove person
- Remove pet from an existing person
- Update an existing person data
- Marry two people
If an operation is not possible, return an appropriate HTTP status code. Demonstrate each request and response using Postman.
- What is a RESTful web service?
- What is a web service and how is that different from REST?
- What is an HTTP verb?
- What is the difference between a request body and a request itself?
- Why do we need HTTP headers?
- What is wrong if you get a status code:
- 405
- 415
- 404
- 500
- 401
- 403
- Why is Postman a useful tool?
- How to turn a class into a controller?
- How is PUT different from PATCH?
- How is POST different from PUT?
- What is a class and what is an object?
- What is a JSON?
- What is serialization/deserialization?
Fundamentals of practical programming
Problem 1: International Recipe ConverterLesson 1: C# Keywords and User Input
Lesson 2: Control Flow, Array and string
Lesson 3: Files, error handling and debugging
Lesson 4: Frontend using WinForms
RESTful Web API and More Fundamentals
Problem 2: Your Online Shopping ListLesson 5: RESTful, objects and JSON
Lesson 6: Code versioning
Lesson 7: OOP
Lesson 8: Understanding WebApi & Dependency Injection
Lesson 9: TDD
Lesson 10: LINQ and Collections
Lesson 11: Entity Framework
Lesson 12: Databases and SQL