<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Matheus Paixão</title>
    <description>The latest articles on Forem by Matheus Paixão (@mgpaixao).</description>
    <link>https://forem.com/mgpaixao</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F729596%2Feea9bd33-293a-4662-ac8a-6f1e6637fe14.jpeg</url>
      <title>Forem: Matheus Paixão</title>
      <link>https://forem.com/mgpaixao</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mgpaixao"/>
    <language>en</language>
    <item>
      <title>Deploy .NET API to Kubernetes using Kind</title>
      <dc:creator>Matheus Paixão</dc:creator>
      <pubDate>Wed, 06 Jul 2022 18:50:59 +0000</pubDate>
      <link>https://forem.com/mgpaixao/deploy-net-api-to-kubernetes-using-kind-44e2</link>
      <guid>https://forem.com/mgpaixao/deploy-net-api-to-kubernetes-using-kind-44e2</guid>
      <description>&lt;p&gt;Hi Devs and Divas.&lt;/p&gt;

&lt;p&gt;Today I am going to show you a simple way to install run and test your API locally with docker caontainer and orchestrating with Kubernetes.&lt;/p&gt;

&lt;p&gt;If you ever heard that Kubernetes is super difficult, don't worry, it's not that bad.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/jTMxfXzAohYnkiTZlg/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/jTMxfXzAohYnkiTZlg/giphy.gif" alt="devops"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article you will learn how to deploys a simple API to kubernetes with a local environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Preparing the API&lt;/li&gt;
&lt;li&gt;Publishing API in Docker Hub&lt;/li&gt;
&lt;li&gt;Installing Kind for Kubernetes&lt;/li&gt;
&lt;li&gt;Preparing the API for Kubernetes&lt;/li&gt;
&lt;li&gt;Pushing and Managing API to Kubernetes&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Pre-requirements
&lt;/h1&gt;

&lt;p&gt;You should have the basic concept knowledge of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes&lt;/li&gt;
&lt;li&gt;Docker/Containers&lt;/li&gt;
&lt;li&gt;Kind for Kubernetes&lt;/li&gt;
&lt;li&gt;.net API&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Preparing the API
&lt;/h1&gt;

&lt;p&gt;We will create a basic Weatherforecast API that dotnet gives us.&lt;br&gt;
 &lt;/p&gt;
&lt;h1&gt;
  
  
  Vs Code
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Open VS CODE, open a new terminal, navigate to the folder you wish to create your project for example (cd source/repos).&lt;/li&gt;
&lt;li&gt;Now type &lt;code&gt;dotnet new webapi -o "weather"&lt;/code&gt; to create a sample webapi project.&lt;/li&gt;
&lt;li&gt;Now open this project folder in the vscode.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To auto-create the Docker support that is available upon project creation in Visual Studio follow the next steps:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install the &lt;code&gt;Docker&lt;/code&gt; extension.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Press &lt;code&gt;Ctrl + Shift + P&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Type &lt;code&gt;Add Docker Files to Workspace&lt;/code&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select &lt;code&gt;.NET: ASP.NET Core&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select &lt;code&gt;Linux&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Type the port you wish to expose&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select &lt;code&gt;No&lt;/code&gt; for docker compose. At this first moment we won't need it.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then you notice it generated a new &lt;code&gt;Dockerfile&lt;/code&gt; in your workspace.&lt;/p&gt;
&lt;h1&gt;
  
  
  Visual Studio
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Open visual studio and create a &lt;code&gt;ASPNET Core Web API&lt;/code&gt; and make sure you enable &lt;code&gt;Docker Support&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;br&gt;
 &lt;/p&gt;
&lt;h3&gt;
  
  
  Swagger Support
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;After the project is created you go to Program.cs (.net 6 above) or to Startup.cs (.net 6 below) and remove the &lt;code&gt;IF condition&lt;/code&gt; from the swagger setup
 
From this:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    app.UseSwagger();
    app.UseSwaggerUI();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt; &lt;/p&gt;

&lt;p&gt;We do this for testing purpose only, because when you push it to kubernetes you need to set which environment you wish to build your application. You can add &lt;code&gt;ASPNETCORE_ENVIRONMENT=Development&lt;/code&gt; in your docker profile, it will work as well. &lt;br&gt;
 &lt;/p&gt;
&lt;h1&gt;
  
  
  Publishing API in Docker Hub
&lt;/h1&gt;

&lt;p&gt;You must have &lt;code&gt;Docker&lt;/code&gt; installed and have a &lt;code&gt;Docker hub Account&lt;/code&gt; to complete this step.&lt;/p&gt;

&lt;p&gt;In your IDE, open terminal and build the API:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t weather . 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As a prevention measure, test your container before orchestrating with kubernetes. So lets run the image. (You can use whatever port you wish)&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker container run -d -p 8070:80 --name containername weather
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now you should be able to see &lt;code&gt;swagger&lt;/code&gt; page if you type localhost:8070/swagger&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pushing to Docker Hub&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before pushing you can add tags to your image.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker tag weather dockerHubUserName/weather
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now you can push it&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker push dockerHubUserName/weather
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you open your docker hub on your browser you should be able to see your image.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;
&lt;h1&gt;
  
  
  Installing Kind
&lt;/h1&gt;

&lt;p&gt;To install &lt;code&gt;kind&lt;/code&gt; refer to original documentation &lt;a href="https://kind.sigs.k8s.io/docs/user/quick-start/" rel="noopener noreferrer"&gt;https://kind.sigs.k8s.io/docs/user/quick-start/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But let me show you what I did.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download the file from &lt;a href="https://kind.sigs.k8s.io/dl/v0.14.0/kind-windows-amd64" rel="noopener noreferrer"&gt;https://kind.sigs.k8s.io/dl/v0.14.0/kind-windows-amd64&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Rename the file to &lt;code&gt;kind.exe&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Move it to a folder named &lt;code&gt;k8s&lt;/code&gt;. So should look like this &lt;code&gt;C:\k8s\kind.exe&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;On windows, go to environment variables and add new PATH &lt;code&gt;C:\k8s&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmesybnzepkzr1qplse8n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmesybnzepkzr1qplse8n.png" alt="Image3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now if you have &lt;code&gt;docker&lt;/code&gt; running, you should be able to create a cluster.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kind create cluster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Wait till it creates the cluster.&lt;/p&gt;

&lt;p&gt;You should see a new container running on your docker. To check if the container is running type &lt;code&gt;docker ps&lt;/code&gt; in your terminal and you should see a container named &lt;code&gt;kind-control-plane&lt;/code&gt; from the image &lt;code&gt;kindest&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To check if there are any clusters type on your terminal:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kind get clusters
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And you should get a response like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kind
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Preparing the API for Kubernetes
&lt;/h1&gt;

&lt;p&gt;To access your application you need at least 2 kubernetes objects:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;deploy.yml&lt;/code&gt; - A Deployment provides declarative updates for Pods and ReplicaSets.&lt;br&gt;
&lt;code&gt;service.yml&lt;/code&gt; - An abstract way to expose an application running on a set of Pods as a network service. To access your pod you need a service to expose it.&lt;/p&gt;

&lt;p&gt;You don't need to know how to write it by hear, you can get a template and edit.&lt;/p&gt;

&lt;p&gt;I recommend you use &lt;code&gt;VsCode&lt;/code&gt; with &lt;code&gt;YAML extension&lt;/code&gt; to edit your yml files, because it indentation is very delicate, and Visual Studio has no support for this extension.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;This is a simplified version, for testing purpose, there are many options and features to be added according to your project&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Create a file in your project &lt;code&gt;weather-deploy.yml&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Template:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: Application Name
spec:
  replicas: How many Replicas?
  template:
    metadata:
      labels:
        app: Application Name
    spec:
      containers:
      - name: Application Name
        image: dockerHubUser/applicationName
  selector:
    matchLabels:
      app: Application Name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Our project:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: weather
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: weather
    spec:
      containers:
      - name: weather
        image: dockerHubUser/weather
  selector:
    matchLabels:
      app: weather
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Don't forget to add you docker hub User&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a file in your project &lt;code&gt;weather-service.yml&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Template:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: v1
kind: Service
metadata:
  name: Project Name
spec:
  selector:
    app: Project Name
  ports:
  - port: port?
    targetPort: 80 is the standart port
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Our project:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: v1
kind: Service
metadata:
  name: weather
spec:
  selector:
    app: weather
  ports:
  - port: 8070
    targetPort: 80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt; &lt;/p&gt;
&lt;h1&gt;
  
  
  Pushing API to Kubernetes
&lt;/h1&gt;

&lt;p&gt;To orchestrate the API to kubernetes pod we will only push this 2 files as the project will come from the docker image.&lt;/p&gt;

&lt;p&gt;Terminal:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f weather-deploy.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f weather-service.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Terminal response should be:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;deployment.apps/weather created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;service/weather created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Wait a minute and check if your pod and service are running:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Terminal:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get pods
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Terminal Response:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjpri18n0xdt4p7qj66iq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjpri18n0xdt4p7qj66iq.png" alt="Imag2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Terminal:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get svc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Terminal response:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   xxxxx       &amp;lt;none&amp;gt;        443/TCP    23h
weather      ClusterIP   xxxxx   &amp;lt;none&amp;gt;        8070/TCP   3m53s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;
  
  
  Accessing your Pod
&lt;/h3&gt;

&lt;p&gt;To access your pod you need to forward a port to the service.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl port-forward service/weather 8070:8070
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now you should be able to see the &lt;code&gt;Swagger&lt;/code&gt; page in your browser typing localhost:8070/swagger&lt;/p&gt;

&lt;p&gt;Basically you are telling the kubernetes that when you access port 8070 locally, you will access 8070 on kubernetes service, which is our pod's service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/AeWoyE3ZT90YM/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/AeWoyE3ZT90YM/giphy.gif" alt="tHANKS"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__729596"&gt;
    &lt;a href="/mgpaixao" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F729596%2Feea9bd33-293a-4662-ac8a-6f1e6637fe14.jpeg" alt="mgpaixao image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/mgpaixao"&gt;Matheus Paixão&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/mgpaixao"&gt;Gosto de compartilhar conhecimento pois foi assim que eu aprendi a programar. O meu negócio é todo dia saber mais que eu sabia ontem. Pode me chamar, vamos aprender juntos. Prazer =)&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>kubernetes</category>
      <category>dotnet</category>
      <category>devops</category>
      <category>docker</category>
    </item>
    <item>
      <title>Flutter - How to format DateTime and how to display it</title>
      <dc:creator>Matheus Paixão</dc:creator>
      <pubDate>Fri, 29 Apr 2022 01:49:10 +0000</pubDate>
      <link>https://forem.com/mgpaixao/flutter-how-to-format-datetime-and-how-you-display-it-2ljn</link>
      <guid>https://forem.com/mgpaixao/flutter-how-to-format-datetime-and-how-you-display-it-2ljn</guid>
      <description>&lt;p&gt;Hello,&lt;br&gt;
Today I will show you how to format datetime in the way you wish to display wi the &lt;code&gt;intl flutter package&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To check the latest version o the package check this link &lt;a href="https://pub.dev/packages/intl/versions" rel="noopener noreferrer"&gt;HERE&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Installation and Importing
&lt;/h1&gt;

&lt;p&gt;At &lt;code&gt;pubspec.yaml&lt;/code&gt; add &lt;code&gt;intl: ^0.17.0&lt;/code&gt; and make sure you check for the latest version, the ^ sign before the version is for the system to auto-update within that main release. So when they release version 0.17.1 it auto-update it self.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dependencies:
  flutter:
    sdk: flutter
  intl: ^0.17.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;At the file you wish to use, import it like this.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:intl/intl.dart';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  How to use
&lt;/h1&gt;

&lt;p&gt;Variable  - datetime&lt;/p&gt;

&lt;p&gt;You can edit and format as you wish, with dots, comma, arrows, etc.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DateFormat('d MMM y').format(datetime)&lt;/code&gt; = 28 Apr 2022&lt;br&gt;
&lt;code&gt;DateFormat('d MM y').format(datetime)&lt;/code&gt; = 28 04 2022&lt;br&gt;
&lt;code&gt;DateFormat('d-MM-y').format(datetime)&lt;/code&gt; = 28-04-2022&lt;/p&gt;

&lt;p&gt;There are also a list o functions that we can use that gives us default formats.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DateFormat.yQQQQ().format(datetime)&lt;/code&gt; = 2nd quarter 2022&lt;/p&gt;

&lt;p&gt;Have a look at all formats available at the official documentation &lt;a href="https://pub.dev/documentation/intl/latest/intl/DateFormat-class.html" rel="noopener noreferrer"&gt;HERE&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__729596"&gt;
    &lt;a href="/mgpaixao" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F729596%2Feea9bd33-293a-4662-ac8a-6f1e6637fe14.jpeg" alt="mgpaixao image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/mgpaixao"&gt;Matheus Paixão&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/mgpaixao"&gt;Gosto de compartilhar conhecimento pois foi assim que eu aprendi a programar. O meu negócio é todo dia saber mais que eu sabia ontem. Pode me chamar, vamos aprender juntos. Prazer =)&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>flutter</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Flutter - Difference between Container vs Column and Row</title>
      <dc:creator>Matheus Paixão</dc:creator>
      <pubDate>Fri, 29 Apr 2022 00:36:05 +0000</pubDate>
      <link>https://forem.com/mgpaixao/flutter-difference-between-container-vs-column-and-row-1hng</link>
      <guid>https://forem.com/mgpaixao/flutter-difference-between-container-vs-column-and-row-1hng</guid>
      <description>&lt;p&gt;Today I will simply show the difference between Container vs Column and Row. Both sets are commonly used in interface development and it's wise to know the basic difference between them both.&lt;/p&gt;

