This application is designed for the exploration and interaction with various API endpoints related to national parks. Whether a park enthusiast or just curious about natural wonders, this application offers the capability to access, search, retrieve, and update information from a comprehensive database of national parks across the United States.
- Github
- VSCode
- C#
- .NET
- CSHTML
- JSON
- MySQL Workbench
- Swagger
- Postman
- MySQL
- MySQL Workbench
- Entity Framework Core
- Postman
(Optional) Postman.
- Clone this repo.
- Open the terminal and navigate to this project's production directory called "NationalParks".
- Within the production directory "NationalParks", create two new files:
appsettings.json
andappsettings.Development.json
. - Within
appsettings.json
, add the following code:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Port=3306;database={YOUR_DATABASE};uid={USERNAME};pwd={PASSWORD};"
},
"JWT": {
"ValidAudience": "example-audience",
"ValidIssuer": "example-issuer",
"Secret": "{SECRET}"
}
}
Make sure to replace the
database
,uid
, andpwd
values in the MySQL database connection string with your choice of database name, your own username, and password for MySQL. For theSecret
key, make sure to replace{SECRET}
with a string of your choice, at least 16 characters long.
As per JWT
"Let's quickly breakdown what this object is. The ValidAudience key of our object is indicating who we are intending to distribute our JWT Tokens to, the ValidIssuer indicates who are the ones creating the tokens, and the Secret is a special string that will be used to encode our JWTs, to make them unique to our application. Depending on what type of algorithm being used, the Secret string will need to be a certain length. In this case, it needs to be at least 16 characters long." - Calvin Will
- Within
appsettings.Development.json
, add the following code:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Trace",
"Microsoft.AspNetCore": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
- Open your shell (e.g., Terminal or GitBash) to the production directory "NationalParks", and run
dotnet ef database update
.To optionally create a migration, run the command
dotnet ef migrations add MigrationName
whereMigrationName
is your custom name for the migration in UpperCamelCase. - To further build out this project in development mode, start the project with
dotnet watch run
in the production directory "NationalParks". - Use your program of choice to make API calls. The upcoming examples will be using Postman. In your API calls, use the domain http://localhost:5000. Keep reading to learn about all of the available endpoints.
Explore the API endpoints in Postman or a browser.
To explore National Parks with NSwag, launch the project using dotnet run
with the Terminal or Powershell, and input the following URL into your browser:
http://localhost:5000/swagger
In order to be authorized to use the POST
, PUT
, and DELETE
functionality of the API, you are required to authenticate yourself through Postman with a JSON Web Token (JWT). All GET
functionality will work for users and non-users, respectively.
In Postman, create a POST
request using the following URL:
http://localhost:5000/accounts/register
Add the following query to the request as raw JSON data in the Body tab:
{
"email": "[email protected]",
"userName": "testUser",
"password": "Test123!"
}
*If you would like to customize your password, please ensure that your password has: 1 uppercase letter, 1 lowercase letter, 1 number, 1 special character, and is at least 6 characters long.
{
"status": "success",
"message": "User has been successfully created"
}
With your newly created account, create another POST
request, this time using the following URL:
http://localhost:5000/accounts/signin
Add the following query to the request as raw JSON data in the Body tab:
{
"email": "[email protected]",
"password": "Test123!"
}
{
"status": "success",
"message": "[email protected] signed in",
"token": "{yourGeneratedToken}"
}
-
Copy
{yourGeneratedToken}
from the response Body -
Click on the 'Authorization' tab
-
Adjacent to 'Type' will be a drowndown menu, click on the menu and select 'Bearer Token'
-
Within the Body, paste
{yourGeneratedToken}
in the empty form field adjacent to 'Token'You now have full access to National Parks.
GET
http://localhost:5000/api/parks/
GET
http://localhost:5000/api/parks/{id}
GET
http://localhost:5000/api/parks/random
GET
http://localhost:5000/api/parks/search
POST
http://localhost:5000/api/parks/
PUT
http://localhost:5000/api/parks/{id}
DELETE
http://localhost:5000/api/parks/{id}
Note: {id}
should be replaced with the id value of the park you want to GET
, PUT
, POST
or DELETE
.
Parameter | Type | Description |
---|---|---|
name | String | Returns park(s) with a matching name value |
state | String | Returns park(s) with matching state value |
description | String | Returns park(s) with matching description |
annualVisitors | Int | Returns park(s) with matching amount of annual visitors |
parkType | String | Returns park(s) with matching park type; National Park or State Park |
http://localhost:5000/api/parks?name=Joshua+Tree+National+Park
Note: You should replace spaces between objects with a +
in the query parameter, for instance, Joshua Tree National Park should be represented as Joshua+Tree+National+Park
.
[
{
"parkId": 3,
"name": "Joshua Tree National Park",
"state": "California",
"description": "Joshua Tree is famous for its unique desert landscapes and iconic Joshua trees.",
"annualVisitors": 3000000,
"parkType": "National Park"
}
]
http://localhost:5000/api/parks
Customize or use the following query as an example to the request as raw JSON data in the Body tab:
{
"name": "ParkName",
"state": "ParkState",
"description": "ParkDescription",
"annualVisitors": 0,
"parkType": "ParkType"
}
Note: You do not need to add the key for parkId
, a POST
request implicitly generates a new parkId
value.
{
"parkId": 13,
"name": "ParkName",
"state": "ParkState",
"description": "ParkDescription",
"annualVisitors": 0,
"parkType": "National Park"
}
http://localhost:5000/api/parks/1
Customize or use the following query as an example to the request as raw JSON data in the Body tab:
{
"parkId": 1,
"name": "ParkName",
"state": "ParkState",
"description": "ParkDescription",
"annualVisitors": 0,
"parkType": "ParkType"
}
{
"parkId": 1,
"name": "Yosemite National Park",
"state": "California",
"description": "Yosemite is known for its waterfalls, deep valleys, grand meadows, and ancient giant sequoias.",
"annualVisitors": 4000000,
"parkType": "National Park"
}
After sending a valid PUT
request, you should see a successful status code in the response Body:
Status: 204 No Content
Now to further test the PUT
query's success, send a GET
request to the following URL:
http://localhost:5000/api/parks/1
{
"parkId": 1,
"name": "ParkName",
"state": "ParkState",
"description": "ParkDescription",
"annualVisitors": 0,
"parkType": "ParkType"
}
http://localhost:5000/api/parks/1
Note: You do not need to add anything in the Body to send a DELETE
request, simply specify the route with a valid {id}
, in our case, 1
, and if successful, just like from our PUT
request example, should appear a Status: 204 No Content
in the response Body.
Now to further test the DELETE
query's success, send a GET
request to the following URL:
http://localhost:5000/api/parks/1
Status: 404 Not Found
Indicative that the object was successfully deleted.
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.4",
"title": "Not Found",
"status": 404,
"traceId": "00-dc5177f4587a2c3017e8d7673889c47d-8a1f1bed21d52b95-00"
}
http://localhost:5000/api/parks/search?annualVisitors=800000
Note: To customize your query, add a query parameter to the URL. In this case, we're using annualVisitors
to filter parks based on their annual visitors count. You can replace 800000
with another desired value or alternatively, by using different query parameters and values, you can tailor your queries to search for parks that meet specific criteria. For instance, you could change annualVisitors
to state
with a value of California
, name
with a value of Redwood
, or parkType
with a value of National+Park
to search for parks by state
, name
, or type
, respectively.
[
{
"parkId": 4,
"name": "Redwood National and State Parks",
"state": "California",
"description": "Home to the tallest trees on Earth, the coastal redwoods.",
"annualVisitors": 800000,
"parkType": "National Park"
}
]
http://localhost:5000/api/parks/search?state=oregon
[
{
"parkId": 6,
"name": "Silver State Falls",
"state": "Oregon",
"description": "Silver State Falls is a beautiful park featuring stunning waterfalls, lush forests, and hiking trails.",
"annualVisitors": 500000,
"parkType": "State Park"
}
]
http://localhost:5000/api/parks/random
This endpoint will simply generate a single randomized park result each time a request is sent.
National Parks returns a default of 6 results per page at a time for a GET
request with the following URL:
http://localhost:5000/api/parks/
To modify this, use the query parameters page
and pageSize
and replace {customize}
with integer values where pageSize
is the amount of objects to be viewed.
http://localhost:5000/api/parks?page={customize}&pageSize={customize}
This project is licensed under the MIT License. Copyright (C) 2023 Jeremy Josol. All Rights Reserved.
MIT License
Copyright (c) 2023 Jeremy Josol.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.