{"id":1089,"date":"2017-11-10T00:00:30","date_gmt":"2017-11-10T03:00:30","guid":{"rendered":"https:\/\/www.erudio.com.br\/blog\/?p=1089"},"modified":"2022-12-21T14:49:02","modified_gmt":"2022-12-21T17:49:02","slug":"criando-um-endpoint-rest-com-asp-net-core","status":"publish","type":"post","link":"https:\/\/www.erudio.com.br\/blog\/criando-um-endpoint-rest-com-asp-net-core\/","title":{"rendered":"Criando um endpoint REST com ASP.NET Core"},"content":{"rendered":"<p>Neste post daremos continuidade a uma s\u00e9rie de postagens sobre <strong>Web-Services<\/strong> divididos entre conceitos te\u00f3ricos e praticos. Nos 3 primeiros posts focou-se em teoria com um sobre <a href=\"https:\/\/www.erudio.com.br\/blog\/web-services\/\">Web Services<\/a>, outro sobre <a href=\"https:\/\/www.erudio.com.br\/blog\/restful-web-services\/\">RESTful Web Services<\/a> e mais um sobre os <a href=\"https:\/\/www.erudio.com.br\/blog\/http-status-codes-em-servicos-rest\/\">HTTP Status Codes<\/a> mais comuns. Este post por sua vez complementa a parte te\u00f3rica e o que foi desenvolvido na s\u00e9rie de posts em que implementamos API&#8217;s REST com SpringBoot. Faremos aqui uma abordagem das mesmas situa\u00e7\u00f5es s\u00f3 que dessa vez com a tecnologia ASP.NET Core. Al\u00e9m disso o c\u00f3digo desse projeto se baseia no post anterior <a href=\"https:\/\/www.erudio.com.br\/blog\/criando-uma-simples-web-api-restful-em-net-core-2-0\/\">Criando um endpoint REST com ASP.NET Core<\/a>. Ent\u00e3o antes de come\u00e7ar confira o post <a href=\"https:\/\/www.erudio.com.br\/blog\/criando-uma-simples-web-api-restful-em-net-core-2-0\/\">Criando uma simples Web API RESTful em .NET Core 2.0<\/a>.<\/p>\n<p>Agora faremos algumas altera\u00e7\u00f5es no <a href=\"http:\/\/href=\" class=\"broken_link\">projeto original<\/a>. Para come\u00e7ar crie os seguintes source folders <strong>Models<\/strong>, <strong>Services<\/strong> e dentro de Services <strong>Implementations<\/strong>. A estrutura da nossa arquitetura deve ficar similar a imagem abaixo.<\/p>\n<p><img decoding=\"async\" style=\"max-width: 100%;\" src=\"https:\/\/github.com\/leandrocgsi\/SimpleRestfulAPIWithAspNetCore\/blob\/master\/SimpleRestfulAPIWithAspNetCore-v02%20-%20First%20REST%20Service\/post\/01.png?raw=true\" alt=\"Arquitetura da Aplica\u00e7\u00e3o\"><\/p>\n<p>Feito isto crie uma classe chamada <strong>Person<\/strong>, no source folder <strong>Models<\/strong>, com as informa\u00e7\u00f5es que ser\u00e3o representadas pelo nosso <strong>endpoint REST<\/strong>.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nnamespace SimpleRestfulAPIWithAspNetCore.Models\n{\npublic class Person\n{\npublic long Id { get; set; }\npublic string FirstName { get; set; }\npublic string LastName { get; set; }\npublic string Address { get; set; }\n}\n}\n\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Feito isto crie uma <strong>interface<\/strong> com o nome <strong>IPersonService<\/strong> no source folder <strong>Services<\/strong>.<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nusing SimpleRestfulAPIWithAspNetCore.Models;\nusing System.Collections.Generic;\n\nnamespace SimpleRestfulAPIWithAspNetCore.Services\n{\npublic interface IPersonService\n{\nPerson Create(Person person);\nPerson FindById(string personId);\nList&lt;person&gt; FindAll();\nPerson Update(Person person);\nvoid Delete(string personId);\n}\n}\n<\/pre>\n<p>Agora vamos criar a implementa\u00e7\u00e3o para a <strong>interface PersonService<\/strong>. No source folder <strong>Services &#8211;&gt; Implementations<\/strong> crie a classe <strong>PersonServiceImpl<\/strong> que implementa a interface que acabamos de criar.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing SimpleRestfulAPIWithAspNetCore.Models;\nusing System.Threading;\n\nnamespace SimpleRestfulAPIWithAspNetCore.Services.Implementations\n{\npublic class PersonServiceImpl : IPersonService\n{\n\/\/ Contador respons\u00e1vel por gerar um fake ID j\u00e1 que n\u00e3o estamos\n\/\/ acessando nenhum banco de dados\nprivate volatile int count;\n\n\/\/ Metodo respons\u00e1vel por criar uma nova pessoa\n\/\/ Se tiv\u00e9ssemos um banco de dados esse seria o\n\/\/ momento de persistir os dados\npublic Person Create(Person person)\n{\nreturn person;\n}\n\n\/\/ M\u00e9todo respons\u00e1vel por retornar uma pessoa\n\/\/ como n\u00e3o acessamos nenhuma base de dados\n\/\/ estamos retornando um mock\npublic Person FindById(string personId)\n{\nreturn new Person\n{\nId = IncrementAndGet(),\nFirstName = &quot;Leandro&quot;,\nLastName = &quot;Costa&quot;,\nAddress = &quot;Uberl\u00e2ndia - Minas Gerais - Brasil&quot;\n};\n}\n\n\/\/ M\u00e9todo respons\u00e1vel por retornar todas as pessoas\n\/\/ mais uma vez essas informa\u00e7\u00f5es s\u00e3o mocks\npublic List&lt;person&gt; FindAll()\n{\nList&lt;person&gt; persons = new List&lt;person&gt;();\nfor (int i = 0; i &amp;lt; 8; i++)\n{\nPerson person = MockPerson(i);\npersons.Add(person);\n}\nreturn persons;\n}\n\n\/\/ M\u00e9todo respons\u00e1vel por atualizar uma pessoa\n\/\/ por ser mock retornamos a mesma informa\u00e7\u00e3o passada\npublic Person Update(Person person)\n{\nreturn person;\n}\n\n\/\/ M\u00e9todo respons\u00e1vel por deletar\n\/\/ uma pessoa a partir de um ID\npublic void Delete(string personId)\n{\n\/\/A nossa l\u00f3gica de exclus\u00e3o viria aqui\n}\n\n\/\/ M\u00e9todo respons\u00e1vel por mockar uma pessoa\nprivate Person MockPerson(int i)\n{\nreturn new Person\n{\nId = IncrementAndGet(),\nFirstName = &quot;Person Name &quot; + i,\nLastName = &quot;Last Name &quot; + i,\nAddress = &quot;Some Address in Brasil &quot; + i\n};\n}\n\npublic Int32 IncrementAndGet()\n{\nreturn Interlocked.Increment(ref count);\n}\n}\n}\n\n<\/pre>\n<p>Por fim renomeie a classe <strong>ValuesController<\/strong> para <strong>PersonController<\/strong>, ap\u00f3s as altera\u00e7\u00f5es esse ser\u00e1 o controller respons\u00e1vel por expor o <strong>endpoint de pessoas<\/strong>, no source folder <strong>Controllers<\/strong>.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nusing Microsoft.AspNetCore.Mvc;\nusing SimpleRestfulAPIWithAspNetCore.Models;\nusing SimpleRestfulAPIWithAspNetCore.Services;\n\nnamespace SimpleRestfulAPIWithAspNetCore.Controllers\n{\n\/* Mapeia as requisi\u00e7\u00f5es de http:\/\/localhost:{porta}\/api\/person\/\nPor padr\u00e3o o ASP.NET Core mapeia todas as classes que extendem Controller\npegando a primeira parte do nome da classe em lower case [Person]Controller\ne exp\u00f5e como endpoint REST\n*\/\n[Route(&quot;api\/[controller]&quot;)]\npublic class PersonController : Controller\n{\n\/\/Declara\u00e7\u00e3o do servi\u00e7o usado\nprivate IPersonService _personService;\n\n\/* Inje\u00e7\u00e3o de uma instancia de IPersonService ao criar\numa instancia de PersonController *\/\npublic PersonController(IPersonService personService)\n{\n_personService = personService;\n}\n\n\/\/Mapeia as requisi\u00e7\u00f5es GET para http:\/\/localhost:{porta}\/api\/person\/\n\/\/Get sem par\u00e2metros para o FindAll --&amp;gt; Busca Todos\n[HttpGet]\npublic IActionResult Get()\n{\nreturn Ok(_personService.FindAll());\n}\n\n\/\/Mapeia as requisi\u00e7\u00f5es GET para http:\/\/localhost:{porta}\/api\/person\/{id}\n\/\/recebendo um ID como no Path da requisi\u00e7\u00e3o\n\/\/Get com par\u00e2metros para o FindById --&amp;gt; Busca Por ID\n[HttpGet(&quot;{id}&quot;)]\npublic IActionResult Get(string id)\n{\nvar person = _personService.FindById(id);\nif (person == null) return NotFound();\nreturn Ok(person);\n}\n\n\/\/Mapeia as requisi\u00e7\u00f5es POST para http:\/\/localhost:{porta}\/api\/person\/\n\/\/O [FromBody] consome o Objeto JSON enviado no corpo da requisi\u00e7\u00e3o\n[HttpPost]\npublic IActionResult Post([FromBody]Person person)\n{\nif (person == null) return BadRequest();\nreturn new ObjectResult(_personService.Create(person));\n}\n\n\/\/Mapeia as requisi\u00e7\u00f5es PUT para http:\/\/localhost:{porta}\/api\/person\/\n\/\/O [FromBody] consome o Objeto JSON enviado no corpo da requisi\u00e7\u00e3o\n[HttpPut]\npublic IActionResult Put([FromBody]Person person)\n{\nif (person == null) return BadRequest();\nreturn new ObjectResult(_personService.Update(person));\n}\n\n\/\/Mapeia as requisi\u00e7\u00f5es DELETE para http:\/\/localhost:{porta}\/api\/person\/{id}\n\/\/recebendo um ID como no Path da requisi\u00e7\u00e3o\n[HttpDelete(&quot;{id}&quot;)]\npublic IActionResult Delete(string id)\n{\n_personService.Delete(id);\nreturn NoContent();\n}\n}\n}\n<\/pre>\n<p>Agora que terminamos nossa codifica\u00e7\u00e3o inicie a aplica\u00e7\u00e3o. Para testar nosso endpoint e cada uma de suas opera\u00e7\u00f5es usaremos o plugin do Chrome <a href=\"https:\/\/chrome.google.com\/webstore\/detail\/postman\/fhbjgbiflinjbdggehcddcbncdddomop\">Postman<\/a>.<\/p>\n<p>Primeiro faremos uma requisi\u00e7\u00e3o do tipo <strong>GET<\/strong> chamando a opera\u00e7\u00e3o <strong>findAll<\/strong> para o recurso <strong>http:\/\/localhost:{porta}\/api\/person\/<\/strong>. Como se pode ver na imagem abaixo obtemos como resposta um <strong>JSON<\/strong> com um array de pessoas.<\/p>\n<p><img decoding=\"async\" style=\"max-width: 100%;\" src=\"https:\/\/github.com\/leandrocgsi\/SimpleRestfulAPIWithAspNetCore\/blob\/master\/SimpleRestfulAPIWithAspNetCore-v02%20-%20First%20REST%20Service\/post\/02.png?raw=true\" alt=\"Requisi\u00e7\u00e3o REST do tipo GET\"><\/p>\n<p>Agora faremos uma requisi\u00e7\u00e3o do tipo <strong>GET<\/strong> chamando a opera\u00e7\u00e3o <strong>http:\/\/localhost:{porta}\/api\/person\/1<\/strong> passando como <strong>vari\u00e1vel path<\/strong> o ID da pessoa que desejamos recuperar. Da mesma forma que na requisi\u00e7\u00e3o anterior recebemos como resposta um <strong>JSON<\/strong> com 1 objeto pessoa.<\/p>\n<p><img decoding=\"async\" style=\"max-width: 100%;\" src=\"https:\/\/github.com\/leandrocgsi\/SimpleRestfulAPIWithAspNetCore\/blob\/master\/SimpleRestfulAPIWithAspNetCore-v02%20-%20First%20REST%20Service\/post\/03.png?raw=true\" alt=\"Requisi\u00e7\u00e3o REST do tipo GET passando variavel via PATH\"><\/p>\n<p>Agora faremos uma requisi\u00e7\u00e3o do tipo <strong>POST<\/strong> <strong>(esse \u00e9 o verbo REST usado para persistir informa\u00e7\u00f5es)<\/strong> chamando a opera\u00e7\u00e3o <strong>http:\/\/localhost:{porta}\/api\/person\/<\/strong> passando como par\u00e2metro um <strong>JSON<\/strong> com um objeto pessoa no corpo da requisi\u00e7\u00e3o. Para isso no <strong>Postman<\/strong> precisamos setar o tipo de requisi\u00e7\u00e3o como <strong>POST<\/strong>, na<strong> aba Body<\/strong> definimos o <strong>JSON<\/strong> que representa o objeto pessoa a ser gravado, <strong>selecionamos a op\u00e7\u00e3o raw<\/strong>, <strong>definimos a op\u00e7\u00e3o JSON(application\/json)<\/strong> e por fim executamos a request atrav\u00e9s do bot\u00e3o send.<\/p>\n<p><img decoding=\"async\" style=\"max-width: 100%;\" src=\"https:\/\/github.com\/leandrocgsi\/SimpleRestfulAPIWithAspNetCore\/blob\/master\/SimpleRestfulAPIWithAspNetCore-v02%20-%20First%20REST%20Service\/post\/04.png?raw=true\" alt=\"Requisi\u00e7\u00e3o REST do tipo POST gravando um recurso\"><\/p>\n<p>&nbsp;<\/p>\n<p>Agora faremos uma requisi\u00e7\u00e3o do tipo <strong>PUT (esse \u00e9 o verbo REST usado para atualizar informa\u00e7\u00f5es)<\/strong> chamando a opera\u00e7\u00e3o <strong>http:\/\/localhost:{porta}\/api\/person\/<\/strong> passando como par\u00e2metro um <strong>JSON<\/strong> com um objeto pessoa no corpo da requisi\u00e7\u00e3o. Lembrando que essa representa\u00e7\u00e3o de pessoa deve ter um ID que ser\u00e1 usado pra localizar e atualizar um recurso na base. Para isso no <strong>Postman<\/strong> precisamos setar informa\u00e7\u00f5es similares ao post a unica diferen\u00e7a \u00e9 que o tipo de requisi\u00e7\u00e3o deve ser o <strong>PUT<\/strong>.<\/p>\n<p><img decoding=\"async\" style=\"max-width: 100%;\" src=\"https:\/\/github.com\/leandrocgsi\/SimpleRestfulAPIWithAspNetCore\/blob\/master\/SimpleRestfulAPIWithAspNetCore-v02%20-%20First%20REST%20Service\/post\/05.png?raw=true\" alt=\"Requisi\u00e7\u00e3o REST do tipo PUT atualizando um recurso\"><\/p>\n<p>Por fim faremos uma requisi\u00e7\u00e3o do tipo <strong>DELETE (verbo REST usado excluir informa\u00e7\u00f5es)<\/strong> chamando a opera\u00e7\u00e3o <strong>http:\/\/localhost:{porta}\/api\/person\/1<\/strong> passando como <strong>vari\u00e1vel path<\/strong> o ID da pessoa que desejamos remover da base. Esse tipo de requisi\u00e7\u00e3o <strong>retorna como resposta um body vazio e um StatusCode 200<\/strong> caso a opera\u00e7\u00e3o seja executada com sucesso os StatusCode <strong>204 (no content)<\/strong>, <strong>401 (Unauthorized)<\/strong>, <strong>403 (forbiden)<\/strong>, <strong>404 (not found)<\/strong> ou <strong>500 (internal server error)<\/strong> podem ser retornados.<\/p>\n<p><img decoding=\"async\" style=\"max-width: 100%;\" src=\"https:\/\/github.com\/leandrocgsi\/SimpleRestfulAPIWithAspNetCore\/blob\/master\/SimpleRestfulAPIWithAspNetCore-v02%20-%20First%20REST%20Service\/post\/06.png?raw=true\" alt=\"Requisi\u00e7\u00e3o REST do tipo DELETE removendo um recurso\"><\/p>\n<p>Dessa forma abordamos os 4 verbos principais do <strong>HTTP<\/strong> usados em aplica\u00e7\u00f5es <strong>REST<\/strong>. Continue ligado no blog, por que no pr\u00f3ximo post iremos documentar a nossa <strong>API<\/strong> com o framewrok <strong>Swagger<\/strong>. E claro a abordagem nesses posts tamb\u00e9m ser\u00e1 totalmente m\u00e3o na massa. \u00c9 isso a\u00ed bons estudos.<\/p>\n<h2>Treinamentos relacionados com este post<\/h2>\n<p><a href=\"https:\/\/pub.erudio.com.br\/kr\/blog_rest_asp_net\" target=\"_blank\" rel=\"noopener\"><\/p>\n<p><img decoding=\"async\" style=\"max-width: 100%;\" title=\"REST API's RESTFul do 0 \u00e0 Azure com ASP.NET Core 5 e Docker\" src=\"https:\/\/raw.githubusercontent.com\/leandrocgsi\/blog-images\/main\/01-rest-asp.png\"><br \/>\n<\/a><\/p>\n<p><a href=\"https:\/\/pub.erudio.com.br\/kr\/blog_microservices-dotnet\" target=\"_blank\" rel=\"noopener\"><br \/>\n        <img decoding=\"async\" style=\"max-width: 100%;\" title=\"Arquitetura de Microsservi\u00e7os do 0 com ASP.NET, .NET 6 e C#\" src=\"https:\/\/raw.githubusercontent.com\/leandrocgsi\/blog-images\/main\/15-microservices-dotnet.png\"><br \/>\n<\/a><\/p>\n<p><a href=\"https:\/\/pub.erudio.com.br\/kr\/blog_docker\" target=\"_blank\" rel=\"noopener\"><br \/>\n        <img decoding=\"async\" style=\"max-width: 100%;\" title=\"Docker do 0 \u00e0 Maestria: Cont\u00eaineres Desmistificados mais 3 B\u00d4NUS\" src=\"https:\/\/raw.githubusercontent.com\/leandrocgsi\/blog-images\/main\/09-docker.png\"><br \/>\n<\/a><\/p>\n<p><a href=\"https:\/\/pub.erudio.com.br\/kr\/blog_docker_para_aws\" target=\"_blank\" rel=\"noopener\"><br \/>\n        <img decoding=\"async\" style=\"max-width: 100%;\" title=\"Docker para Amazon AWS Implante Apps Java e .NET com Travis CI\" src=\"https:\/\/raw.githubusercontent.com\/leandrocgsi\/blog-images\/main\/10-docker-to-aws.png\"><br \/>\n<\/a><\/p>\n<p><a href=\"https:\/\/pub.erudio.com.br\/kr\/blog_rest_react_asp_net\" target=\"_blank\" rel=\"noopener\"><br \/>\n        <img decoding=\"async\" style=\"max-width: 100%;\" title=\"React JS consumindo REST API RESTful em ASP.NET Core .NET 6\" src=\"https:\/\/raw.githubusercontent.com\/leandrocgsi\/blog-images\/main\/17-rest-react-aspnet.png\"><br \/>\n<\/a><\/p>\n<\/person><\/person><\/person><\/person>\n","protected":false},"excerpt":{"rendered":"<p>Neste post daremos continuidade a uma s\u00e9rie de postagens sobre Web-Services divididos entre conceitos te\u00f3ricos e praticos. Nos 3 primeiros posts focou-se em teoria com um sobre Web Services, outro sobre RESTful Web Services e mais um sobre os HTTP Status Codes mais comuns. Este post por sua vez complementa a parte te\u00f3rica e o [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3,11,13,17,96],"tags":[124,134,135,139,221],"_links":{"self":[{"href":"https:\/\/www.erudio.com.br\/blog\/wp-json\/wp\/v2\/posts\/1089"}],"collection":[{"href":"https:\/\/www.erudio.com.br\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.erudio.com.br\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.erudio.com.br\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.erudio.com.br\/blog\/wp-json\/wp\/v2\/comments?post=1089"}],"version-history":[{"count":5,"href":"https:\/\/www.erudio.com.br\/blog\/wp-json\/wp\/v2\/posts\/1089\/revisions"}],"predecessor-version":[{"id":1545,"href":"https:\/\/www.erudio.com.br\/blog\/wp-json\/wp\/v2\/posts\/1089\/revisions\/1545"}],"wp:attachment":[{"href":"https:\/\/www.erudio.com.br\/blog\/wp-json\/wp\/v2\/media?parent=1089"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.erudio.com.br\/blog\/wp-json\/wp\/v2\/categories?post=1089"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.erudio.com.br\/blog\/wp-json\/wp\/v2\/tags?post=1089"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}