&lt;h1&gt;
  
  
  Container - &lt;a href="https://api.flutter.dev/flutter/widgets/Container-class.html" rel="noopener noreferrer"&gt;Flutter doc reference&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2fpzour5wajn0vuryj64.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2fpzour5wajn0vuryj64.png" alt="Imagedescription"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;The container widget is the most used component in flutter apps because it provides you with various common painting, positioning, and sizing widgets, whenever you have widgets that are focus on it’s core functionality and don’t give you the option of positioning and styling, you involve it in a Container.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accepts only one Widgets as child&lt;/li&gt;
&lt;li&gt;Alignment is more flexible and the style options are more broad&lt;/li&gt;
&lt;li&gt;Flexible Width, it can use the child width or whatever you set as width&lt;/li&gt;
&lt;li&gt;Used when alignment and style is to be personalized&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  &lt;a href="https://api.flutter.dev/flutter/widgets/Column-class.html" rel="noopener noreferrer"&gt;Column&lt;/a&gt;/&lt;a href="https://api.flutter.dev/flutter/widgets/Row-class.html" rel="noopener noreferrer"&gt;Row&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fce8ydba9q015a8ga6trn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fce8ydba9q015a8ga6trn.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The row is the widget that can display various child widgets in a horizontal manner. &lt;br&gt;
The column displays child widgets in a vertical manner. &lt;br&gt;
By default, they do not support scrolling. It can be enabled by wrapping with other widgets. But, it is preferred to use ListView in case there are numerous child widgets to be displayed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accepts a list of Widgets as children&lt;/li&gt;
&lt;li&gt;Limited alignment and no style options available.&lt;/li&gt;
&lt;li&gt;Always fills the height (Column) and the Row always fills the width&lt;/li&gt;
&lt;li&gt;Used when the Widgets are close to each other, follow a pattern or on top of each other&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A great use of a Container and a Column/Row together, is when you want to personalize your Column and Row but you can’t. Then you involve your Widget in a Container so you can give better alignment and style it as you wish.&lt;/p&gt;

&lt;p&gt;Thank you and let me know what you think bellow in the comments&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__729596"&gt;
    &lt;a href="/mgpaixao" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F729596%2Feea9bd33-293a-4662-ac8a-6f1e6637fe14.jpeg" alt="mgpaixao image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/mgpaixao"&gt;Matheus Paixão&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/mgpaixao"&gt;Gosto de compartilhar conhecimento pois foi assim que eu aprendi a programar. O meu negócio é todo dia saber mais que eu sabia ontem. Pode me chamar, vamos aprender juntos. Prazer =)&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>flutter</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>C# - Criando API com Jwt Token - Autorização e Autenticação - Módulo 3 - Arquitetura 3 camadas - Repository Pattern</title>
      <dc:creator>Matheus Paixão</dc:creator>
      <pubDate>Thu, 07 Apr 2022 20:30:10 +0000</pubDate>
      <link>https://forem.com/mgpaixao/c-criando-api-com-jwt-token-autorizacao-e-autenticacao-modulo-3-arquitetura-3-camadas-repository-pattern-9mf</link>
      <guid>https://forem.com/mgpaixao/c-criando-api-com-jwt-token-autorizacao-e-autenticacao-modulo-3-arquitetura-3-camadas-repository-pattern-9mf</guid>
      <description>&lt;p&gt;Sejam Bem Vindos a mais um módulo da nossa série.&lt;br&gt;
 &lt;br&gt;
Código Modulo 3 - &lt;a href="https://github.com/mgpaixao/JWTAuthAuthenticationProject/tree/master/Modulo%203"&gt;Repositório GitHub&lt;/a&gt;&lt;br&gt;
 &lt;/p&gt;

&lt;p&gt;Primeiramente. Olá&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/3oz8xSjBmD1ZyELqW4/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3oz8xSjBmD1ZyELqW4/giphy.gif" alt="Gifss" width="600" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Melhorias desse modulo
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;CRUD de Usuários&lt;/li&gt;
&lt;li&gt;Introdução do Repository Pattern&lt;/li&gt;
&lt;li&gt;Divisão em 3 Projetos (Infra - Domain - API)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nesse módulo, irei abordar a evolução do módulo anterior, será muito fácil se perder na nova arquitetura que implementei, pois são vários caminhos percorridos para conseguir executar um end point. &lt;/p&gt;
&lt;h1&gt;
  
  
  Divisão em 3 Camadas
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iWL9tWbc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pjws8zrgrcap5x86dgh3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iWL9tWbc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pjws8zrgrcap5x86dgh3.png" alt="Image description" width="506" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API 

&lt;ul&gt;
&lt;li&gt;Na camada de API colocamos os itens principais do projeto, Controllers, as models de entrada e saída (RequestDTO e ResponseDTO) e as configurações pertinentes a &lt;code&gt;program.cs(.net 6)&lt;/code&gt; ou &lt;code&gt;startup.cs (.net 5 ou anterior)&lt;/code&gt;.
 &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;INFRA

&lt;ul&gt;
&lt;li&gt;Na camada de infraestrutura colocamos toda a infra de banco de dados e repositórios. (Context, Mapeamentos, Repositories)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;DOMAIN

&lt;ul&gt;
&lt;li&gt;Na camada de Domain colocamos tudo que é compartilhado entre os outros projetos, as Models, os Services, Utilitários, Interfaces e helpers compartilhados entre os outros projetos. Domain é onde fica toda a regra de negócio da aplicação onde será compartilhado com as outras camadas.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Arquitetura 3 camadas
&lt;/h1&gt;

&lt;p&gt; &lt;br&gt;
A arquitetura em 3 camadas serve para dividir as responsabilidades entre 3 projetos, podendo cada um focar em sua parte. Por exemplo, separando a camada de domínio e colocando toda a regra de negócio apenas ali, facilita assim, a manutenção do código, pois você já sabe que cada tecnologia, cada parte de código, está em seu devido lugar. &lt;/p&gt;
&lt;h1&gt;
  
  
  Como dividir o projeto em 3 camadas?
&lt;/h1&gt;
&lt;h4&gt;
  
  
  Criando Biblioteca de classes
&lt;/h4&gt;

&lt;p&gt;Entenda que dividir o projeto em camadas nada mais é do que você criar sua própria biblioteca para consumo interno. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3N6mSqjG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oaww8wq7806fkazzid7r.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3N6mSqjG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oaww8wq7806fkazzid7r.gif" alt="Criando Projeto" width="880" height="575"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para fazer a comunicação entre as camadas, é necessário referencia-las como no gif abaixo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Mrkdsmja--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ko90v60ntkri2dkdb7l.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Mrkdsmja--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ko90v60ntkri2dkdb7l.gif" alt="referencias" width="874" height="627"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repare que o projeto &lt;code&gt;domain&lt;/code&gt;, não contem referências, pois na verdade ele não depende de ninguém, são os outros projetos que dependem dele, pois é ali que se concentra toda a regra de negócio que precisa ser consumida pela infraestrutura e pelas controllers no projeto principal. &lt;/p&gt;
&lt;h1&gt;
  
  
  Repository Pattern
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kpQNAGqG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2bex6i1ys4hltrasuz2m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kpQNAGqG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2bex6i1ys4hltrasuz2m.png" alt="Repo Pattern" width="880" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;repository pattern&lt;/code&gt; é um dos padrões de projetos mais utilizamos mundialmente, ele é amplamente conhecido e aceito em projetos de todos os níveis. &lt;/p&gt;

&lt;p&gt;Esse padrão de projeto visa a abstração de responsabilidade e encapsulamento do banco de dados, possibilitando a injeção de dependência. &lt;/p&gt;

&lt;p&gt;Mas o que isso significa? Basicamente, você pode ter o banco de dados que for, e isso não irá afetar o resto do sistema. Pois agora cada um tem sua responsabilidade, se o repositório é responsável pelo acesso ao banco de dados, então quando tivermos alguma alteração de banco de dados, já sabemos que a alteração é mais provável que seja apenas ali.&lt;/p&gt;
&lt;h1&gt;
  
  
  Implementação
&lt;/h1&gt;

&lt;p&gt;Primeiro de tudo eu crio o Repositório base, tem muitos exemplos prontos disponíveis pela internet com os métodos já prontos.&lt;/p&gt;

&lt;p&gt;Entenda que pra todo repositório, ou serviço criado, você precisa também criar a Interface, que é o método de acesso a essa classe.&lt;/p&gt;
&lt;h1&gt;
  
  
  Base Repository
&lt;/h1&gt;

&lt;p&gt;É aqui o único lugar onde terá uma estância do &lt;code&gt;DataContext&lt;/code&gt; que é nosso acesso ao Banco de dados.&lt;/p&gt;

