-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFundamentos ASP.NET 6 - Balta
5022 lines (3667 loc) · 187 KB
/
Fundamentos ASP.NET 6 - Balta
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Fundamentos ASP.NET 6 - Balta
-----------------------------
# Pasta de projetos do curso
https://github.com/balta-io/2811
https://dotnettutorials.net/course/asp-net-core-web-api-tutorials/
Introdução e Minimal APIs
-------------------------
Aula 2. Rodando sua primeira App
--------------------------------
. Acesse a pasta raiz de projetos e execute o comando abaixo:
dotnet new web -o minhaApp -n MinhaApp -f net6.0
. Acesse a pasta do projeto recém criado e execute o comando abaixo:
dotnet run
. Através do comando acima a aplicação web é levantada e o servidor web fica
escutando a URL 127.0.0.1 ou "localhost" na porta "xxxx".
. A porta no "dotnet 6" muda aleatoriamente, neste caso precisamos observar o loga
da aplicação, logo após o comando "dotnet run", para ver a porta que foi escolhida.
. Já no "dotnet 5" pra baixo, a porta é sempre "5001"
. Acesse o navegador e acesse a URL abaixo:
http://localhost:[porta]
. Se tudo der certo o navegador apresentará a mensagem "Hello World!"
Aula 3. Entendendo os verbos HTTP
---------------------------------
https://www.tutorialspoint.com/http/index.htm
. Principais métodos do protocolo HTTP
. GET - Obter os dados de um recurso.
. POST - Criar um novo recurso.
. PUT - Alterar dados de um determinado recurso.
. PATCH - Atualizar parcialmente um determinado rcurso.
. DELETE - Excluir um determinado recurso.
. Exemplo de rotas:
http://site.com.br/clientes (GET, POST)
http://site.com.br/clientes/57 (GET, DELETE)
Aula 4. HTTP Status Code
------------------------
. Uma requisição é dividida em duas partes: Headers/Cabeçalho e Body/Corpo
. Headers - Os cabeçalhos HTTP permitem que o cliente e o servidor passem informações
adicionais com a solicitação ou a resposta HTTP. Um cabeçalho de solicitação é
composto por seu nome case-insensitive (não diferencia letras maiúsculas e minúsculas),
seguido por dois pontos ':' e pelo seu valor (sem quebras de linha).
Espaços em branco antes do valor serão ignorados.
Accept-Charset: O cabeçalho de requisição HTTP Accept-Charset anuncia quais character encodings o
cliente entende.
Por exemplo: Accept-Charset: iso-8859-1
Accept-Charset: utf-8, iso-8859-1;q=0.5
Accept-Charset: utf-8, iso-8859-1;q=0.5, *;q=0.1
Accept-Encoding: indica qual codificação de conteúdo, usualmente um algoritmo de compressão, o cliente
está apto a entender.
Por exemplo: Accept-Encoding: gzip
Accept-Encoding: compress
Accept-Encoding: deflate
Accept-Encoding: br
Accept-Encoding: identity
Accept-Encoding: *
// Múltiplos algoritmos, com pesos baseados na sintaxe de quality value (en-US):
Accept-Encoding: deflate, gzip;q=1.0, *;q=0.5
Accept-Language: Determina qual linguagem é entendida pelo cliente e qual a sua região de preferência.
Por exemplo, Accept-Language: pt-br, en;q=0.9,*;q=0.8 diz que preferimos que o conteúdo
esteja em português do Brasil ou inglês, caso a primeira opção não esteja disponível.
Allow: Lista quais métodos HTTP são aceitos pelo servidor para o recurso acessado.
Essa lista pode variar de acordo com a página que estamos acessando.
Por exemplo, Allow: GET, POST, HEAD diz que a página acessada aceita apenas esses métodos.
Authorization O cabeçalho de requisição HTTP Authorization contém as credenciais para autenticar o agente de
usuário com o servidor, geralmente o servidor responderá com um status 401 Unauthorized se não
for possível fazer a autenticação, e com o cabeçalho WWW-Authenticate.
Sintaxe:
Authorization: <tipo> <credenciais>
Por exemplo: Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
Content-Language: É a forma do servidor dizer ao cliente quais linguagens estão disponíveis para o recurso atual.
Por exemplo, Content-Language: pt-br determina que apenas a linguagem português do
Brasil está disponível.
A partir de Content-Language o cliente sabe como escolher o valor para Accept-Language.
Cookie: Contém o valor de um Cookie HTTP e é a forma do navegador enviar esse dado de volta
ao servidor a cada requisição.
Uma vez que o HTTP é stateless, algumas vezes precisamos recorrer a esse mecanismo
para saber se um usuário permanece logado ou tem sessão ativa, por exemplo.
Por exemplo, Cookie: PHPSESSID=298zf09hf012fh2; é o id da sessão criada pelo PHP.
Através dela, o PHP pode determinar, no servidor, se duas requisições partiram de um mesmo computador.
Content-Type: Indica qual o tipo de mídia de um recurso.
A partir dele o navegador pode determinar se o conteúdo recebido na resposta é uma
página HTML, imagem, áudio, vídeo, etc.
Por exemplo, Content-Type: text/html; charset=utf-8 indica que receberemos uma página em
HTML na codificação de caracteres UTF-8.
Expect
From
Host
If-Match
If-Modified-Since
If-None-Match
If-Range
If-Unmodified-Since
Max-Forwards
Proxy-Authorization
Range
Referer
TE
User-Agent: Contém uma string de identificação da aplicação, sistema operacional e distribuidor
do software que fez a requisição.
Por exemplo, User-Agent: Googlebot/2.1 (+http://www.google.com/bot.html) diz que o Google quem
disparou a requisição a fim de coletar dados para o seu mecanismo de busca.
. Exemplos de Headers de requisição:
GET /hello.htm HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
Host: www.tutorialspoint.com
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
------------------------------------------------------------------
POST /cgi-bin/process.cgi HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
Host: www.tutorialspoint.com
Content-Type: application/x-www-form-urlencoded
Content-Length: length
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
licenseID=string&content=string&/paramsXML=string
------------------------------------------------------------------
POST /cgi-bin/process.cgi HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
Host: www.tutorialspoint.com
Content-Type: text/xml; charset=utf-8
Content-Length: length
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://clearforest.com/">string</string>
. Body
Ou "Request Body", ou corpo da requisição, é onde geralmente enviamos dados que queremos gravar no servidor.
Não é muito utilizado em requisições do tipo GET, mas sim nas do tipo POST e PUT.
É no corpo da requisição onde você envia dados de um formulário de cadastro em seu site, por exemplo.
. Status Code Resumido:
(100-199) - Respostas de informação
(200-299) - Respostas de sucesso
(300-399) - Redirecionamentos
(400-499) - Erros do cliente
(500-599) - Erros do servidor
. Status Code Detalhadamente: Todos que estão marcados com "*" são os que mais ocorrem.
. Respostas informativas:
*100 Continue - Essa resposta provisória indica que tudo ocorreu bem até agora e que o
cliente deve continuar com a requisição ou ignorar se já concluiu o que gostaria.
101 Switching Protocol - Esse código é enviado em resposta a um cabeçalho de solicitação Upgrade (en-US) pelo
cliente, e indica o protocolo a que o servidor está alternando.
102 Processing (WebDAV (en-US)) - Este código indica que o servidor recebeu e está processando a requisição, mas nenhuma
resposta está disponível ainda.
103 Early Hints - Este código tem principalmente o objetivo de ser utilizado com o cabeçalho Link,
indicando que o agente deve iniciar a pré-carregar (en-US) recursos enquanto o servidor prepara uma resposta.
. Respostas de sucesso:
GET: O recurso foi buscado e transmitido no corpo da mensagem.
HEAD: Os cabeçalhos da entidade estão no corpo da mensagem.
PUT ou POST: O recurso descrevendo o resultado da ação é transmitido no corpo da mensagem.
TRACE: O corpo da mensagem contém a mensagem de requisição recebida pelo servidor.
**200 OK - Estas requisição foi bem sucedida. O significado do sucesso varia de acordo com o método HTTP:
**201 Created - A requisição foi bem sucedida e um novo recurso foi criado como resultado. Esta é uma tipica resposta
enviada após uma requisição POST.
*202 Accepted - A requisição foi recebida mas nenhuma ação foi tomada sobre ela. Isto é uma requisição não-comprometedora,
o que significa que não há nenhuma maneira no HTTP para enviar uma resposta assíncrona indicando o resultado
do processamento da solicitação. Isto é indicado para casos onde outro processo ou servidor lida com a requisição,
ou para processamento em lote.
*203 Non-Authoritative Information - Esse código de resposta significa que o conjunto de meta-informações retornadas não é o conjunto exato
disponível no servidor de origem, mas coletado de uma cópia local ou de terceiros. Exceto essa condição,
a resposta de 200 OK deve ser preferida em vez dessa resposta.
*204 No Content - Não há conteúdo para enviar para esta solicitação, mas os cabeçalhos podem ser úteis. O user-agent pode atualizar
seus cabeçalhos em cache para este recurso com os novos.
205 Reset Content - Esta requisição é enviada após realizanda a solicitação para informar ao user agent redefinir a visualização do
documento que enviou essa solicitação.
206 Partial Content - Esta resposta é usada por causa do cabeçalho de intervalo enviado pelo cliente para separar o download em vários fluxos.
207 Multi-Status (WebDAV (en-US)) - Uma resposta Multi-Status transmite informações sobre vários recursos em situações em que vários códigos de status
podem ser apropriados.
208 Multi-Status (WebDAV (en-US)) - Usado dentro de um elemento de resposta <dav:propstat> para evitar enumerar os membros internos de várias ligações
à mesma coleção repetidamente.
226 IM Used (HTTP Delta encoding) - O servidor cumpriu uma solicitação GET para o recurso e a resposta é uma representação do resultado de uma ou mais
manipulações de instância aplicadas à instância atual.
. Mensagens de redirecionamento:
300 Multiple Choice - A requisição tem mais de uma resposta possível. User-agent ou o user deve escolher uma delas. Não há maneira
padrão para escolher uma das respostas.
*301 Moved Permanently - Esse código de resposta significa que a URI do recurso requerido mudou. Provavelmente, a nova URI será
especificada na resposta.
302 Found - Esse código de resposta significa que a URI do recurso requerido foi mudada temporariamente. Novas mudanças na
URI poderão ser feitas no futuro. Portanto, a mesma URI deve ser usada pelo cliente em requisições futuras.
303 See Other - O servidor manda essa resposta para instruir ao cliente buscar o recurso requisitado em outra URI com uma requisição GET.
304 Not Modified - Essa resposta é usada para questões de cache. Diz ao cliente que a resposta não foi modificada. Portanto, o cliente
pode usar a mesma versão em cache da resposta.
*305 Use Proxy Deprecated - Foi definida em uma versão anterior da especificação HTTP para indicar que uma resposta deve ser acessada por um proxy.
Foi depreciada por questões de segurança em respeito a configuração em banda de um proxy.
306 unused Deprecated - Esse código de resposta não é mais utilizado, encontra-se reservado. Foi usado numa versão anterior da especificação HTTP 1.1.
307 Temporary Redirect - O servidor mandou essa resposta direcionando o cliente a buscar o recurso requisitado em outra URI com o mesmo método
que foi utilizado na requisição original. Tem a mesma semântica do código 302 Found, com a exceção de que o user-agent
não deve mudar o método HTTP utilizado: se um POST foi utilizado na primeira requisição, um POST deve ser utilizado na segunda.
308 Permanent Redirect - Esse código significa que o recurso agora está permanentemente localizado em outra URI, especificada pelo cabeçalho
de resposta Location. Tem a mesma semântica do código de resposta HTTP 301 Moved Permanently com a exceção de que o user-agent
não deve mudar o método HTTP utilizado: se um POST foi utilizado na primeira requisição, um POST deve ser utilizado na segunda.
. Respostas de erro do Cliente:
**400 Bad Request - Essa resposta significa que o servidor não entendeu a requisição pois está com uma sintaxe inválida.
**401 Unauthorized - Embora o padrão HTTP especifique "unauthorized", semanticamente, essa resposta significa "unauthenticated". Ou seja,
o cliente deve se autenticar para obter a resposta solicitada.
*402 Payment Required Experimental - Este código de resposta está reservado para uso futuro. O objetivo inicial da criação deste código era usá-lo para sistemas
digitais de pagamento porém ele não está sendo usado atualmente.
*403 Forbidden - O cliente não tem direitos de acesso ao conteúdo portanto o servidor está rejeitando dar a resposta. Diferente do
código 401, aqui a identidade do cliente é conhecida.
**404 Not Found - O servidor não pode encontrar o recurso solicitado. Este código de resposta talvez seja o mais famoso devido à frequência
com que acontece na web.
*405 Method Not Allowed - O método de solicitação é conhecido pelo servidor, mas foi desativado e não pode ser usado.
406 Not Acceptable - Essa resposta é enviada quando o servidor da Web após realizar a negociação de conteúdo orientada pelo servidor,
não encontra nenhum conteúdo seguindo os critérios fornecidos pelo agente do usuário.
407 Proxy Authentication Required - Semelhante ao 401 porem é necessário que a autenticação seja feita por um proxy.
408 Request Timeout - Esta resposta é enviada por alguns servidores em uma conexão ociosa, mesmo sem qualquer requisição prévia pelo cliente. Ela
significa que o servidor gostaria de derrubar esta conexão em desuso. Esta resposta é muito usada já que alguns
navegadores, como Chrome, Firefox 27+, ou IE9, usam mecanismos HTTP de pré-conexão para acelerar a navegação. Note também
que alguns servidores meramente derrubam a conexão sem enviar esta mensagem.
409 Conflict - Esta resposta será enviada quando uma requisição conflitar com o estado atual do servidor.
410 Gone - Esta resposta será enviada quando o conteúdo requisitado foi permanentemente deletado do servidor, sem nenhum endereço de
redirecionamento. É experado que clientes removam seus caches e links para o recurso. A especificação HTTP espera que este
código de status seja usado para "serviços promocionais de tempo limitado". APIs não devem se sentir obrigadas a indicar que
recursos foram removidos com este código de status.
411 Length Required - O servidor rejeitou a requisição porque o campo Content-Length do cabeçalho não está definido e o servidor o requer.
412 Precondition Failed - O cliente indicou nos seus cabeçalhos pré-condições que o servidor não atende.
413 Payload Too Large - A entidade requisição é maior do que os limites definidos pelo servidor; o servidor pode fechar a conexão ou retornar um
campo de cabeçalho Retry-After.
414 URI Too Long - A URI requisitada pelo cliente é maior do que o servidor aceita para interpretar.
415 Unsupported Media Type - O formato de mídia dos dados requisitados não é suportado pelo servidor, então o servidor rejeita a requisição.
416 Requested Range Not Satisfiable - O trecho especificado pelo campo Range do cabeçalho na requisição não pode ser preenchido; é possível que o trecho esteja fora
do tamanho dos dados da URI alvo.
417 Expectation Failed - Este código de resposta significa que a expectativa indicada pelo campo Expect do cabeçalho da requisição não pode ser satisfeita
pelo servidor.
418 I'm a teapot - O servidor recusa a tentativa de coar café num bule de chá.
421 Misdirected Request - A requisição foi direcionada a um servidor inapto a produzir a resposta. Pode ser enviado por um servidor que não está
configurado para produzir respostas para a combinação de esquema ("scheme") e autoridade inclusas na URI da requisição.
422 Unprocessable Entity (WebDAV (en-US)) - A requisição está bem formada mas inabilitada para ser seguida devido a erros semânticos.
423 Locked (WebDAV (en-US)) - O recurso sendo acessado está travado.
424 Failed Dependency (WebDAV (en-US)) - A requisição falhou devido a falha em requisição prévia.
425 Too Early - Indica que o servidor não está disposto a arriscar processar uma requisição que pode ser refeita.
426 Upgrade Required - O servidor se recusa a executar a requisição usando o protocolo corrente mas estará pronto a fazê-lo após o cliente atualizar
para um protocolo diferente. O servidor envia um cabeçalho Upgrade (en-US) numa resposta 426 para indicar o(s) protocolo(s) requeridos.
428 Precondition Required - O servidor de origem requer que a resposta seja condicional. Feito para prevenir o problema da 'atualização perdida', onde um
cliente pega o estado de um recurso (GET) , modifica-o, e o põe de volta no servidor (PUT), enquanto um terceiro modificou o
estado no servidor, levando a um conflito.
429 Too Many Requests - O usuário enviou muitas requisições num dado tempo ("limitação de frequência").
431 Request Header Fields Too Large - O servidor não quer processar a requisição porque os campos de cabeçalho são muito grandes. A requisição PODE ser submetida
novemente depois de reduzir o tamanho dos campos de cabeçalho.
451 Unavailable For Legal Reasons - O usuário requisitou um recurso ilegal, tal como uma página censurada por um governo.
. Respostas de erro do Servidor:
**500 Internal Server Error - O servidor encontrou uma situação com a qual não sabe lidar.
501 Not Implemented - O método da requisição não é suportado pelo servidor e não pode ser manipulado. Os únicos métodos exigidos que servidores
suportem (e portanto não devem retornar este código) são GET e HEAD.
502 Bad Gateway - Esta resposta de erro significa que o servidor, ao trabalhar como um gateway a fim de obter uma resposta necessária
para manipular a requisição, obteve uma resposta inválida.
*503 Service Unavailable - O servidor não está pronto para manipular a requisição. Causas comuns são um servidor em manutenção ou sobrecarregado.
Note que junto a esta resposta, uma página amigável explicando o problema deveria ser enviada. Estas respostas devem
ser usadas para condições temporárias e o cabeçalho HTTP Retry-After: deverá, se possível, conter o tempo estimado
para recuperação do serviço. O webmaster deve também tomar cuidado com os cabeçalhos relacionados com o cache que são
enviados com esta resposta, já que estas respostas de condições temporárias normalmente não deveriam ser postas em cache.
504 Gateway Timeout - Esta resposta de erro é dada quando o servidor está atuando como um gateway e não obtém uma resposta a tempo.
505 HTTP Version Not Supported - A versão HTTP usada na requisição não é suportada pelo servidor.
506 Variant Also Negotiates - O servidor tem um erro de configuração interno: a negociação transparente de conteúdo para a requisição resulta em
uma referência circular.
507 Insufficient Storage - O servidor tem um erro interno de configuração: o recurso variante escolhido está configurado para entrar em negociação
transparente de conteúdo com ele mesmo, e portanto não é uma ponta válida no processo de negociação.
508 Loop Detected (WebDAV (en-US)) - O servidor detectou um looping infinito ao processar a requisição.
510 Not Extended - Exigem-se extensões posteriores à requisição para o servidor atendê-la.
511 Network Authentication Required - O código de status 511 indica que o cliente precisa se autenticar para ganhar acesso à rede.
. A URL abaixo apresenta detalhadamento o funcionamento das chamadas HTTP no POSTMAN:
https://learning.postman.com/docs/sending-requests/requests/
Aula 5. Como funciona um App ASP.NET
-------------------------------------
. No .Net 6 a execução começa pela classe "Program.cs"
// Construi a aplicação
var builder = WebAppication.CreateBuilder(args);
var app = builder.Build();
// Mapea a rota para ser chamada na linha debaixo
app.MapGet("/", () => "Hello World!");
// Executa a aplicação e fica escutando e respondendo alguma chamada na porta do projeto
app.Run();
. No .Net 6 a classe "Startup.cs" foi suprimida
. No .Net 6 a estrutura da classe "Program.cs" foi alterada deixando equivalente ao apresentado acima.
Aula 6. Mapeando uma Requisição
-------------------------------
. Na classe "Program.cs" temos a rota abaixo:
app.MapGet("/", () => "Hello World!");
|
+----> Função anônima
. A chamada acima resultará na URL:
https://localhost:[porta]/
Aula 7. Funções Anônimas
------------------------
. Na classe "Program.cs" temos a rota abaixo:
app.MapGet("/", () => "Hello World!");
|
+----> Função anônima
. Poderiamos construir a mesma função da seguinte forma:
app.MapGet( "/", () => {
return "Hello World!";
});
Aula 8. Parâmetros
------------------
. Na classe "Program.cs" altere a rota colocando o "StatusCode" com o objeto "Results"
..
app.MapGet( "/", () => {
return Results.Ok("Hello World"); // Linha alterada
});
...
. Inclua nova rota abaixo:
...
app.MapGet( "/{nome}", (string nome) => { // Linha alterada
return Results.Ok($"Hello World {nome}"); // Linha alterada
});
...
...
app.MapGet( "/nome/{nome}", (string nome) => { // Linha alterada
return Results.Ok($"Hello World {nome}"); // Linha alterada
});
...
. Acesse o Postman e execute as URLs abaixo:
https://localhost:[porta]/
https://localhost:[porta]/Marco
https://localhost:[porta]/nome/Marco
Aula 9. Serialização JSON
-------------------------
. Inclua as linhas abaixo na classe "Program.cs":
...
// Linha inserida abaixo
app.MapPost("/", (User user) => {
return Results.Ok( user );
});
app.Run();
// Classe inserida
public class User{
public int Id { get; set; }
public string Username { get; set; }
}
. Acesse o Postman e execute a URL abaixo:
Method: POST
Url: https:localhost:[porta]/
Body.raw:
{
"id": 1,
"username": "MARCO"
}
Type: JSON
. Observe: Se o valor inteiro 1 chegará com sucesso ao backend.
Se os nomes propriedade minisculos serão convertidos automaticamente para dentro da classe.
MVC
---
Aula 10. Iniciando o Projeto
----------------------------
. Acesse a pasta de projetos e execute o comando abaixo:
dotnet new web -o Todo -f net6.0
. Acesse o VSCode na pasta do projeto criado.
. Cria a classe abaixo dentro da pasta "Model":
namespace Todo.Models
{
public class TodoModel
{
public int Id { get; set; }
public string? Title { get; set; }
public bool Done { get; set; }
public DateTime CreatedAt { get; set; }
}
}
Aula 11. Configurando o EF
--------------------------
. ACesse a pasta raiz do projeto e execute os comandos abaixo:
dotnet add package Microsoft.EntityFrameworkCore.Sqlite --version 6.0.8
dotnet add package Microsoft.EntityFrameworkCore.Design --version 6.0.8
.
. Crie a pasta "Data" e dentro dela crie a classe abaixo:
using Microsoft.EntityFrameworkCore;
using Todo.Models;
namespace Todo.Data
{
public class AppDbContext : DbContext
{
public DbSet<TodoModel> Todos { get; set; }
// public DbSet<TodoModel> Todos => Set<TodoModel>();
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlite("DataSource=app.db;Cache=Shared");
}
}
. A forma como vinhamos trabalhando até o .NET 5, permitia a declaração dos contextos "public DbSet<TodoModel> ..."
na classe de contexto (AppDbContext) da forma abaixo:
public DbSet<TodoModel> Todos { get; set; }
. Já da versão .NET 6 em diante, ao fazer da forma acima, o compilador reclama/avisa "Que o objeto poderá ficar com um
valor nulo. Para resolver essa situação, temos que declarar de uma das duas formas os "DBSets" como abaixo:
// Até .NET 5
public DbSet<TodoModel> Todos { get; set; }
ou
// A partir do .NET 6
public DbSet<TodoModel> Todos => Set<TodoModel>();
. Declarando DbSets no .NET 6 com a sintaxe do .NET 5, teremos muito trabalho para adaptar todo os códigos das classes que for utilizar o DBSet.
Devemos prepará-los para receber valores nulos:
public DbSet<TodoModel>? Todos { get; set; }
. Observe que devemos utilizar o operador (?) para informar ao compilador que o objeto poderá ser nulo. Resolve num primeiro
momento para a classe de Contexto (AppDbContext), porém nas classes seguintes que forem utilizar o contexto ocorrerá
o mesmo problema de aviso de possível objeto nulo.
. Nesse caso podemos declarar operadores de perdão nulo (!) para informar ao compilador que um valor nulo real. Por exemplo:
return context.Todos!.ToList();
. E também em outros lugares avisar ao compilar que o objeto poderá ser nulo:
TodoModel? todo = context.Todos!.FirstOrDefault( x => x.Id == id );
return todo!;
. Um exemplo de um controller com a declaração nos moldes .NET 5 no .NET 6:
namespace Todo.Controllers
{
[ApiController]
[Route("[controller]/")]
public class HomeController : ControllerBase
{
[HttpGet]
public List<TodoModel> Get([FromServices] AppDbContext context )
{
return context.Todos!.ToList();
}
[HttpGet("{id:int}")]
public TodoModel GetById( [FromServices] AppDbContext context, [FromRoute] int id)
{
TodoModel? todo = context.Todos!.FirstOrDefault( x => x.Id == id );
return todo!;
}
[HttpPost]
public TodoModel Post( [FromServices] AppDbContext context, [FromBody] TodoModel model){
context.Todos!.Add(model);
context.SaveChanges();
return model;
}
}
}
. IMPORTANTE: se quisermos continuar da forma como era antes no .NET5 sem nenhuma mudança, basta acessar o
arquivo "Todo.csproj" e alterar o parâmetro "<Nullable>enable</Nullable>" para "<Nullable>disable</Nullable>".
Dessa forma a compilação ocorrerá no .NET 6 como era no 5, desconsiderando as msgs de warning.
Aula 12. Gerando o banco de dados
---------------------------------
. Verifique se o "ef" está instalado:
dotnet ef
. Caso não estiver execute o comando abaixo:
dotnet tool install --global dotnet-ef --version 6.0.8
. Execute o comando abaixo dentro da pasta raiz do projeto:
dotnet clean
dotnet build
dotnet ef migrations add CreationDatabase
dotnet ef database update
. Verifique se foi criado a pasta "Migrations" dentro do projeto com as devidas classes.
. Verifique se foi criado dentro do projeto um arquivo com o nome "app.db" que é o nosso BD SqLite.
Aula 13. Entendendo os Controllers
----------------------------------
. Crie a pasta "Controllers" e dentro dela a classe abaixo:
using Microsoft.AspNetCore.Mvc;
using Todo.Data;
using Todo.Models;
namespace Todo.Controllers
{
[ApiController]
public class HomeController : ControllerBase
{
[HttpGet]
public String Get()
{
return "Hello World";
}
}
}
. Diferença entre "Controller" e "ControllerBase":
...
public class HomeController : ControllerBase
...
. "ControllerBase" é a classe que representa toda a base do padrão MVC Controller. Já a "Controller" estende
a "ControllerBase" e acrescenta alguns métodos destinados ao uso de páginas web:
public abstract class Controller : ControllerBase
{
public dynamic ViewBag { get; }
public virtual ViewResult View(object model) { }
// more View support stuff
}
. Quando for desenvolver APIs que retornam JSONs, estenda a classe "ControllerBase". Caso contrário, se
a API for para retornar além de JSONs, como páginas web, estenda a classe "Controller",
pois essa última tem métodos a mais do que a "ControllerBase".
. O que é a annotation "[ApiController]?
https://wakeupandcode.com/api-controllers-in-asp-net-core/
. Os nomes dos métodos se começarem com Get, Post, Put, Delete, Patch, etc, serão chamados automaticamente de acordo com o verbo http
solicitado pelo "client". Porém, é possível adicionar sufixos aos nomes dos métodos, desde que eles iniciem com o nome do verbo
HTTP (Get, Post, ...)
HTTP Method Possible Web API Action Method Name Usage
----------- ----------------------------------- -----
GET Get() *any name starting with Get * Retrieves data.
get()
GET()
GetAllStudent()
POST Post() *any name starting with Post* Inserts new record.
post()
POST()
PostNewStudent()
PUT Put() *any name starting with Put* Updates existing record.
put()
PUT()
PutStudent()
PATCH Patch() *any name starting with Patch* Updates record partially.
patch()
PATCH()
PatchStudent()
DELETE Delete() *any name starting with Delete* Deletes record.
delete()
DELETE()
DeleteStudent()
. Outra maneira de desenvolver os métodos das APIs sem a necessidade dos nomes dos métodos da classe serem os mesmos dos verbos HTTP,
seria tipificar os métodos com [HttpGet], [HttpPost], etc.
Aula 14. Rotas e Controllers
----------------------------
. Acesse a classe "Program.cs" e comente a linha com o conteúdo "app.Map("/", () => "Hello World");"
. Adicionando suporte a Controllers:
. Adicione as linhas abaixo na classe "Program.cs":
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(); // Linha inserida
var app = builder.Build();
app.MapControllers(); // Linha inserida
. As linhas inseridas servem para publicar as rotas quando o projeto for levantado.
. Acrescente no método "Get" a annotation "Route":
...
[ApiController]
public class HomeController : ControllerBase
{
[HttpGet]
[Route("/")]
public String Get()
{
return "Hello World";
}
}
...
. No Postman e altere a chamada GET com a URL http://localhost:[porta]/
. Acrescente a expressão "home" na classe a annotation "Route":
...
[ApiController]
[Route("home")]
public class HomeController : ControllerBase
{
[HttpGet]
[Route("/")]
public String Get()
{
return "Hello World";
}
}
...
. No Postman e altere a chamada GET com a URL http://localhost:[porta]/home/
. Neste caso a request poderá ser chamada pela URL http://localhost:[porta]/home/
. Podemos colocar o "Route(..)" na classe e neste caso todos os contexto declarados nos métodos
serão acrescidos pelo primeiro pelo da classe e depois pelo do método:
. Confrontar com a "Aula 3 - Entendendo as URL amigáveis." do curso "Uma visão completa do ASP.NET MVC"
. Podemos compor o nome rota com o prefixo do nome da classe controller acrescente a expressão "[controller]" nas
annotation "[Http...()]" ou "[Route()]":
...
[ApiController]
public class HomeController : ControllerBase
{
[HttpGet("[controller]/")]
// ou [Route("[controller]/")]
public String Get()
...
. Em resumo, podemos definir a rota padrão deste controller seria:
[HttpGet("[controller]/")]
^
|
|
https://localhost:[porta]/home/
|
+---> [Home]Controller
. Acesse o Postman e crie uma chamada GET com a URL http://localhost:[porta]/home/
Aula 16. Lendo itens do banco de dados
---------------------------------------
. Adicione as linhas abaixo na classe "Program.cs":
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddDbContext<AppDbContext>(); // Linha inserida
var app = builder.Build();
app.MapControllers();
. A linha inserida servirá para fazermos injeção de dependência do objeto de conexão.
. Acrescente no método "Get" da classe "HomeController" a injeção da nossa classe de conexão:
// https://gutfrau.medium.com/how-to-bind-fromroute-and-frombody-into-one-model-in-net-5-be0730a77852
...
[ApiController]
[Route("[controller]/")] // Linha alterada
public class HomeController : ControllerBase
{
[HttpGet] // Linha alterada
public List<TodoModel> Get([FromService] AppDbContext context) // Linha alterada
{
return context.Todos.ToList(); // Linha alterada
}
}
...
. No Postman e altere a chamada GET com a URL http://localhost:[porta]/home/
. O resultado será uma lista vazia.
[]
Aula 17. Criando um registro
----------------------------
. Crie o método abaixo na classe "HomeController":
[Post]
public TodoModel Post( [FromServices] AppDbContext context, [FromBody] TodoModel model){
context.Todos.Add(model);
context.SaveChanges();
return model;
}
. No Postman crie uma chamada com os parâmetros abaixo:
Method: POST
URL: https://localhost:[porta]/home/
Body.Json: true
Body.raw: {
"id": "1",
"Title": "Ir ao Supermercado",
"Done": True,
"CreatedAt": "2022-09-01T14:00:00"
}
. No Postman, execute a chamada GET com a URL http://localhost:[porta]/home/
Aula 18. Atualizando e excluindo um registro
--------------------------------------------
. Crie o método abaixo na classe "HomeController":
[HttpGet("id:{int}")]
public Todo GetById( [FromServices] AppDbContext context, [FromRoute] int id)
{
TodoModel todo = context.Todos.FirstOrDefault( x => x.Id == id );
return todo;
}
. Observe que na annotation "HttpGet" do método foi utilizado como parâmetro "id:{int}". Isto força com que
exista uma URL com um parâmetro e restringe mais ainda com um tipo "int" que valida o parâmetro
com um número inteiro. Caso for chamado essa url, porém com um parâmetro que não se enquadre num no. válido
o próprio container .NET nem entra no método. Caso a chamada foi feita com sucesso o valor será passado
automaticamente para o parâmetro da assinatura do método "Get([FromServices] AppDbContext context, [FromRoute] int id)"
. Repare que o parâmetro da assinatura "id" está anotado com a annotation [FromRoute]. Este atributo faz com que o
Model Binder apenas vincule dados que são oriundos da rota de dados.
. Poderiamos realizar a mesma configuração do parâmetro na annotation "HttpGet("id:{int}")" na annotation
"Route("id:{int}")".
. A lista de annotation possíveis na assinatura dos métodos são:
. FromForm
Este atributo faz com que o Model Binder utilize somente os dados recebidos do formulário enviado.
public IActionResult Detail([FromForm] ProdutoViewModel produtoViewModel) => View(produtoViewModel);
. FromRoute
Este atributo faz com que o Model Binder apenas vincule dados que são oriundos da rota de dados
public IActionResult Detail([FromRoute] int id) => View();
. FromQuery
Este atributo diz ao Model Binder para receber apenas os dados da cadeia de consulta (querystring).
public IActionResult Detail([FromQuery] int id) => View();
. Se fizermos uma solicitação com a URL: Produto/Detalhe/2?Id=4 . O valor 4 será vinculado e não o
valor 2 conforme seria previsto no comportamento padrão.
. FromHeader
Este atributo diz ao Model Binder para vincular os valores que vêm no cabeçalho da requisição HTTP.
. FromBody
Este atributo diz ao Model Binder para vincular dados a partir do Body do request.
public IActionResult Detail([FromBody] ProdutoViewModel produtoViewModel) => View(produtoViewModel);
. FromServices
Este atributo vincula o valor especificado à implementação que foi configurada no seu container de injeção de dependência.
public IActionResult Detail([FromServices] IPrintable printer) => View();
. Bind e BindNever
Este atributo vincula o valor especificado à implementação que foi configurada no seu container de injeção de dependência.
O atributo BindNever diz ao model binder que não deve vincular o atributo especificado.
Como você pode ver no trecho de código abaixo, IsAdminUser nunca será vinculado.
Esta abordagem pode ser chamada de propriedades de lista negra, o que não é uma boa prática de segurança.
É melhor listar os atributos que queremos vincular usando o atributo Bind, deixando de fora os que não queremos,
como você pode ver no exemplo:
BindNever
---------
public class ProdutoViewModel
{
[FromQuery]
public int ProdutoId { get; set; }
public string ProdutoName { get; set; }
[BindNever]
public string IsAdminUser { get; set; }
}
Bind
----
[Bind(nameof(ProdutoId), nameof(ProdutoNome))]
public class ProdutoViewModel
{
[FromQuery]
public int ProdutoId { get; set; }
public string ProdutoNome { get; set; }
public string IsAdminUser { get; set; }
}
. No Postman, execute a chamada GET com a URL http://localhost:[porta]/home/1
. Inclua os métodos abaixo na classe "HomeController.cs":
...
[HttpPut("{id:int}")]
public TodoModel Put([FromServices] AppDbContext context, [FromRoute] int id, [FromBody] TodoModel todo )
{
var model = context.Todos.FirstOrDefault( x => x.Id == id );
if ( model == null ){
return model;
}
model.Title = todo.Title;
model.Done = todo.Done;
context.Todos.Update( model );
context.SaveChanges();
return model;
}
[HttpDelete("{id:int}")]
public TodoModel Delete( [FromServices] AppDbContext context, [FromRoute] int id )
{
var model = context.Todos.FirstOrDefault( x => x.Id == id );