&lt;p&gt;Os repositórios sempre implementam os métodos definidos na interface dele, e representam de forma genérica uma entidade/model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class BaseRepository&amp;lt;T&amp;gt; : IBaseRepository&amp;lt;T&amp;gt; where T : Entity
    {
        private readonly DbSet&amp;lt;T&amp;gt; DbSet;
        private readonly DataContext _context;

        protected BaseRepository(DataContext context)
        {
            _context = context;
            DbSet = _context.Set&amp;lt;T&amp;gt;();
        }

        public async Task&amp;lt;T?&amp;gt; GetById(Guid id) =&amp;gt;
        await DbSet.FindAsync(id);

        public async Task&amp;lt;IEnumerable&amp;lt;T&amp;gt;&amp;gt; GetAllAsync() =&amp;gt;
            await DbSet.ToListAsync();

        public async Task&amp;lt;T?&amp;gt; GetOneBy(Expression&amp;lt;Func&amp;lt;T, bool&amp;gt;&amp;gt; expression) =&amp;gt;
            await DbSet.AsNoTracking().FirstOrDefaultAsync(expression);

        public async Task&amp;lt;IEnumerable&amp;lt;T&amp;gt;&amp;gt; GetListBy(Expression&amp;lt;Func&amp;lt;T, bool&amp;gt;&amp;gt; expression) =&amp;gt;
            await DbSet.Where(expression).ToListAsync();

        public async Task&amp;lt;bool&amp;gt; Exists(Expression&amp;lt;Func&amp;lt;T, bool&amp;gt;&amp;gt; expression) =&amp;gt;
            await DbSet.AnyAsync(expression);

        public async Task AddAsync(T entity)
        {
            await DbSet.AddAsync(entity);
            await SaveChanges();
        }

        public void Update(T entity) =&amp;gt;
            DbSet.Update(entity);

        public void Remove(T entity) =&amp;gt;
            DbSet.Remove(entity);

        public async Task&amp;lt;int&amp;gt; SaveChanges()
        {
            return await _context.SaveChangesAsync();
        }

        public void Dispose()
        {
            _context?.Dispose();
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  IBaseRepository Interface
&lt;/h1&gt;

&lt;p&gt;Notem que a interface tem todos os métodos que implementamos no repositório base.&lt;/p&gt;

&lt;p&gt;A interface é o método de acesso aos repositórios e serviços.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public interface IBaseRepository&amp;lt;T&amp;gt; : IDisposable where T : Entity
    {
        Task&amp;lt;T&amp;gt; GetById(Guid id);
        Task&amp;lt;IEnumerable&amp;lt;T&amp;gt;&amp;gt; GetAllAsync();
        Task&amp;lt;T&amp;gt; GetOneBy(Expression&amp;lt;Func&amp;lt;T, bool&amp;gt;&amp;gt; expression);
        Task&amp;lt;IEnumerable&amp;lt;T&amp;gt;&amp;gt; GetListBy(Expression&amp;lt;Func&amp;lt;T, bool&amp;gt;&amp;gt; expression);
        Task&amp;lt;bool&amp;gt; Exists(Expression&amp;lt;Func&amp;lt;T, bool&amp;gt;&amp;gt; expression);
        Task&amp;lt;int&amp;gt; SaveChanges();
        Task AddAsync(T entity);
        public void Update(T entity);
        public void Remove(T entity);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Service Login
&lt;/h1&gt;

&lt;p&gt;Vou exemplificar como funciona o fluxo com o serviço de Login.&lt;/p&gt;

&lt;p&gt;Repare que estanciamos o repositório de Login, que lá dentro acessa o repositório base que tem acesso ao banco de dados. Antes de chegar aqui, esse serviço é estanciado na controller através de sua interface.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class LoginService :  ILoginService
    {
        private readonly ILoginRepository _loginRepository;
        private readonly TokenService _tokenService;

        public LoginService(ILoginRepository loginRepository, TokenService tokenService)
        {
            _tokenService = tokenService;
            _loginRepository = loginRepository;
        }

        public async Task&amp;lt;string&amp;gt; LoginAsync(string email, string password)
        {
            var user = await _loginRepository.GetUser(email);

            if (user == null)
                return "User or password invalid";

            if (!PasswordHasher.Verify(user.PasswordHash, password))
                return "User or password invalid";

            try
            {
                var token = _tokenService.GenerateToken(user);
                return token;
            }
            catch
            {
                return "Internal Error";
            }
        }

        public void Dispose()
        {
            _loginRepository?.Dispose();
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Controller
&lt;/h1&gt;

&lt;p&gt;Terminando aqui o fluxo reverso de como acessar o banco de dados com o repository pattern, podemos ver que na controller estanciamos a interface do serviço de interesse.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class AuthController : ControllerBase
    {
        private readonly ILoginService _loginService;
        public AuthController(ILoginService loginService)
        {
            _loginService = loginService;
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Colocarei aqui novamente a imagem do fluxo de dados no repository pattern. Da controller você acessa os serviço de interesse, onde tem toda a regra de negócio da entidade em questão, depois acessa o repositório da entidade através da interface, e por fim, acessa o repositório base pra acesso aos dados.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cUJ_qObS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9eas9dfisu9gxd0usgd4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cUJ_qObS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9eas9dfisu9gxd0usgd4.png" alt="Images" width="880" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pra tudo isso funcionar, temos que declarar as injeções de dependências, pois é dessa forma que estamos estanciando uma classe na outra.&lt;/p&gt;

&lt;p&gt;Sempre declarar na ordem da esquerda pra direita no fluxo de dados, então primeiro a interface depois sua classe de implementação.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static IServiceCollection ResolveDependencies(this IServiceCollection services)
        {
            services.AddDbContext&amp;lt;DataContext&amp;gt;();
            services.AddScoped&amp;lt;TokenService&amp;gt;();

            services.AddScoped&amp;lt;ILoginService, LoginService&amp;gt;();
            services.AddScoped&amp;lt;ILoginRepository, LoginRepository&amp;gt;();

            services.AddScoped&amp;lt;IRoleRepository, RoleRepository&amp;gt;();
            services.AddScoped&amp;lt;IRoleService, RoleService&amp;gt;();

            services.AddScoped&amp;lt;IUserService, UserService&amp;gt;();
            services.AddScoped&amp;lt;IUserRepository, UserRepository&amp;gt;();

            return services;
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Porque implementar tudo isso?
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/0Vv0Ne2CnOClIExIuL/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/0Vv0Ne2CnOClIExIuL/giphy.gif" alt="garoa" width="292" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Temos diversos padrões e designs de arquiteturas a adotar, no fim das contas implemente aquele que mais se encaixa com sua demanda. &lt;br&gt;
Se você vai fazer uma API simples, com 2 models, 1 controller e um crud simples, talvez não faça sentido você aplicar essa complexidade. Mas é uma decisão e se tomar com o seu time de desenvolvimento.&lt;/p&gt;

&lt;p&gt;Lembrando os benefícios que você aplicar conceitos como S.O.L.I.D e Repository pattern por exemplo.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O sistema ser agnóstico de banco de dados, você pode trocar o banco de dados com facilidade sem afetar o resto do código.&lt;/li&gt;
&lt;li&gt;Código centralizado em um único ponto, evitando duplicidade.&lt;/li&gt;
&lt;li&gt;Facilita a implementação de testes. Em caso de testes mais avançados, talvez você não consiga fazer sem adotar uma arquitetura mais organizada.&lt;/li&gt;
&lt;li&gt;Diminui o acoplamento entre classes.&lt;/li&gt;
&lt;li&gt;Padronização de códigos e serviços.&lt;/li&gt;
&lt;li&gt;Facilita a reutilização de código.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fique ligado no próximo artigo da série, onde vamos adicionar o padrão de UOW - Unity of Work para acesso ao banco de dados.&lt;/p&gt;

&lt;p&gt;Confira os módulos anteriores&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/mgpaixao/criando-api-com-jwt-autorizacao-e-autenticacao-modulo-1-20b8"&gt;Modulo 1&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/mgpaixao/c-criando-api-login-com-jwt-token-autorizacao-e-autenticacao-modulo-2-5cf"&gt;Modulo 2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/AeWoyE3ZT90YM/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/AeWoyE3ZT90YM/giphy.gif" alt="tHANKS" width="480" height="202"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__729596"&gt;
  
    .ltag__user__id__729596 .follow-action-button {
      background-color: #000000 !important;
      color: #ffffff !important;
      border-color: #000000 !important;
    }
  
    &lt;a href="/mgpaixao" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LmLu25D3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--OQVKr0N8--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/729596/eea9bd33-293a-4662-ac8a-6f1e6637fe14.jpeg" alt="mgpaixao image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/mgpaixao"&gt;Matheus Paixão&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/mgpaixao"&gt;Gosto de compartilhar conhecimento pois foi assim que eu aprendi a programar. O meu negócio é todo dia saber mais que eu sabia ontem. Pode me chamar, vamos aprender juntos. Prazer =)&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
    </item>
    <item>
      <title>C# - Criando API Login com Jwt Token - Autorização e Autenticação - Módulo 2</title>
      <dc:creator>Matheus Paixão</dc:creator>
      <pubDate>Wed, 02 Mar 2022 17:04:54 +0000</pubDate>
      <link>https://forem.com/mgpaixao/c-criando-api-login-com-jwt-token-autorizacao-e-autenticacao-modulo-2-5cf</link>
      <guid>https://forem.com/mgpaixao/c-criando-api-login-com-jwt-token-autorizacao-e-autenticacao-modulo-2-5cf</guid>
      <description>&lt;p&gt;Sejam bem vindos novamente marujos, bora continuar remando rumo à mais um módulo desse projeto incrível.&lt;/p&gt;

&lt;p&gt; &lt;br&gt;
 Código Módulo 2 -&amp;gt; &lt;a href="https://github.com/mgpaixao/JWTAuthAuthenticationProject/tree/master/Modulo%202" rel="noopener noreferrer"&gt;Repositório GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/DPUEnpnceULzE7Wki5/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/DPUEnpnceULzE7Wki5/giphy.gif" alt="Remar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;br&gt;
Nesse módulo irei abordar a evolução do projeto da API de Login com autorização através do JWT Token. &lt;a href="https://dev.to/mgpaixao/criando-api-com-jwt-autorizacao-e-autenticacao-modulo-1-20b8"&gt;Modulo 1&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Migração de .net 5 para .net 6&lt;/li&gt;
&lt;li&gt;Crud de Roles&lt;/li&gt;
&lt;li&gt;O Sistema sempre tem 1 admin&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;
&lt;h1&gt;
  
  
  Migrando .Net 5 para .Net 6
&lt;/h1&gt;

&lt;p&gt; &lt;/p&gt;
&lt;h4&gt;
  
  
  1 - No arquivo .csproj altere o &lt;code&gt;TargertFramework&lt;/code&gt; para &lt;code&gt;net6.0&lt;/code&gt; e dentro do mesmo &lt;code&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/code&gt; adicione &lt;code&gt;&amp;lt;Nullable&amp;gt;enable&amp;lt;/Nullable&amp;gt;&lt;/code&gt; e &lt;code&gt;&amp;lt;ImplicitUsings&amp;gt;enable&amp;lt;/ImplicitUsings&amp;gt;&lt;/code&gt; e o resultado deve ficar assim:
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  &amp;lt;PropertyGroup&amp;gt;     
      &amp;lt;TargetFramework&amp;gt;net6.0&amp;lt;/TargetFramework&amp;gt;
      &amp;lt;Nullable&amp;gt;enable&amp;lt;/Nullable&amp;gt;
      &amp;lt;ImplicitUsings&amp;gt;enable&amp;lt;/ImplicitUsings&amp;gt;     
  &amp;lt;/PropertyGroup&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  2 - Atualize os pacotes Nugets
&lt;/h4&gt;
&lt;h4&gt;
  
  
  3 - Migrando dados da Startup.cs para Program.cs
&lt;/h4&gt;

&lt;p&gt;No .net 6 você não precisa mais dos métodos &lt;code&gt;ConfigureServices()&lt;/code&gt; e do &lt;code&gt;Configure()&lt;/code&gt;, você precisa apenas estanciar  o &lt;code&gt;WebApplication Builder&lt;/code&gt; na classe &lt;code&gt;program&lt;/code&gt; para poder ter acesso aos métodos de configuração.&lt;br&gt;
 &lt;br&gt;
Então no nosso programa o método &lt;code&gt;ConfigureServices()&lt;/code&gt; ficou assim:&lt;br&gt;
 &lt;br&gt;
&lt;strong&gt;IMPORTANTE: Mudei o JWTkey para o nosso secrets, para não deixar exposto a nossa chave de criptografia.&lt;/strong&gt;&lt;br&gt;
 &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var builder = WebApplication.CreateBuilder(args);

builder.Services.AddTransient&amp;lt;TokenService&amp;gt;();
builder.Services.AddDbContext&amp;lt;DataContext&amp;gt;();
builder.Services.AddControllers();


//JWTConfig 
var key = Encoding.ASCII.GetBytes(builder.Configuration["Key:JwtKey"].ToString());
builder.Services.AddAuthentication(x =&amp;gt;
{
    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =&amp;gt;
{
    x.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuerSigningKey = true,
        ValidateAudience = false,
        IssuerSigningKey = new SymmetricSecurityKey(key),
        ValidateIssuer = false
    };
});

//Configuração do Swagger para adicionar o Bearer Token na auth
builder.Services.AddSwaggerGen(c =&amp;gt;
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "JWTAuthAuthentication2", Version = "v1" });
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
    {
        Name = "Authorization",
        Type = SecuritySchemeType.ApiKey,
        Scheme = "Bearer",
        BearerFormat = "JWT",
        In = ParameterLocation.Header,
        Description = "JWT Authorization header using the Bearer scheme",
    });
    c.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                          new OpenApiSecurityScheme
                          {
                              Reference = new OpenApiReference
                              {
                                  Type = ReferenceType.SecurityScheme,
                                  Id = "Bearer"
                              }
                          },
                         new string[] {}
                    }
                });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;E o método &lt;code&gt;Configure()&lt;/code&gt; vai ficar assim:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
    app.UseSwagger();
    app.UseSwaggerUI(c =&amp;gt; c.SwaggerEndpoint("/swagger/v1/swagger.json", "JWTAuthAuthentication2 v1"));
}
app.UseHttpsRedirection();
app.UseRouting();

////JWTConfig - Adicionar sempre Authentication antes de Authorization
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =&amp;gt;
{
    endpoints.MapControllers();
});
app.Run();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Repare que não fiz grandes alterações, só passei as configurações da startup para a classe &lt;code&gt;Program.cs&lt;/code&gt; e agora você pode excluir a classe &lt;code&gt;Startup.cs&lt;/code&gt; adotoando os padrões do .net 6&lt;/p&gt;
&lt;h1&gt;
  
  
  Crud de Roles
&lt;/h1&gt;

&lt;p&gt; &lt;/p&gt;
&lt;h3&gt;
  
  
  Create Read Update Delete - CRUD
&lt;/h3&gt;

&lt;p&gt; &lt;br&gt;
&lt;a href="https://i.giphy.com/media/YO3icZKE2G8OoGHWC9/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/YO3icZKE2G8OoGHWC9/giphy.gif" alt="Crud"&gt;&lt;/a&gt;&lt;br&gt;
Como vamos fazer um crud completo da entidade Roles, é de boa prática criar uma Controller só pra isso, separando as responsabilidades.&lt;/p&gt;

&lt;p&gt;Nessa Controller só terá autorização quem tiver acesso de Admin.&lt;br&gt;
Regas de negócio que aplicamos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 - Usuário não pode alterar sua própria role&lt;/li&gt;
&lt;li&gt;2 - Precisa ter ao menos 1 usuário admin no banco de dados&lt;/li&gt;
&lt;li&gt;3 - Não pode haver duas Roles com o mesmo nome&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;E assim ficou a &lt;code&gt;RolesController&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Post
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    [HttpPost("AddRole")]
    public async Task&amp;lt;IActionResult&amp;gt; AddRole(RoleViewModel roleRequest,
                                             [FromServices] DataContext context)
    {
        if (!ModelState.IsValid) return BadRequest(ModelState);
        if (context.Roles.Any(x =&amp;gt; x.Name.Equals(roleRequest.Name))) return BadRequest("Role duplicated");

        var roleModel = new Role
        {
            Name = roleRequest.Name,
        };

        await context.Roles.AddAsync(roleModel);
        await context.SaveChangesAsync();
        return Ok(roleModel);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Patch Change User Role
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    [HttpPatch("ChangeUserRole")]
    public async Task&amp;lt;IActionResult&amp;gt; ChangeUserRole(int UserId,
                                                    int NewRoleId,
                                                    [FromServices] DataContext context)
    {
        if(!ModelState.IsValid) return BadRequest(ModelState);

        //Consultas
        var userModel = await context
            .Users
            .FirstOrDefaultAsync(x =&amp;gt; x.Id == UserId);

        var roleModel = await context
            .Roles
            .AsNoTracking()
            .FirstOrDefaultAsync(x =&amp;gt; x.Id == NewRoleId);

        //Validações
        if (userModel == null || roleModel == null)
            return StatusCode(401, "Invalid Id");

        //Verificando quantos usuarios admins temos no sistema
        var userList = await context.Users.ToListAsync();
        int adminUsers = 0;
        foreach (var item in userList)
        {
            if (item.RolesId == 2) adminUsers++;
        }

        //Verificando se sobrará pelo menos 1 admin no sistema
        if (userModel.RolesId == 2 &amp;amp;&amp;amp; adminUsers &amp;lt;= 1) return StatusCode(400, "You must have at least 1 admin user in the database");

        userModel.Roles = roleModel;

        //Admin não pode mudar sua própria role
        if (User.Claims.First(x =&amp;gt; x.Type == ClaimTypes.NameIdentifier).Value.Equals(userModel.Id.ToString())) return StatusCode(400, "You cannot change your own role");


        await context.SaveChangesAsync();
        return Ok(userModel.Name + " Role changed to " + roleModel.Name);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Get Mostrar todos os Roles
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[HttpGet("GetRoles")]
    public async Task&amp;lt;IEnumerable&amp;lt;Role&amp;gt;&amp;gt; GetRoles([FromServices] DataContext context)
    {
        return await context.Roles.ToListAsync();
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Patch Edit Role
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    [HttpPatch("EditRole")]
    public async Task&amp;lt;IActionResult&amp;gt; EditRole([FromServices] DataContext context,
                                                              Role roleRequest)
    {
        if(!ModelState.IsValid) return BadRequest(ModelState);

        var roleModel = await context.Roles.AsNoTracking().FirstOrDefaultAsync(x =&amp;gt; x.Id == roleRequest.Id);

        //Validações
        if (roleModel == null) return NotFound("Role not found");
        if (context.Roles.Any(x =&amp;gt; x.Name.Equals(roleRequest.Name))) return BadRequest("Role duplicated");


        context.Roles.Update(roleRequest);
        await context.SaveChangesAsync(); 
        return Ok(roleRequest);        
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Delete Roles
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[HttpDelete("DeleteRoles")]
    public async Task&amp;lt;IActionResult&amp;gt; DeleteRoles(int roleId,
                                                [FromServices] DataContext context)
    {
        if(!ModelState.IsValid) return BadRequest(ModelState);

        var roleModel = await context.Roles.FirstOrDefaultAsync(x =&amp;gt; x.Id == roleId);

        //Validações
        if (roleModel == null) return NotFound("Role not found");
        if (roleModel.Name.Contains("admin")) return BadRequest("Cannot delete admin role");

        context.Roles.Remove(roleModel);
        await context.SaveChangesAsync();
        return Ok("Role " + roleModel.Name + " Deleted");
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;O código está inteiro comentado e separei os blocos por #region para facilitar leitura e busca dos métodos.&lt;br&gt;
 &lt;br&gt;
Qualquer dúvida, é só comentar ou entrar em contato comigo.&lt;br&gt;
 &lt;/p&gt;

&lt;p&gt;No proximo módulo eu adicionarei:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CRUD de Usuários&lt;/li&gt;
&lt;li&gt;introdução do Repository Pattern&lt;/li&gt;
&lt;li&gt;Divisão em 3 Projetos (Infra - Domain - API)
 
Obrigado por lerem mais um módulo da série dessa API.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag__user ltag__user__id__729596"&gt;
    &lt;a href="/mgpaixao" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F729596%2Feea9bd33-293a-4662-ac8a-6f1e6637fe14.jpeg" alt="mgpaixao image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/mgpaixao"&gt;Matheus Paixão&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/mgpaixao"&gt;Gosto de compartilhar conhecimento pois foi assim que eu aprendi a programar. O meu negócio é todo dia saber mais que eu sabia ontem. Pode me chamar, vamos aprender juntos. Prazer =)&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>programming</category>
    </item>
    <item>
      <title>C# - Criando API com Jwt Token - Autorização e Autenticação - Módulo 1</title>
      <dc:creator>Matheus Paixão</dc:creator>
      <pubDate>Mon, 07 Feb 2022 17:10:27 +0000</pubDate>
      <link>https://forem.com/mgpaixao/criando-api-com-jwt-autorizacao-e-autenticacao-modulo-1-20b8</link>
      <guid>https://forem.com/mgpaixao/criando-api-com-jwt-autorizacao-e-autenticacao-modulo-1-20b8</guid>
      <description>&lt;p&gt;Código Módulo 1 -&amp;gt; &lt;a href="https://github.com/mgpaixao/JWTAuthAuthenticationProject/tree/master/Modulo%201" rel="noopener noreferrer"&gt;Repositório GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Olá Devs, este artigo vai mostrar de forma simples como criar um API de autenticação e autorização de API's através de JWT Token e definindo Roles(cargos) pra cada usuário do sistema. &lt;/p&gt;

&lt;h1&gt;
  
  
  Sumário - Clique e ache rápido o que deseja ler
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Regra de Negócio e Contextualização&lt;/li&gt;
&lt;li&gt;Banco de dados Postgres&lt;/li&gt;
&lt;li&gt;Criando API Básica com JWT - Models&lt;/li&gt;
&lt;li&gt;Configuração do JWT&lt;/li&gt;
&lt;li&gt;Controller Auth&lt;/li&gt;
&lt;li&gt;Criptografia da senha de usuário&lt;/li&gt;
&lt;li&gt;Configuração Startup&lt;/li&gt;
&lt;li&gt;Populando o Banco de Dados&lt;/li&gt;
&lt;li&gt;Teste com Swagger&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Regra de Negócio
&lt;/h1&gt;

&lt;h1&gt;
  
  
  &lt;code&gt;Modulo 1&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Nesse primeiro módulo, iremos focar na aplicação pura do JWT Token com Roles. Nos próximos módulos teremos os CRUDs completos e complementos de funcionalidades.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;O usuário Admin é cadastrado na mão, no banco de dados e ele é o único que tem o poder de mudar as Roles dos usuários.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As roles são cadastradas direto no banco de dados também.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;O sistema cadastra um usuário.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;O sistema faz Login do usuário.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/11fot0YzpQMA0g/giphy-downsized-large.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/11fot0YzpQMA0g/giphy-downsized-large.gif" alt="Gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Importância do Controle de Acesso
&lt;/h1&gt;

&lt;p&gt;Imagina que você tem um sistema que vários usuários com cargos diferentes e você quer que cada cargo tenha um tipo de acesso diferente. Exemplo: O Assistente Financeiro terá acesso a relatórios da área de finanças, mas, apenas o Diretor financeiro terá acesso a liberar verbas, aumentar e diminuir budgets (despesas) de cada departamento. &lt;/p&gt;

&lt;p&gt;Para que você consiga fazer esse controle por tipo de usuário, uma solução pode ser definir &lt;code&gt;Roles&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Roles
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/3o6EhRA9T9NF6mIhjy/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3o6EhRA9T9NF6mIhjy/giphy.gif" alt="Gif"&gt;&lt;/a&gt;&lt;br&gt;
No nosso caso, no Modulo 1, teremos 2 tipos de usuários: &lt;code&gt;Admin&lt;/code&gt; e o &lt;code&gt;User&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Admin&lt;/code&gt; - Acesso a todos os endpoints&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;User&lt;/code&gt; - Acesso ao endpoint de registro de usuários e o de login de usuários&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Qual a diferença entre Autenticação e Autorização?
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/81xwEHX23zhvy/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/81xwEHX23zhvy/giphy.gif" alt="Gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Autenticação&lt;/code&gt; é o processo de ver quem você é, qual seu nome, senha, email, você realmente é quem você diz ser? Isso é AUTENTICAR&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Autorização&lt;/code&gt; é o processo de verificar aonde você tem permissão de acessar. Quais endpoints você terá acesso. Isso é AUTORIZAR&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Exemplo: Você chega numa balada e logo na entrada precisa ser &lt;code&gt;Autenticado&lt;/code&gt;, eles verificaram seu nome, seu cartão de crédito e vão verificar pelo seu nome aonde você tem &lt;code&gt;Autorização&lt;/code&gt; de entrar se você vai apenas na pista é uma pulseira, se pode ir na pista e no camarote, já é outra pulseira. No programação essa pulseira de identificação seria o seu &lt;code&gt;Token&lt;/code&gt;, contendo suas informações básicas e suas &lt;code&gt;Claims&lt;/code&gt;, que seriam as &lt;code&gt;autorizações&lt;/code&gt; que você tem, compactadas naquela pulseira (token).&lt;/p&gt;
&lt;h3&gt;
  
  
  Criando uma API básica usando o processo de autenticação COM JWT token
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/SV09Wp6hvMW7m/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/SV09Wp6hvMW7m/giphy.gif" alt="Gif"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Models e View Models
&lt;/h1&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;Role&lt;/code&gt;
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public class Role
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;User&lt;/code&gt;
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public class User
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public string PasswordHash { get; set; }
        public string Slug { get; set; }
        public int RolesId { get; set; }
        public Role Roles { get; set; }
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;LoginViewModel&lt;/code&gt;
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public class LoginViewModel
    {
        [Required(ErrorMessage = "Name is required")]
        public string Name { get; set; }

        [Required(ErrorMessage = "Email is required")]
        [EmailAddress(ErrorMessage = "Email must be valid")]
        public string Email { get; set; }
        [Required(ErrorMessage = "Password is required")]
        public string Password { get; set; }
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;RegisterViewModel&lt;/code&gt;
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public class RegisterViewModel
    {
        [Required(ErrorMessage = "Name is required")]
        public string Name { get; set; }

        [Required(ErrorMessage = "Email is required")]
        [EmailAddress(ErrorMessage = "Email must be valid")]
        public string Email { get; set; }
        [Required(ErrorMessage = "Password is required")]
        public string Password { get; set; }
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  Banco de Dados - Postgres
&lt;/h1&gt;
&lt;h1&gt;
  
  
  &lt;code&gt;Mapeamentos&lt;/code&gt;
&lt;/h1&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;UserMap&lt;/code&gt;
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public class UserMap : IEntityTypeConfiguration&amp;lt;User&amp;gt;
    {
        public void Configure(EntityTypeBuilder&amp;lt;User&amp;gt; builder)
        {
            // Tabela
            builder.ToTable("User");

            // Chave Primária
            builder.HasKey(x =&amp;gt; x.Id);

            // Identity
            builder.Property(x =&amp;gt; x.Id)
                .ValueGeneratedOnAdd()
                .UseIdentityColumn();

            // Propriedades
            builder.Property(x =&amp;gt; x.Name)
                .IsRequired()
                .HasColumnName("Name")
                .HasColumnType("VARCHAR")
                .HasMaxLength(80);

            builder.Property(x =&amp;gt; x.Email)
                .IsRequired()
                .HasColumnName("Email")
                .HasColumnType("VARCHAR")
                .HasMaxLength(160);

            builder.Property(x =&amp;gt; x.PasswordHash).IsRequired()
                .HasColumnName("PasswordHash")
                .HasColumnType("VARCHAR")
                .HasMaxLength(255);

            builder.Property(x =&amp;gt; x.Slug)
                .IsRequired()
                .HasColumnName("Slug")
                .HasColumnType("VARCHAR")
                .HasMaxLength(80);              


            // Índices
            builder
                .HasIndex(x =&amp;gt; x.Slug, "IX_User_Slug")
                .IsUnique();            
        }
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;RolesMap&lt;/code&gt;
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public class RolesMap : IEntityTypeConfiguration&amp;lt;Role&amp;gt;
    {
        public void Configure(EntityTypeBuilder&amp;lt;Role&amp;gt; builder)
        {
            builder.ToTable("Role");

            builder.HasKey(x =&amp;gt; x.Id);

            builder.Property(x =&amp;gt; x.Id)
                .ValueGeneratedOnAdd()
                .UseIdentityColumn();

            builder.Property(x =&amp;gt; x.Name)
                .HasMaxLength(128)
                .HasColumnType("VARCHAR")
                .HasColumnName("Name");

        }
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;Startup.cs&lt;/code&gt;
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public void ConfigureServices(IServiceCollection services)
        {
...
            //DBContext
            services.AddDbContext&amp;lt;DataContext&amp;gt;();
...
...
        }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;DataContext&lt;/code&gt;
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public class DataContext : DbContext
    {
        public DbSet&amp;lt;User&amp;gt; Users { get; set; }
        public DbSet&amp;lt;Role&amp;gt; Roles { get; set; }

        private IConfiguration configuration;

        public DataContext(IConfiguration _configuration)
        {
            configuration = _configuration;
        }
        protected override void OnConfiguring(DbContextOptionsBuilder options)
            =&amp;gt; options.UseNpgsql(configuration["ConnectionString:Postgres"].ToString());

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.ApplyConfiguration(new UserMap());
            modelBuilder.ApplyConfiguration(new RolesMap());
        }
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;ConnectionString - secrets.json&lt;/code&gt;
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

{
  "ConnectionString:Postgres": "Host=localhost;Database=Teste;Username=seu username;Password=sua senha"
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  Token de Assinatura
&lt;/h1&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;Configuration.cs&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;A chave de assinatura ou &lt;code&gt;JWTKey&lt;/code&gt; é no nosso caso um &lt;code&gt;GUID&lt;/code&gt; que colocamos dentro da &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public static class Configuration
    {
        //Token
        public static string JwtKey { get; set; } = "12345678-1234-1234-1234-123456789123";
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  O segredo por trás de tudo
&lt;/h1&gt;
&lt;h1&gt;
  
  
  &lt;code&gt;TokenService.cs&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Bibliotecas usadas&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public string GenerateToken (User user)
        {
            //Estancia do manipulador de Token
            var tokenHandler = new JwtSecurityTokenHandler();
            //Chave da classe Configuration. O Token Handler espera um Array de Bytes, por isso é necessário converter
            var key = Encoding.ASCII.GetBytes(Configuration.JwtKey);
            //
            var claims = user.GetClaims();
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(claims), //Claims que vão compor o token
                Expires = DateTime.UtcNow.AddHours(8), //Por quanto tempo vai valer o token?
                SigningCredentials = //Assinatura do token, serve para identificar que mandou o token e garantir que o token não foi alterado no meio do caminho.
                new SigningCredentials(
                    new SymmetricSecurityKey(key),
                    SecurityAlgorithms.HmacSha256Signature)
            };

            //Gerando o token
            var token = tokenHandler.CreateToken(tokenDescriptor);
            //Retornando tudo como uma string
            return tokenHandler.WriteToken(token);
        }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;tokenHandle&lt;/code&gt; - Chave da classe Configuration. O Token Handler espera um Array de Bytes, por isso é necessário converter&lt;br&gt;
&lt;code&gt;key&lt;/code&gt; - JWTKey em formato byte&lt;br&gt;
&lt;code&gt;claims&lt;/code&gt; - Resultado do método GetClaims() que gera as Claims que vão copor o token&lt;br&gt;
&lt;code&gt;tokenDescriptor = new SecurityTokenDescriptor{}&lt;/code&gt; - Montando o token com todos seus parâmetros.&lt;/p&gt;

&lt;p&gt;Há mais comentários detalhando cada linha do código no próprio código.&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;code&gt;GetClaims()&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Método que adiciona dentro de uma lista todas as informações que você quer export do usuário no Jwt token através da Claim.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public static class RoleClaimExtention
    {
        public static IEnumerable&amp;lt;Claim&amp;gt; GetClaims(this User user)
        {
            var result = new List&amp;lt;Claim&amp;gt;
            {
                new(ClaimTypes.Name, user.Name),
                new(ClaimTypes.Email, user.Email),
                new(ClaimTypes.Role, user.Roles.Name)
            };
            return result;
        }
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  Controller
&lt;/h1&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;Bibliotecas&lt;/code&gt;
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

using SecureIdentity.Password;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Endpoints -
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Post&lt;/strong&gt; &lt;code&gt;Register&lt;/code&gt; - &lt;strong&gt;Rota&lt;/strong&gt;  - &lt;code&gt;api/auth/v1/register&lt;/code&gt;
Registra uma nova conta de usuário no banco de dados&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Post&lt;/strong&gt; &lt;code&gt;Login&lt;/code&gt; - &lt;strong&gt;Rota&lt;/strong&gt;- &lt;code&gt;api/auth/v1/login&lt;/code&gt;
Autoriza o usuário através da validação das credenciais, e gera um JWT Token&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Patch&lt;/strong&gt; &lt;code&gt;ChangeRole&lt;/code&gt; - &lt;strong&gt;Rota&lt;/strong&gt;- &lt;code&gt;api/auth/v1/changeUserRole&lt;/code&gt;
Altera a Role do usuário no banco de dados&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;Classe da Controller&lt;/code&gt;
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

    [Authorize]
    [Route("api/auth")]
    [ApiController]
    public class AuthController : ControllerBase


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  EndPoint &lt;code&gt;Register&lt;/code&gt;
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

        [AllowAnonymous]
        [HttpPost("v1/register")]
        public async Task&amp;lt;IActionResult&amp;gt; Register([FromBody] RegisterViewModel model,
                                              [FromServices] DataContext context)
        {
            if (!ModelState.IsValid) return BadRequest(ModelState);

            var user = new User
            {
                Name = model.Name,
                Email = model.Email,
                Slug = model.Email.Replace("@", "-").Replace(".", "-"),
                RolesId = 1,
                PasswordHash = PasswordHasher.Hash(model.Password),
            };

            try
            {
                await context.Users.AddAsync(user);
                await context.SaveChangesAsync();

                return Ok($"{user.Email} {user.PasswordHash}");
            }
            catch (DbUpdateException)
            {
                return StatusCode(400, "Duplicate Email");
            }
            catch
            {
                return StatusCode(500, "Internal Error");
            }
        }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Criptografia da senha do usuário
&lt;/h3&gt;

&lt;p&gt;Usamos a classe &lt;code&gt;PasswordHasher&lt;/code&gt; da biblioteca &lt;code&gt;SecureIdentity&lt;/code&gt; para criptografar a senha digitada pelo usuário e salvar no banco esse senha criptografada. &lt;code&gt;PasswordHash = PasswordHasher.Hash(model.Password)&lt;/code&gt; &lt;a href="https://www.kaspersky.com.br/blog/hash-o-que-sao-e-como-funcionam/2773/" rel="noopener noreferrer"&gt;O que é Hash?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para segurança do usuário nunca salvar a senha do usuário sem criptografia no banco de dados.&lt;/p&gt;

&lt;p&gt;Na hora de fazer a autenticação, e verificar a senha, é necessário discriptografar a senha do banco de dados e comparar com a senha que o usuário digitou.&lt;br&gt;
&lt;code&gt;PasswordHasher.Verify(Senha do banco de dados, Senha digitada pelo usuário)&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  EndPoint &lt;code&gt;Login&lt;/code&gt;
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

        [AllowAnonymous]
        [HttpPost("v1/login")]
        public async Task&amp;lt;IActionResult&amp;gt; Login(
       [FromBody] LoginViewModel model,
       [FromServices] DataContext context,
       [FromServices] TokenService tokenService)
        {
            if (!ModelState.IsValid)
                return BadRequest(ModelState.Values);

            var user = await context
                .Users
                .Include(x =&amp;gt; x.Roles)
                .AsNoTracking()
                .FirstOrDefaultAsync(x =&amp;gt; x.Email == model.Email);

            if (user == null)
                return StatusCode(401, "User or password invalid");

            if (!PasswordHasher.Verify(user.PasswordHash, model.Password))
                return StatusCode(401, "User or password invalid");

            try
            {
                var token = tokenService.GenerateToken(user);
                return Ok(token);
            }
            catch
            {
                return StatusCode(500, "Internal Error");
            }
        }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  EndPoint &lt;code&gt;changeUserRole&lt;/code&gt;
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

        [Authorize(Roles = "admin")]
        [HttpPatch("v1/changeUserRole")]
        public async Task&amp;lt;IActionResult&amp;gt; ChangeRole(int UserId,
                                                    int NewRoleId,
                                                    [FromServices] DataContext context)
        {
            var user = await context
                .Users
                .FirstOrDefaultAsync(x =&amp;gt; x.Id == UserId);

            var role = await context
                .Roles
                .AsNoTracking()
                .FirstOrDefaultAsync(x =&amp;gt; x.Id == NewRoleId);

            if (user == null || role == null)
                return StatusCode(401, "Invalid Id");

            user.Roles = role;

            await context.SaveChangesAsync();
            return Ok();
        }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;[Authorize]&lt;/code&gt; - Data Notation que limita o acesso apenas para quem está autorizado/Logado apenas.&lt;br&gt;
&lt;code&gt;[AllowAnonymous]&lt;/code&gt; - Data Notation que permite acesso de usuários que não estão autorizados/logados na API.&lt;br&gt;
&lt;code&gt;[Authorize(Roles = "admin")]&lt;/code&gt; - Data Notation que permite acesso de usuários que contem a role &lt;code&gt;admin&lt;/code&gt; em seu Claim&lt;/p&gt;
&lt;h2&gt;
  
  
  Configuração da Startup
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            //DBContext
            services.AddDbContext&amp;lt;DataContext&amp;gt;();

            //JWTConfig
            var key = Encoding.ASCII.GetBytes(JwtKey);
            services.AddAuthentication(x =&amp;gt;
                {
                    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                }).AddJwtBearer(x =&amp;gt;
                {
                    x.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuerSigningKey = true,
                        ValidateAudience = false,
                        IssuerSigningKey = new SymmetricSecurityKey(key),
                        ValidateIssuer = false
                    };                    
                });
            //Injeção de Dependencia
            services.AddTransient&amp;lt;TokenService&amp;gt;();

            services.AddControllers();

            //Configuração do Swagger para adicionar o Bearer Token na auth
            services.AddSwaggerGen(c =&amp;gt;
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "JWTAuthAuthentication", Version = "v1" });
                c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
                 {
                     Name = "Authorization",
                     Type = SecuritySchemeType.ApiKey,
                     Scheme = "Bearer",
                     BearerFormat = "JWT",
                     In = ParameterLocation.Header,
                     Description = "JWT Authorization header using the Bearer scheme",
                 });
                c.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                          new OpenApiSecurityScheme
                          {
                              Reference = new OpenApiReference
                              {
                                  Type = ReferenceType.SecurityScheme,
                                  Id = "Bearer"
                              }
                          },
                         new string[] {}
                    }
                }); 
            });
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c =&amp;gt; c.SwaggerEndpoint("/swagger/v1/swagger.json", "JWTAuthAuthentication v1"));

            }

            app.UseHttpsRedirection();

            app.UseRouting();

            ////JWTConfig - Adicionar sempre Authentication antes de Authorization
            app.UseAuthentication();
            app.UseAuthorization();


            app.UseEndpoints(endpoints =&amp;gt;
            {
                endpoints.MapControllers();
            });
        }
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  Populando o Banco de dados
&lt;/h1&gt;

&lt;p&gt;Da forma que achar melhor, através de GUIs como PgAdmin ou console, popúle a tabela de &lt;code&gt;Role&lt;/code&gt; como na imagem abaixo, pois ainda não criaram um endpoint para isso.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnljlzz0cn46j8m6w3ylg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnljlzz0cn46j8m6w3ylg.png" alt="ROLES"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E na tabela &lt;code&gt;User&lt;/code&gt; crie um usuário com a role de Admin, pois ele será o ínico que terá acesso ao endpoint &lt;code&gt;changeRoles&lt;/code&gt;. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6acar5op9w9wxvayxhgm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6acar5op9w9wxvayxhgm.png" alt="User"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Teste com Swagger
&lt;/h1&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;Register&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm6g4kuds5oq8j0x76zn1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm6g4kuds5oq8j0x76zn1.png" alt="Register"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;Login&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa6mu36y64700t5kr71f3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa6mu36y64700t5kr71f3.png" alt="Login"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Antes de seguirmos com a validação do token, tente alterar as roles no endpoint &lt;code&gt;changeRoles&lt;/code&gt; e repare que o retorno é 401, não autorizado. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2sstvx3lag88hrfr9y8v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2sstvx3lag88hrfr9y8v.png" alt="Logins"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;O retorno que temos do login é o JTW token com as claims que definimos do token service. Para se autorizar, pegue esse Token e se tudo deu certo na configuração do Swagger, você deve ver um ícone no lado direito superior da pagina do Swagger:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffx87yq7vevto5mei3k7x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffx87yq7vevto5mei3k7x.png" alt="Retornojtw"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clique nele e insira o token nesse formado &lt;code&gt;Bearer + Token&lt;/code&gt;, como na imagem abaixo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5pjwgopdl7s8uk4qzmr9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5pjwgopdl7s8uk4qzmr9.png" alt="Bearertoken"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Porém, mesmo assim você não terá acesso ao endpoint &lt;code&gt;changeRoles&lt;/code&gt;, pois quando você cria um usuário, o role dele não é de admin. &lt;/p&gt;

&lt;p&gt;Faça o login com o usuário &lt;code&gt;Admin&lt;/code&gt; que criou no banco de dados.&lt;/p&gt;

&lt;p&gt;Insira o Bearer Token e altere a role do usuário que acabou de criar.&lt;/p&gt;

&lt;p&gt;E veja que o resultado é 200, sucesso.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkkhg99ztxxw0207ssuw2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkkhg99ztxxw0207ssuw2.png" alt="Sucesso"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para verificar o JWT token e suas claims, acesse o site &lt;a href="https://jwt.io/" rel="noopener noreferrer"&gt;Jwt.io&lt;/a&gt; e cole o token no quadro de Encoded.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F39bs03x5izemommgh4rx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F39bs03x5izemommgh4rx.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repare o payload do token tem o nome, email, a role e os timestamps de quando foi gerando e até quando dura o token.&lt;/p&gt;

&lt;p&gt;Obrigado por ler este artigo. Abaixo colocarei os links dos próximos módulos quando forem lançados, a ideia é evolouirmos pouco a pouco essa aplicação.&lt;/p&gt;
&lt;h1&gt;
  
  
  Spoiler
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Modulo 2
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;CRUD da Roles&lt;/li&gt;
&lt;li&gt;O sistema tem sempre que ter um Admin&lt;/li&gt;
&lt;li&gt;Admin não pode mudar suas próprias roles&lt;/li&gt;
&lt;li&gt;E muito mais.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag__user ltag__user__id__729596"&gt;
    &lt;a href="/mgpaixao" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F729596%2Feea9bd33-293a-4662-ac8a-6f1e6637fe14.jpeg" alt="mgpaixao image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/mgpaixao"&gt;Matheus Paixão&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/mgpaixao"&gt;Gosto de compartilhar conhecimento pois foi assim que eu aprendi a programar. O meu negócio é todo dia saber mais que eu sabia ontem. Pode me chamar, vamos aprender juntos. Prazer =)&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>jwt</category>
      <category>csharp</category>
    </item>
    <item>
      <title>How to use Postgres SQL, NoSql and Entity Framework Core</title>
      <dc:creator>Matheus Paixão</dc:creator>
      <pubDate>Wed, 15 Dec 2021 21:14:16 +0000</pubDate>
      <link>https://forem.com/mgpaixao/how-to-use-postgres-sql-nsql-and-entity-framework-core-804</link>
      <guid>https://forem.com/mgpaixao/how-to-use-postgres-sql-nsql-and-entity-framework-core-804</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkwmm6viu0x5yylokbgje.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkwmm6viu0x5yylokbgje.gif" alt="Gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hello. I'll show you step by step how to work with relational and non-relational database at the same time with Postgres and support for EFCore.&lt;/p&gt;

&lt;h1&gt;
  
  
  Postgres
&lt;/h1&gt;

&lt;p&gt;Postgres is an object-relational database owned by Oracle company, however it is an open source database with a strong community backing it. Postgres is incredibly robust and reliable, given its 30-year history in the market.&lt;/p&gt;

&lt;h1&gt;
  
  
  Data Types
&lt;/h1&gt;

&lt;p&gt;Primitives: Integer, Numeric, String, Boolean&lt;br&gt;
Structured: Date/Time, Array, Range / Multirange, UUID&lt;br&gt;
Document: JSON/JSONB, XML, Key-value (Hstore)&lt;br&gt;
Geometry: Point, Line, Circle, Polygon&lt;br&gt;
Customizations: Composite, Custom Types&lt;/p&gt;
&lt;h1&gt;
  
  
  JSON/JSONB - Working with NSql
&lt;/h1&gt;

&lt;p&gt;One of the wonders of the Postgres database is the possibility of working in a relational and non-relational way in the same database, in the same object, in the same table. YEA ! It is possible, through the Document data type that receives Json and JsonBinary (JsonB) data.&lt;/p&gt;
&lt;h1&gt;
  
  
  Entity FrameWork Core ORM
&lt;/h1&gt;

&lt;p&gt;In order to be able to use EFcore in our methods using NSql, we need to install a nuget package called &lt;code&gt;npgsql.entityframeworkcore.postgresql&lt;/code&gt; which will allow us to make the CRUD methods more similar to the EFCore ORM we are used to.&lt;/p&gt;
&lt;h1&gt;
  
  
  Prática - Config
&lt;/h1&gt;
&lt;h3&gt;
  
  
  Pacotes
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;npgsql.entityframeworkcore.postgresql&lt;br&gt;
Microsoft.EntityFrameworkCore&lt;br&gt;
Microsoft.EntityFrameworkCore.Design&lt;br&gt;
Microsoft.EntityFrameworkCore.Toll&lt;br&gt;
EFCore.NamingConventions&lt;/code&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  StartUp
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;ConfigureServices Method&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

            services.AddDbContext&amp;lt;PostgresNsql.MyContext&amp;gt;(option =&amp;gt; option.UseNpgsql(Configuration.GetConnectionString("Nsql")));



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  DBContext
&lt;/h1&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public class MyContext : DbContext
    {
        public MyContext(DbContextOptions options) :base(options)
        {

        }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            =&amp;gt; optionsBuilder
            .UseNpgsql()
            .UseSnakeCaseNamingConvention();

        protected override void OnModelCreating(ModelBuilder modelBuilder)
            =&amp;gt; modelBuilder
            .Entity&amp;lt;DataModel&amp;gt;()
            .Property(e =&amp;gt; e.Id)
            .UseIdentityAlwaysColumn();

        public DbSet&amp;lt;DataModel&amp;gt; DataModels { get; set; }
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;UseSnakeCaseNamingConvention()&lt;/code&gt; Snake Case may be needed to handle JSONs that separate 2 words with _ underscore. That way you won't have problems with serialization.&lt;/p&gt;

&lt;p&gt;Setting auto-increment for ID column&lt;br&gt;
&lt;code&gt;.Property(e =&amp;gt; e.Id)&lt;br&gt;
 .UseIdentityAlwaysColumn();&lt;/code&gt; Identity always column is one of the types of value assignment you can give, in this mode you define that the values will be generated directly in the database, making it impossible for you to set the value at the time of insertion into the database.&lt;/p&gt;
&lt;h1&gt;
  
  
  Model
&lt;/h1&gt;

&lt;p&gt;In creating the model is the big leap in using SQL and NSql together. If you have unstable data yet and it's not 100% mappable and structured, you can use DataType Json to get the NSql part of your data.&lt;/p&gt;

&lt;p&gt;For that, you need to add the &lt;code&gt;System.Text.Json&lt;/code&gt; library and type its property with the JsonDocument class, as it will already identify that data will be received there in JSON and will facilitate de-cerealization.&lt;/p&gt;

&lt;p&gt;The model needs to be IDisposable as the JsonDocument class is IDisposable too, improving memory management.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public class DataModel : IDisposable
    {
        public int Id { get; set; }
        public string Nome { get; set; }
        public int idade { get; set; }

        public JsonDocument Data { get; set; }

        public void Dispose() =&amp;gt; Data?.Dispose();
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  Estructured Data
&lt;/h1&gt;

&lt;p&gt;To identify the NSql part of our model, we need to add the Data Notation &lt;code&gt;[Column(TypeName = "jsonb")]&lt;/code&gt; to identify the Json object and map the properties.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public class DataModel
    {
        public int Id { get; set; }
        public string Nome { get; set; }
        public int idade { get; set; }

        [Column(TypeName = "jsonb")]
        public Endereco Address { get; set; }
    }

public class Endereco // Mapping the JSON Data received
{
    public string Rua { get; set; }
    public int Numero { get; set; }
    public Casa[] Casas { get; set; }
}

public class Casa 
{
    public decimal Preco { get; set; }
    public string EnderecoCompleto { get; set; }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  CRUD
&lt;/h1&gt;

&lt;p&gt;I didn't use a repository or some more complex architecture to make the article easier to understand.&lt;/p&gt;

&lt;p&gt;But I will now show in Controller how we can work with JSON type data.&lt;/p&gt;
&lt;h1&gt;
  
  
  GetAll()
&lt;/h1&gt;

&lt;p&gt;Note that nothing changes in the listing of all columns.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public List&amp;lt;DataModel&amp;gt; GetAll()
        {
            return _myContext.DataModels.ToList();
        }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  GetCustom
&lt;/h1&gt;

&lt;p&gt;A question I had when starting to work with Postgres SQL and NSql together is whether it could be done in a query, joining the SQL and NSql data. Below is an example of a Get where I parameterize that I only want results from 12 year olds AND with the last name equal to "Paixao". Age is an SQL value from the age column and "lastname" is an item of the data we receive in JSON.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public IEnumerable&amp;lt;string&amp;gt; Get()
        {
            var resultado = _myContext.DataModels;

            return resultado.Where(x =&amp;gt; x.idade == 12 &amp;amp;&amp;amp; x.Data.RootElement.GetProperty("lastName").GetString() == "Paixao").ToList();           
        }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Another example I brought is if you want to display only 1 of the data items in JSON.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public IEnumerable&amp;lt;string&amp;gt; Get()
        {
            var resultado = _myContext.DataModels;

return resultado.Select(x=&amp;gt;x.Data.RootElement.GetProperty("lastName").GetString()).ToList();
        }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Elements of the JsonElement class from the above code
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;RootElement&lt;/code&gt; is a class that will get the JSON data from the &lt;code&gt;Data&lt;/code&gt; property allowing you to then name with the &lt;code&gt;GetProperty("property")&lt;/code&gt; method which JSON property you will work with and finally you must put the &lt;code&gt;GetString method ()&lt;/code&gt; to convert the JSON data you filtered to string.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/d68IdpvmAHohx5NMEV/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/d68IdpvmAHohx5NMEV/giphy.gif" alt="Gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__user ltag__user__id__729596"&gt;
    &lt;a href="/mgpaixao" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F729596%2Feea9bd33-293a-4662-ac8a-6f1e6637fe14.jpeg" alt="mgpaixao image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/mgpaixao"&gt;Matheus Paixão&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/mgpaixao"&gt;Gosto de compartilhar conhecimento pois foi assim que eu aprendi a programar. O meu negócio é todo dia saber mais que eu sabia ontem. Pode me chamar, vamos aprender juntos. Prazer =)&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>programming</category>
      <category>postgres</category>
      <category>entityframework</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Como trabalhar com Postgres SQL e NOSql juntos com Entity Framework Core?</title>
      <dc:creator>Matheus Paixão</dc:creator>
      <pubDate>Tue, 14 Dec 2021 03:38:39 +0000</pubDate>
      <link>https://forem.com/mgpaixao/como-trabalhar-com-postgres-sql-e-nosql-juntos-com-entity-framework-core-374c</link>
      <guid>https://forem.com/mgpaixao/como-trabalhar-com-postgres-sql-e-nosql-juntos-com-entity-framework-core-374c</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/mgpaixao/how-to-use-postgres-sql-nsql-and-entity-framework-core-804"&gt;This topic in English&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/xT9IgG50Fb7Mi0prBC/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/xT9IgG50Fb7Mi0prBC/giphy.gif" alt="Gif" width="400" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Olá. Vou mostrar um passo a passo de como trabalhar com banco de dado relacional e não relacional ao mesmo tempo com Postgres e suporte para EFCore.&lt;/p&gt;

&lt;h1&gt;
  
  
  Postgres
&lt;/h1&gt;

&lt;p&gt;Postgres é uma banco de dados objeto-relational que pertence a empresa Oracle, porém é um banco de dados open source com uma forte comunidade mantendo-o. Postgres é incrivelmente robusto e confiável, dado seu histórico de 30 anos no mercado.&lt;/p&gt;

&lt;h1&gt;
  
  
  Data Types
&lt;/h1&gt;

&lt;p&gt;Primitives: Integer, Numeric, String, Boolean&lt;br&gt;
Structured: Date/Time, Array, Range / Multirange, UUID&lt;br&gt;
Document: JSON/JSONB, XML, Key-value (Hstore)&lt;br&gt;
Geometry: Point, Line, Circle, Polygon&lt;br&gt;
Customizations: Composite, Custom Types&lt;/p&gt;
&lt;h1&gt;
  
  
  JSON/JSONB - Trabalhando com NSql
&lt;/h1&gt;

&lt;p&gt;Uma das maravilhas do banco de Postgres é a possibilidade de trabalhar de forma relacional e não relacional no mesmo banco, no mesmo objeto, na mesma tabela. SIM ! É possível, através do tipo de dado Document, que recebe dados Json e JsonBinary (JsonB).&lt;/p&gt;
&lt;h1&gt;
  
  
  Entity FrameWork Core ORM
&lt;/h1&gt;

&lt;p&gt;Para podermos usar o EFcore nos nossos métodos usando o NSql, precisamos instalar um pacote nuget chamado &lt;code&gt;npgsql.entityframeworkcore.postgresql&lt;/code&gt; ele vai permitir fazer os métodos CRUD de forma mais parecida com o EFCore ORM que estamos acostumados.&lt;/p&gt;
&lt;h1&gt;
  
  
  Prática - Configuração
&lt;/h1&gt;
&lt;h3&gt;
  
  
  Pacotes
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;npgsql.entityframeworkcore.postgresql&lt;br&gt;
Microsoft.EntityFrameworkCore&lt;br&gt;
Microsoft.EntityFrameworkCore.Design&lt;br&gt;
Microsoft.EntityFrameworkCore.Toll&lt;br&gt;
EFCore.NamingConventions&lt;/code&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  StartUp
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;ConfigureServices Method&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;            services.AddDbContext&amp;lt;PostgresNsql.MyContext&amp;gt;(option =&amp;gt; option.UseNpgsql(Configuration.GetConnectionString("Nsql")));

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  DBContext
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class MyContext : DbContext
    {
        public MyContext(DbContextOptions options) :base(options)
        {

        }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            =&amp;gt; optionsBuilder
            .UseNpgsql()
            .UseSnakeCaseNamingConvention();

        protected override void OnModelCreating(ModelBuilder modelBuilder)
            =&amp;gt; modelBuilder
            .Entity&amp;lt;DataModel&amp;gt;()
            .Property(e =&amp;gt; e.Id)
            .UseIdentityAlwaysColumn();

        public DbSet&amp;lt;DataModel&amp;gt; DataModels { get; set; }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;UseSnakeCaseNamingConvention()&lt;/code&gt; Snake Case pode ser necessário para lidar com JSONs que separam 2 palavras com _ underline. Dessa forma não tera problemas com serialização.&lt;/p&gt;

&lt;p&gt;Definindo auto-increment na coluna ID&lt;br&gt;
&lt;code&gt;.Property(e =&amp;gt; e.Id)&lt;br&gt;
 .UseIdentityAlwaysColumn();&lt;/code&gt; Identity always column é um dos tipos de atribuição de valor que você pode dar, nessa modalidade você define que os valores serão gerados diretamente no banco, impossibilitando você setar o valor no momento de inserção no banco de dados.&lt;/p&gt;
&lt;h1&gt;
  
  
  Model
&lt;/h1&gt;

&lt;p&gt;Na criação da model é que está o grande pulo do gato no uso de SQL e NSql juntos. Caso você tenha dados instáveis ainda e eles não são 100% mapeaveis e estruturados, você pode usar o DataType Json para receber a parte NSql dos seus dados.&lt;/p&gt;

&lt;p&gt;Para isso, você precisa adicionar a biblioteca &lt;code&gt;System.Text.Json&lt;/code&gt; e tipar a sua propriedade com a classe JsonDocument, pois ele já identificará que ali será recebido dados em JSON e facilitará a descerialização.&lt;/p&gt;

&lt;p&gt;A model precisa ser IDisposable pois a classe JsonDocument é IDisposable também, melhorando o gerenciamento de memória.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class DataModel : IDisposable
    {
        public int Id { get; set; }
        public string Nome { get; set; }
        public int idade { get; set; }

        public JsonDocument Data { get; set; }

        public void Dispose() =&amp;gt; Data?.Dispose();
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Dados Estruturados
&lt;/h1&gt;

&lt;p&gt;Para identificar a parte NSql da nossa model, é preciso adicionar a Data Notation &lt;code&gt;[Column(TypeName = "jsonb")]&lt;/code&gt; para identificar o objeto Json e mapear as propriedades.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class DataModel
    {
        public int Id { get; set; }
        public string Nome { get; set; }
        public int idade { get; set; }

        [Column(TypeName = "jsonb")]
        public Endereco Address { get; set; }
    }

public class Endereco // Mapeando os dados recebidos em Json
{
    public string Rua { get; set; }
    public int Numero { get; set; }
    public Casa[] Casas { get; set; }
}

public class Casa 
{
    public decimal Preco { get; set; }
    public string EnderecoCompleto { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  CRUD
&lt;/h1&gt;

&lt;p&gt;Eu não usei um repositório ou alguma arquitetura mais complexa para facilitar o entendimento do artigo.&lt;/p&gt;

&lt;p&gt;Mas mostrarei agora na Controller como podemos trabalhar com os dados do tipo JSON.&lt;/p&gt;
&lt;h1&gt;
  
  
  GetAll()
&lt;/h1&gt;

&lt;p&gt;Percebam que nada muda na listagem de todas as colunas.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public List&amp;lt;DataModel&amp;gt; GetAll()
        {
            return _myContext.DataModels.ToList();
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  GetPersonalidado
&lt;/h1&gt;

&lt;p&gt;Uma dúvida que tinha quando começando a trabalhar com Postgres SQL e NSql junto é se dava pra fazer em uma consulta, juntar os dados SQL e NSql. Abaixo está um exemplo de um Get onde eu parametrizo que quero apenas resultados de pessoas com 12 anos E com o ultimo nome igual a "Paixao". Idade é um valor SQL da coluna idade e "lastname" é um item dos dados que recebemos em JSON.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public IEnumerable&amp;lt;string&amp;gt; Get()
        {
            var resultado = _myContext.DataModels;

            return resultado.Where(x =&amp;gt; x.idade == 12 &amp;amp;&amp;amp; x.Data.RootElement.GetProperty("lastName").GetString() == "Paixao").ToList();           
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Um outro exemplo que trouxe, é caso você quero exibir apenas 1 dos itens dos dados em JSON.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public IEnumerable&amp;lt;string&amp;gt; Get()
        {
            var resultado = _myContext.DataModels;

return resultado.Select(x=&amp;gt;x.Data.RootElement.GetProperty("lastName").GetString()).ToList();
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Elementos da classe JsonElement do código apresentado acima
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;RootElement&lt;/code&gt; é uma classe que vai pegar os dados JSON da propriedade &lt;code&gt;Data&lt;/code&gt; permitindo que você então denomine com o método &lt;code&gt;GetProperty("propriedade")&lt;/code&gt; qual propriedade do JSON você vai trabalhar e por final você deve colocar o método &lt;code&gt;GetString()&lt;/code&gt; para converter o dados JSON que você filtrou em string. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/d68IdpvmAHohx5NMEV/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/d68IdpvmAHohx5NMEV/giphy.gif" alt="Gif" width="480" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Obrigado&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__user ltag__user__id__729596"&gt;
  
    .ltag__user__id__729596 .follow-action-button {
      background-color: #000000 !important;
      color: #ffffff !important;
      border-color: #000000 !important;
    }
  
    &lt;a href="/mgpaixao" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LmLu25D3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--OQVKr0N8--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/729596/eea9bd33-293a-4662-ac8a-6f1e6637fe14.jpeg" alt="mgpaixao image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/mgpaixao"&gt;Matheus Paixão&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/mgpaixao"&gt;Gosto de compartilhar conhecimento pois foi assim que eu aprendi a programar. O meu negócio é todo dia saber mais que eu sabia ontem. Pode me chamar, vamos aprender juntos. Prazer =)&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KAgiXlrF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n8bndcx2jkn1jz1dy98v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KAgiXlrF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n8bndcx2jkn1jz1dy98v.png" alt="linha horizontal" width="880" height="3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Disclaimer
&lt;/h3&gt;

&lt;p&gt;A VaiVoa incentiva seus Desenvolvedores em seu processo de crescimento e aceleração técnica. Os artigos publicados não traduzem a opinião da VaiVoa. A publicação obedece ao propósito de estimular o debate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QJQcNDAe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1wmziqv74ghhgyi9p0om.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QJQcNDAe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1wmziqv74ghhgyi9p0om.png" alt="logo vaivoa" width="548" height="122"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>entityframeworkcore</category>
      <category>csharp</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to map Nested Object mappings with AutoMapper C#</title>
      <dc:creator>Matheus Paixão</dc:creator>
      <pubDate>Mon, 29 Nov 2021 19:50:55 +0000</pubDate>
      <link>https://forem.com/mgpaixao/how-to-map-nested-object-mappings-with-automapper-c-28h1</link>
      <guid>https://forem.com/mgpaixao/how-to-map-nested-object-mappings-with-automapper-c-28h1</guid>
      <description>&lt;p&gt;So let me start by saying that I decided to share this content because I just couldn't find the perfect answer on internet, it took me half a day to figure this out. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F668nvht7zksc10m7zhj5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F668nvht7zksc10m7zhj5.gif" alt="Gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a good practice, we are using the RequestDTO and a ResponseDTO, so we don't return the same model we receive.&lt;/p&gt;

&lt;h2&gt;
  
  
  RequestDTO
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    public class Attributes
    {
        public string type { get; set; }
        public string url { get; set; }
    }

    public class Keep
    {
        public Attributes attributes { get; set; }
        public DateTime LastModifiedDate { get; set; }
        public string Email { get; set; }            
    }

    public class Discart
    {
        public Attributes attributes { get; set; }
        public DateTime LastModifiedDate { get; set; }
        public string Email { get; set; }

    }

    public class Root
    {            
        public List&amp;lt;DataWeNeed&amp;gt; Keep { get; set; }
        public List&amp;lt;DataWeDontNeed&amp;gt; Discart { get; set; }
        public string userId { get; set; }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  ResponseDTO
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    public class Attributes
    {
        public string type { get; set; }
        public string url { get; set; }
    }

    public class ResponseKeep
    {
        public Attributes attributes { get; set; }
        public DateTime LastModifiedDate { get; set; }
        public string Email { get; set; }            
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  AutoMapper Basic Configuration Startup.cs
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

 public void ConfigureServices(IServiceCollection services)
        {            
            services.AddAutoMapper(typeof(Startup));
        }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Controller
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public class Controller : ControllerBase
    {
//AutoMapper Dependency Injection
        private readonly IMapper _map;

        public ValuesController(IMapper map)
        {
            _map = map;
        }

        [HttpPost]
        [Route("api")]
        public Keep Post(Object value)
        {            
//Deserialize de Json request into our Object
            Root deserialized = JsonConvert.DeserializeObject&amp;lt;Root&amp;gt;(value.ToString());

//Mapping the first item of the Keep List into the responseDto
            var responseDTO = _map.Map&amp;lt;ResponseDTO&amp;gt;(deserealized.Keep.FirstOrDefault());

            return responseDTO;
        }
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Mapping Profile
&lt;/h2&gt;

&lt;p&gt;Here is where the magic happens.&lt;/p&gt;

&lt;p&gt;To make sure the the automapper does the right mapping and doesn't returns an exception we must resolve the mapping in details.&lt;br&gt;
How?&lt;/p&gt;

&lt;p&gt;As we have different Objects, we need to tell automapper which objects and fields are mapped and from where, using the method ForMember and MapFrom.&lt;/p&gt;

&lt;p&gt;See that the main Object the automapper does automatically without mapping the fields, but, when it comes to the Object Value Attributes I had to map one by one so it would understand where the information is sourced and where the information the designated. &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

public AutoMapper()
        {
            CreateMap&amp;lt;RequestDTO.Attributes, ResponseDTO.Attributes&amp;gt;()
                .ForMember(
                    dest =&amp;gt; dest.type,
                    opt =&amp;gt; opt.MapFrom(src =&amp;gt; src.type)
                )
                .ForMember(
                    dest =&amp;gt; dest.url,
                    opt =&amp;gt; opt.MapFrom(src =&amp;gt; src.url)
                );
            CreateMap&amp;lt;Keep, ResponseKeep&amp;gt;()
                .ForMember(
                dest =&amp;gt; dest.attributes,
                opt =&amp;gt; opt.MapFrom(src =&amp;gt; src.attributes));
        }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;That's the solution I found to solve my issue, If you have another solution, specially that doesn't involve mapping field by field.&lt;/p&gt;

&lt;p&gt;Obrigado&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__user ltag__user__id__729596"&gt;
    &lt;a href="/mgpaixao" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F729596%2Feea9bd33-293a-4662-ac8a-6f1e6637fe14.jpeg" alt="mgpaixao image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/mgpaixao"&gt;Matheus Paixão&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/mgpaixao"&gt;Gosto de compartilhar conhecimento pois foi assim que eu aprendi a programar. O meu negócio é todo dia saber mais que eu sabia ontem. Pode me chamar, vamos aprender juntos. Prazer =)&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>automapper</category>
      <category>csharp</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Criando uma Web API com .NET Core, EntityFramework Core - Número Cartão de Crédito Aleatório</title>
      <dc:creator>Matheus Paixão</dc:creator>
      <pubDate>Mon, 18 Oct 2021 21:07:29 +0000</pubDate>
      <link>https://forem.com/vaivoa/criando-uma-web-api-com-net-core-entityframework-core-numero-cartao-de-credito-aleatorio-2j0i</link>
      <guid>https://forem.com/vaivoa/criando-uma-web-api-com-net-core-entityframework-core-numero-cartao-de-credito-aleatorio-2j0i</guid>
      <description>&lt;p&gt;Este projeto irá te guiar no Passo a Passo de como criar uma Web API aplicando os conceitos REST em .NET Core, usando Entity Framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pré-requisitos:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Visual Studio 2019 com pacotes de ASP.NET e desenvolvimento web instalados&lt;/li&gt;
&lt;li&gt;.NET Core 3.1 &lt;/li&gt;
&lt;li&gt;Postman&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  O Projeto:
&lt;/h1&gt;

&lt;p&gt;Desenvolver uma aplicação Web API com .NET Core, EntityFramework Core usando arquitetura REST.&lt;/p&gt;

&lt;p&gt;A API deverá gerar números aleatórios para o pedido de um novo cartão de crédito virtual. Cada cartão gerado deve estar associado a um email para identificar a pessoa que está utilizando.&lt;/p&gt;

&lt;h1&gt;
  
  
  EndPoints
&lt;/h1&gt;

&lt;p&gt;GET&lt;br&gt;
Listar todos os números de cartão de crédito indexados a um email fornecido em forma de parâmetro pelo cliente.&lt;/p&gt;

&lt;p&gt;POST&lt;br&gt;
Cadastrar email&lt;/p&gt;

&lt;p&gt;Gerar Número de cartão de crédito aleatório.&lt;/p&gt;

&lt;p&gt;Indexar email criado a Número de cartão gerado.&lt;/p&gt;

&lt;p&gt;Mostrar número de cartão gerado ao final da operação.&lt;/p&gt;
&lt;h1&gt;
  
  
  Relacionamentos
&lt;/h1&gt;

&lt;p&gt;É de extrema importância entender e modelar o projeto em questão antes de avançar para os códigos.&lt;/p&gt;

&lt;p&gt;Esse projeto pode ser feito com apenas uma classe, uma tabela de dados, pois são apenas 2 informações coletadas e o relacionamento exigido permite isso.&lt;/p&gt;
&lt;h2&gt;
  
  
  Classe: ClienteDados
&lt;/h2&gt;

&lt;p&gt;Atributos&lt;/p&gt;

&lt;p&gt;int Id&lt;br&gt;
string Email&lt;br&gt;
string CardNumber&lt;/p&gt;

&lt;p&gt;A chave primária dessa classe é o ID, pois será uma forma de indexar o e-mail a seu respectivo cartão de crédito e também porque o atributo Email não poderia ser chave primária pois chave primária não pode ser repetir e podemos ter vários emails iguais. &lt;/p&gt;

&lt;p&gt;Podemos 1 email com vários cartões de crédito (Email 1 para * muitos Cartões de crédito), porém podemos ter apenas 1 email por cartão de crédito, esse é o relacionamento de dados entre os atributos.&lt;/p&gt;

&lt;p&gt;Agora que compreendemos o que o projeto pede, mãos à obra.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft8b6twkoc3kiz3o3cika.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft8b6twkoc3kiz3o3cika.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Digite o nome do projeto e clique em Proximo.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbuhvzg81umgair341xu1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbuhvzg81umgair341xu1.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Em informações adicionais selecione “.NET Core 3.1 (suporte de longo prazo)” e clique em Criar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh89a5ncj6reexwvf3l3k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh89a5ncj6reexwvf3l3k.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Instalar pacotes de NuGet
&lt;/h1&gt;

&lt;p&gt;Para instalar o suporte EF Core a um projeto, vá em Gerenciar Pacotes de NuGet para a Solução, para instalar os pacotes necessários para esta API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmhcbf4u8ri0vituckekd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmhcbf4u8ri0vituckekd.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Os pacotes a serem instalados são:&lt;br&gt;
Microsoft.EntityFrameworkCore&lt;br&gt;
Microsoft.EntityFrameworkCore.InMemory&lt;br&gt;
Microsoft.EntityFrameworkCore.Design&lt;br&gt;
Microsoft.EntityFrameworkCore.SqlServer&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgdwxhx6uozn0609snwjy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgdwxhx6uozn0609snwjy.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para instalar, digite o nome do pacote em Procurar, selecione o pacote, selecione o nome do seu projeto e clique em instalar.&lt;/p&gt;
&lt;h1&gt;
  
  
  Criar Models e Classes
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8nas92ijuficcsl0clgh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8nas92ijuficcsl0clgh.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O projeto vem com uma classe e um Controller de exemplos, os WeatherForecast.cs. Exclua esses dois arquivos pois não vamos usá-los.&lt;/p&gt;

&lt;p&gt;Agora vamos criar nosso Modelo e nossa Classe ClienteDados.&lt;/p&gt;

&lt;p&gt;Criar uma pasta chamada Models, clicando com o botão direito no nome do projeto clique em Adicionar &amp;gt; Pasta. Nomear de Models. Models é onde armazenamos nossas classes.&lt;/p&gt;

&lt;p&gt;Dentro da pasta Models criar uma Class chamada ClienteDados. Clicando com o botão direito na pasta Models e depois clique em Adicionar &amp;gt; Classe. Nomear ClienteDados e criar.&lt;/p&gt;

&lt;p&gt;Agora declare os atributos que usaremos neste projeto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace APICartaoDeCredito.Models
{
    public class ClienteDados
    {
        public int Id {get; set;}
        public string Email {get; set;}
        public string CardNumber {get; set;}
    }   
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Construir o contexto de Banco de Dados
&lt;/h1&gt;

&lt;p&gt;Criar a pasta de banco de dados chamada DataBase e dentro dessa parte criar a nossa classe de contexto a ApiContext.cs. Essa classe é a responsável principal pela comunicação com a Entity Framework Core&lt;/p&gt;

&lt;p&gt;Dentro dessa classe, vamos criar o nosso InMemory Data Base, que será nosso banco de dados em memória.&lt;/p&gt;

&lt;p&gt;Carregue os pacotes que usaremos nessa classe.&lt;br&gt;
using Microsoft.EntityFrameworkCore;&lt;br&gt;
using ApiCartaoDeCredito.Models;&lt;/p&gt;

&lt;p&gt;Olhando o Código pronto abaixo, temos ClientesDb que será nossa propriedade DbSet de acesso ao banco de dados.&lt;/p&gt;

&lt;p&gt;Dentro da classe ApiContex seria onde podemos definir regras de relacionamento, definir quem é chave primária entre outras coisas relacionadas a Banco de Dados, mas não será necessário nesse projeto.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ApiContex : DbContext

    {
        public ApiContex(DbContextOptions&amp;lt;ApiContex&amp;gt; options) : base(options)
        {

        }
        public DbSet&amp;lt;ClienteDados&amp;gt; ClientesDb { get; set; }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Criar registro do ApiContex
&lt;/h1&gt;

&lt;p&gt;No projeto tem uma classe que foi criada com a criação do projeto que precisamos registrar o banco de dados que criamos. Abra a classe Startup.cs e procure o método ConfigureServices() e adicione essa linha de código.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext&amp;lt;ApiContex&amp;gt;(opt =&amp;gt;
            opt.UseInMemoryDatabase("ClienteDb"));

            services.AddControllers();
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Criar Controllers
&lt;/h1&gt;

&lt;p&gt;Clicar com botão direito na pasta Controllers &amp;gt; Adicionar &amp;gt; Novo Item Scaffold. Na janela que abrir selecione Controlador API com ações, usando o Entity Framework, depois clique em Adicionar. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmdxk30m27oy0whzpq81.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmdxk30m27oy0whzpq81.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Na janela que abrir, temos que escolher para qual classe estamos criando nossa Controller. Selecione ClienteDados. Logo abaixo tem a opção da classe de contexto de dados, que é a classe ApiContext, que criamos para ser nossa classe de controle do banco de dados.&lt;br&gt;
Escolher o nome do Controller, mas de default Visual Studio já nos fornece o nome apropriado.&lt;br&gt;
Agora clique em Adicionar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhzd2rrifgbv00ax14t2z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhzd2rrifgbv00ax14t2z.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Usar o Scaffold para criar os Controllers, nos dá o benefício de que eles já criam automaticamente os métodos REST, que são os vistos na imagem abaixo. GET PUT POST e DELETE.&lt;/p&gt;

&lt;p&gt;GET: Método onde vamos extrair informações do banco de dados e exibi-los.&lt;br&gt;
PUT: Método que altera informações do banco de dados&lt;br&gt;
POST: Método para adicionar informações no banco de dados.&lt;br&gt;
DELETE: Método para deletar informações do banco de dados.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsp4cjr5lb8yn7comgejp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsp4cjr5lb8yn7comgejp.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lembrando das exigências que vimos anteriormente, neste projeto usaremos apenas o método GET e POST.&lt;/p&gt;
&lt;h1&gt;
  
  
  Método POST
&lt;/h1&gt;

&lt;p&gt;Id - Gerada automaticamente (Chave primária, gerada automaticamente pelo sistema)&lt;br&gt;
Email - Adicionado pelo usuário.&lt;br&gt;
CardNumber - Gerado automaticamente de forma aleatória.&lt;/p&gt;

&lt;p&gt;No método POST adicione as linhas de código abaixo.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    public async Task&amp;lt;ActionResult&amp;lt;ClienteDados&amp;gt;&amp;gt; PostClienteDados(ClienteDados clienteDados)
    {        
        Random rnd = new Random();
        int ccn1 = rnd.Next(1000, 9999);
        int ccn2 = rnd.Next(1000, 9999);
        int ccn3 = rnd.Next(1000, 9999);
        int ccn4 = rnd.Next(1000, 9999);
        clienteDados.CardNumber = $"{ccn1} {ccn2} {ccn3} {ccn4}";

        _context.ClientesDb.Add(clienteDados);  
            await _context.SaveChangesAsync();
            return CreatedAtAction("PostClienteDados", new { clienteDados = clienteDados.CardNumber }, clienteDados.CardNumber);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Random rnd - Para gerarmos números aleatórios crie uma instância da classe Random para acessarmos as funções desta classe.&lt;br&gt;
Como não foi especificado no nosso projeto a bandeira do cartão de crédito ou quantos números teria, então decidi que neste projeto serão 4 blocos de 4 números aleatórios. &lt;/p&gt;

&lt;p&gt;int ccn1/2/3/4 - Estas 4 variáveis são os 4 blocos de 4 números.&lt;br&gt;
Para gerarmos de fato os números aleatórios precisamos chamar a função next da classe Random, através da instância rnd.  rnd.Next. Dentro da função Next definimos o range de números que queremos. &lt;/p&gt;

&lt;p&gt;rnd.Next(1000, 9999);&lt;/p&gt;

&lt;p&gt;Agora que temos os números criados, precisamos armazená-los dentro do nosso atributo que representa o número do cartão de crédito no nosso banco de dados, o CardNumber.&lt;br&gt;
Precisamos então concatenar as 4 variáveis ccn para armazená-las em CardNumber.&lt;/p&gt;

&lt;p&gt;clienteDados.CardNumber = $"{ccn1} {ccn2} {ccn3} {ccn4}"&lt;/p&gt;

&lt;p&gt;Aqui usamos a nossa instância (clienteDados) da classe (ClienteDados) do projeto para acessar o atributo CardNumber.&lt;/p&gt;

&lt;p&gt;Bom, já temos nosso número aleatório de cartão de crédito, agora precisamos armazenar tudo no banco de dados.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;_context.ClientesDb.Add(clienteDados);
        await _context.SaveChangesAsync();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Usamos a nossa instância do nosso contexto do banco de dados _context.ClientesDb para acessar o banco de dados e executar a função .Add para ADICIONAR informação da classe ClienteDados.&lt;br&gt;
E toda vez que adicionamos algo ao banco de dados precisamos salvar através da função .SaveChangesAsync();&lt;/p&gt;

&lt;p&gt;O projeto pede que após o usuário inserir o seu email, o sistema vai retornar apenas o número de cartão de crédito. Para isso vamos usar o código abaixo.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;            return CreatedAtAction("PostClienteDados", new { clienteDados = clienteDados.CardNumber }, clienteDados.CardNumber);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Se atentar para o método que está sendo chamado, que é o PostClienteDados e para o que vem após de new, pois deve ser o mesmo parâmetro da função PostClienteDados. Para filtrar e mostrar apenas CardNumber é necessário que especifique clienteDados.CardNumber.&lt;/p&gt;
&lt;h1&gt;
  
  
  Método GET
&lt;/h1&gt;

&lt;p&gt;O projeto pede que quando o usuário insere o seu e-mail como parâmetro, retorne em ordem de criação apenas os números de cartão de crédito.&lt;/p&gt;

&lt;p&gt;Antes do método GET precisamos criar um TYPE, para ter acesso aos atributos da nossa classe.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    public class NEW_TYPE
    {
        public string Cartao { get; set; }
    };

     // GET: api/ClienteDados/”inserir email aqui”
    [HttpGet("{email}")]
        public async Task&amp;lt;ActionResult&amp;lt;IEnumerable&amp;lt;ClienteDados&amp;gt;&amp;gt;&amp;gt; GetEmail(string email)
        {
            var list = from a in _context.ClientesDb
                        where a.Email.Equals(email)
                        select new NEW_TYPE
                        {
                            Cartao = a.CardNumber
                        };
            var CartoesdeCredito = await list.ToListAsync();
            return Ok(CartoesdeCredito);
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Repare que agora o [HttpGet] está com um complemento, que é o parâmetro que o usuário vai inserir [HttpGet(“{email}”).&lt;/p&gt;

&lt;p&gt;Como estamos recebendo um parâmetro, precisamos receber em uma variável, por isso temos (string email) após a declaração do método.&lt;/p&gt;

&lt;p&gt;public async Task&amp;gt;&amp;gt; GetEmail&lt;/p&gt;

&lt;p&gt;Crie uma instância do nosso banco de dados.&lt;/p&gt;

&lt;p&gt;var list = from a in _context.ClientesDb&lt;/p&gt;

&lt;p&gt;Crie uma estrutura de consulta com filtro.&lt;/p&gt;

&lt;p&gt;var list = from a in _context.ClientesDb&lt;br&gt;
                       where a.Email.Equals(email)&lt;br&gt;
                       select new NEW_TYPE&lt;br&gt;
                       {&lt;br&gt;
                           Cartao = a.CardNumber&lt;br&gt;
                       };&lt;/p&gt;

&lt;p&gt;Agora que temos a informação filtrada, vamos adicionar a uma lista.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var CartoesdeCredito = await list.ToListAsync();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;E retornaremos a lista para o usuário.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return Ok(CartoesdeCredito);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  Roteamento
&lt;/h1&gt;

&lt;p&gt;Antes de testarmos nossa API precisamos atualizar o arquivo launchSettings.json adicionando a rota do URL que desejamos acessar nossa API&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; "profiles": {
"IIS Express": {
  "commandName": "IISExpress",
  "launchBrowser": true,
  "launchUrl": "api/ClienteDados",
  "environmentVariables": {
    "ASPNETCORE_ENVIRONMENT": "Development"
  }
},
"APICartaoDeCredito": {
  "commandName": "Project",
  "launchBrowser": true,
  "launchUrl": "api/ClienteDados",
  "applicationUrl": "https://localhost:5001;http://localhost:5000",
  "environmentVariables": {
    "ASPNETCORE_ENVIRONMENT": "Development"
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Atualize o parâmetro “launchUrl” e coloque o caminho desejado, no nosso caso vai ser o api/ClienteDados.&lt;/p&gt;

&lt;p&gt;Na parte superior desse arquivo você pode escolher a porta do localhost a ser usada.&lt;/p&gt;

&lt;p&gt;Caso você queira personalizar a URL, você deve se atentar para mudar o roteamento no Controller também, pois ele vem como de Defaut roteando para api/nome da classe e se você inicializar com outro nome, deve especificar no Controller.&lt;/p&gt;
&lt;h1&gt;
  
  
  Postman
&lt;/h1&gt;

&lt;p&gt;Por conveniência, escolhi a plataforma Postman para realizar os testes do projeto, existem outras formas e plataformas para testar. &lt;/p&gt;

&lt;p&gt;Ao abrir o Postman clique em Create New para criar um novo projeto, e na próxima janela que abrir escolha HTTP Request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5oqh9qjateiozqevlruk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5oqh9qjateiozqevlruk.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Na próxima janela que abrir clique em New Collection, dê um nome pra ela, e clique em Create, na próxima janela clique em Save e pronto, projeto criado.&lt;/p&gt;

&lt;p&gt;De volta ao Visual Studio, na barra superior de ferramentas, no símbolo de PLAY para executar nosso projeto.&lt;/p&gt;

&lt;p&gt;O seu navegador padrão deverá abrir no endereço que roteamos no projeto. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/mgpaixao" rel="noopener noreferrer"&gt;https://localhost:44340/api/ClienteDados&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lembrando que a porta do URL pode ser diferente. &lt;/p&gt;

&lt;p&gt;Pegue esse link e cole no Postman. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Freyshzox4o8goba5xmos.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Freyshzox4o8goba5xmos.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Você deve receber Status 200 OK que significa que a requisição retornou com sucesso.&lt;/p&gt;

&lt;p&gt;Como não demos nenhuma entrada até esse momento, ele retornou tudo em branco.&lt;/p&gt;
&lt;h1&gt;
  
  
  Endpoint 1
&lt;/h1&gt;

&lt;p&gt;Para realizarmos a primeira entrada, clique no Dropdown menu onde está escrito GET e aparecerá todos os verbos disponíveis de Http para você escolher.&lt;/p&gt;

&lt;p&gt;Clique em Post para acessarmos o método Post do nosso projeto. &lt;br&gt;
Clique em Body, depois em raw, depois troque o método de entrada de Text para JSON.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foz4z2l0pom4535n1u3in.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foz4z2l0pom4535n1u3in.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O código para darmos a primeira entrada no banco de dados, inclui apenas Email, pois as outras informações são geradas automaticamente.&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
    "Email": "digite o email aqui"&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Após digitar o email desejado clique em Send para executar o código e o sistema retornará 200 OK e o número de cartão de crédito gerado.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvekunwn3dr8kdsugfsoh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvekunwn3dr8kdsugfsoh.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para fazer o teste do segundo Endpoint, crie vários números para o mesmo email.&lt;/p&gt;
&lt;h1&gt;
  
  
  Endpoint 2
&lt;/h1&gt;

&lt;p&gt;Mude o verbo Http no Postman para GET novamente.&lt;br&gt;
E no caminho URL adicione o email cadastrado e clique Send novamente.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/mgpaixao" rel="noopener noreferrer"&gt;https://localhost:44340/api/ClienteDados/EmailCadastradoAQUI&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F80io2o6lmy0jnydaah2c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F80io2o6lmy0jnydaah2c.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E o sistema retornou os cartões de crédito que pertencem ao usuário do email cadastrado, e listou-os em ordem de criação.&lt;/p&gt;

&lt;p&gt;É possível testar o método GET no browser também, digitando o caminho  do URL+email &lt;a href="https://github.com/mgpaixao" rel="noopener noreferrer"&gt;https://localhost:44340/api/ClienteDados/emailcadastrado&lt;/a&gt; e ele dará o mesmo retorno que no Postman.&lt;/p&gt;

&lt;p&gt;Com isso concluímos este projeto. &lt;a href="https://github.com/mgpaixao/APICartaoDeCredito" rel="noopener noreferrer"&gt;https://github.com/mgpaixao/APICartaoDeCredito&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Obrigado&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__user ltag__user__id__729596"&gt;
    &lt;a href="/mgpaixao" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F729596%2Feea9bd33-293a-4662-ac8a-6f1e6637fe14.jpeg" alt="mgpaixao image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/mgpaixao"&gt;Matheus Paixão&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/mgpaixao"&gt;Gosto de compartilhar conhecimento pois foi assim que eu aprendi a programar. O meu negócio é todo dia saber mais que eu sabia ontem. Pode me chamar, vamos aprender juntos. Prazer =)&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcz1xbk1xbzlg8kyfy6ri.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcz1xbk1xbzlg8kyfy6ri.png" alt="Linha Horizontal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Disclaimer
&lt;/h1&gt;

&lt;p&gt;A VaiVoa incentiva seus Desenvolvedores em seu processo de crescimento e aceleração técnica. Os artigos publicados não traduzem a opinião da VaiVoa. A publicação obedece ao propósito de estimular o debate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1wmziqv74ghhgyi9p0om.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1wmziqv74ghhgyi9p0om.png" alt="logo vaivoa"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>beginners</category>
      <category>vaivoa</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
