Aplicação ASP.NET MVC Cliente de Aplicação Web...
-
Upload
dangkhuong -
Category
Documents
-
view
222 -
download
0
Transcript of Aplicação ASP.NET MVC Cliente de Aplicação Web...
Aplicação ASP.NET MVC Cliente de Aplicação Web API (com Class Library)
http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client
Calling a Web API From a .NET Client in ASP.NET Web API 2 (C#)
Vamos criar:
uma Class Library com o modelo de dados,
uma Aplicação Web API 2 com uma Referência para a Class Library, e
uma Aplicação Web MVC 5 também com uma Referência para a Class Library, cliente
da aplicação Web API 2
As vantagens de usar Class library são a reutilização do componente e a garantia de que as
classes do modelo de dados são iguais nas duas aplicações web.
Estes três projetos podem ser criados numa mesma Solução Visual Studio ou em Soluções
diferentes.
Numa máquina menos potente é aconselhável criar uma única Solução para todos os projetos
pois permite executar cliente e servidor tendo apenas uma única instância do Visual Studio
aberta.
1. Criar a Solução
Visual Studio 2015 > File > New Project… > Templates: abrir Other Project Types > Visual Studio Solutions > Blank Solution Name: Livros
2. Criar a Class Library Bt. dir. do rato em cima do nome da solução:
Add > New Project… > Visual C# > Class Library
Name: ClassLibraryLivros
OK
3. Criar a Aplicação ASP.NET Web API 2
Bt. dir. do rato em cima do nome da solução:
Add > New Project… > Web > ASP.NET Web Application Name: WebApiLivros OK ASP.NET 4.6 Templates: Web API OK
4. Criar a Aplicação ASP.NET MVC 5 (Cliente da Aplicação Web API 2)
Bt. dir. do rato em cima do nome da solução:
Add > New Project… > Web > ASP.NET Web Application Name: ClienteMvcLivros OK ASP.NET 4.6 Templates: MVC OK
Em seguida vamos criar Soluções diferentes para cada projeto.
1. Criar a Class Library
Visual Studio 2015 > File > New > Project… Visual C# > Class Library [ Type: Visual C#, A project for creating a C# class library (.dll) ]
Name: ClassLibraryLivros
1.1. Adicionar as classes Editora e Livro
ClassLibraryLivros > botão direito do rato em cima do nome do projeto: Add > Class… > Name: Editora.cs Add public class Editora { public int EditoraId { get; set; } public string Nome { get; set; } }
Add > Class… > Name: Livro.cs Add public class Livro { public int LivroId { get; set; } public string Titulo { get; set; } public int EditoraId { get; set; } public Editora Editora { get; set; } }
1.2. Build da Solução
Build > Build Solution
2. Criar a Aplicação Asp.Net Web API 2
Visual Studio 2015 > File > New > Project… Visual C#, Web > ASP.NET Web Application (.NET Framework)
Name: WebAPILivros
ASP.NET 4.6 Templates: Web API Authentication: Individual User Accounts OK
2.1 Adicionar uma Referência para a biblioteca ClassLibraryLivros
Adicionar o projeto ClassLibraryLivros à solução Visual Studio:
Solution ‘WebAPILivros’ (1 project) > bt. dir. do rato
Add > Existing Project… > ClassLibraryLivros.csproj > Abrir
Solution ‘WebAPILivros’ (2 projects)
Adicionar uma referência da aplicação WebAPILivros para a biblioteca ClassLibraryLivros:
WebAPILivros > bt. dir. do rato > Add > Reference…
Projects, Solution > selecionar ClassLibraryLivros > OK
2.2 Build da Aplicação
Necessário para em seguida o scaffolding poder usar as classes do modelo e do contexto.
Build > Build Solution
2.3 Scaffolding para criar Controladores para as entidades Editora e Livro
Controllers > botão direito do rato: Add > Controller… >
Add Scaffold: Web API 2 Controller with actions, using Entity Framework > Add
Model class: Editora (ClassLibraryLivros) Data context class: ApplicationDbContext (WebApiLivros.Models) Use async controller actions Controller name: EditorasController Add
Controllers > botão direito do rato: Add > Controller… >
Add Scaffold: Web API 2 Controller with actions, using Entity Framework > Add
Model class: Livro (ClassLibraryLivros) Data context class: ApplicationDbContext (WebApiLivros.Models) Use async controller actions Controller name: LivrosController Add
2.4 Verificar a criação de objetos DbSet para acesso à base de dados (na classe ApplicationDbContext)
No ficheiro Models\IdentityModels.cs aparecem 2 propriedades DbSet: Editoras e Livroes.
public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { public ApplicationDbContext() : base("DefaultConnection", throwIfV1Schema: false) { } public static ApplicationDbContext Create() { return new ApplicationDbContext(); } public System.Data.Entity.DbSet<WebApiLivros.Models.Editora> Editoras { get; set; } public System.Data.Entity.DbSet<WebApiLivros.Models.Livro> Livroes { get; set; } }
2.5 Criar a base de dados com Migrações (ou executando a aplicação)
Criar a base de dados com Migrações:
Visual Studio 2015 > Tools > Nuget Package Manager > Package Manager Console
PM> enable-migrations
PM> add-migration Initial
PM> update-database
2.6 Executar a aplicação ou testar com Postman
Debug > Start Without Debugging Na barra de endereços do browser acrescentar /api/Editoras ou /api/Livros localhost:xxxxx/api/Editoras localhost:xxxxx/api/Livros
3. Criar a Aplicação ASP.NET MVC 5 (Cliente da Aplicação Web API 2)
Visual Studio 2015 > File > New Project… > Web > ASP.NET Web Application Name: ClienteMvcLivros OK ASP.NET 4.6 Templates: MVC OK
3.1 Adicionar uma Referência para a biblioteca ClassLibraryLivros
Adicionar o projeto ClassLibraryLivros à solução Visual Studio:
Solution ‘ClienteMvcLivros’ (1 project) > bt. dir. do rato
Add > Existing Project… > ClassLibraryLivros.csproj > Abrir
Solution ‘ClienteMvcLivros’ (2 projects)
Adicionar uma referência da aplicação ClienteMvcLivros para a biblioteca ClassLibraryLivros:
ClienteMvcLivros > bt. dir. do rato > Add > Reference…
Projects, Solution > selecionar ClassLibraryLivros > OK
3.2 Build da Aplicação
Necessário para em seguida o scaffolding poder usar as classes do modelo e do contexto.
Build > Buil Solution
3.3 Scaffolding para criar Controladores e Vistas Controllers > botão direito do rato: Add > Controller… >
Add Scaffold: MVC 5 Controller with views, using Entity Framework > Add
Model class: Editora (ClassLibraryLivros) Data context class: ApplicationDbContext (ClienteMvcLivros.Models) Use async controller actions Controller name: EditorasController Add
Controllers > botão direito do rato: Add > Controller… >
Add Scaffold: MVC 5 Controller with views, using Entity Framework > Add
Model class: Livro (ClasLibraryLivros) Data context class: ApplicationDbContext (ClienteMvcLivros.Models) Use async controller actions Controller name: LivrosController Add
3.4 Alterar a classe EditorasController
Para que esta classe possa fazer pedidos ao serviço Web API necessitámos de um cliente. A
classe HttpClient pode ser usada quer para aplicações Web, aplicações de Consola ou
aplicações móveis.
Como vamos necessitar desta classe em todas as ações de todos os controladores vamos
escrever uma classe helper para inicializar este cliente.
3.4.1 Criar uma pasta Helpers para conter a classe de acesso à Web API
ClienteMvcLivros> botão direito do rato: Add > New Folder > Helpers
Helpers > botão direito do rato: Add > Class… > Name: WebApiHttpClient.cs Add
using System; using System.Net.Http;
namespace ClienteMvcLivros.Helpers { public class WebApiHttpClient { public const string WebApiBaseAddress = "http://localhost:1742/"; public static HttpClient GetClient() { HttpClient client = new HttpClient(); client.BaseAddress = new Uri(WebApiBaseAddress); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); return client; } } } Necessário mudar a localização do serviço Web API na constante WebApiBaseAddress.
Configurámos no objeto HttpClient:
a propriedade BaseAddress com o endereço do serviço Web API
a propriedade DefaultRequestHeaders para que o formato da resposta do serviço seja
apenas o formato JSON. Começámos por fazer Clear() e depois adicionámos o formato
"application/json"
3.4.2 Classe EditorasController
using System.Collections.Generic; using System.Threading.Tasks; using System.Net; using System.Web.Mvc; using ClienteMvcLivros.Models; using ClienteMvcLivros.Helpers; using System.Net.Http; using Newtonsoft.Json;
using ClassLibraryLivros;
namespace ClienteMvcLivros.Controllers { public class EditorasController : Controller { // private ApplicationDbContext db = new ApplicationDbContext(); // GET: Editoras
. . .
3.4.3 Método Index de EditorasController
Inicial: // GET: Editoras public async Task<ActionResult> Index() { return View(await db.Editoras.ToListAsync()); }
Alterar para:
// GET: Editoras public async Task<ActionResult> Index() { var client = WebApiHttpClient.GetClient(); HttpResponseMessage response = await client.GetAsync("api/Editoras"); if (response.IsSuccessStatusCode) { string content = await response.Content.ReadAsStringAsync(); var editoras = JsonConvert.DeserializeObject<IEnumerable<Editora>>(content); return View(editoras); } else { return Content("Ocorreu um erro: " + response.StatusCode); } }
3.4.4 Método Details de EditorasController
Inicial:
// GET: Editoras/Details/5
public async Task<ActionResult> Details(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Editora editora = await db.Editoras.FindAsync(id); if (editora == null) { return HttpNotFound(); } return View(editora); }
Alterar para:
// GET: Editoras/Details/5 public async Task<ActionResult> Details(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } var client = WebApiHttpClient.GetClient(); HttpResponseMessage response = await client.GetAsync("api/Editoras/" + id); if (response.IsSuccessStatusCode) { string content = await response.Content.ReadAsStringAsync(); var editora = JsonConvert.DeserializeObject<Editora>(content); if (editora == null) return HttpNotFound(); return View(editora); } else { return Content("Ocorreu um erro: " + response.StatusCode); } }
3.4.5 Métodos Create de EditorasController
Inicial:
// GET: Editoras/Create public ActionResult Create() { return View(); } // POST: Editoras/Create // To protect from overposting attacks, please enable the specific properties you want to bind to, for // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost] [ValidateAntiForgeryToken] public async Task<ActionResult> Create( [Bind(Include = "EditoraId,Nome")] Editora editora) { if (ModelState.IsValid) { db.Editoras.Add(editora); await db.SaveChangesAsync(); return RedirectToAction("Index"); } return View(editora); }
Alterar para:
// GET: Editoras/Create public ActionResult Create() { return View(); } // POST: Editoras/Create // To protect from overposting attacks, please enable the specific properties you want to bind to, for // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost] [ValidateAntiForgeryToken] public async Task<ActionResult> Create( [Bind(Include = "EditoraId,Nome")] Editora editora) { try { var client = WebApiHttpClient.GetClient(); string editoraJSON = JsonConvert.SerializeObject(editora); HttpContent content = new StringContent(editoraJSON, System.Text.Encoding.Unicode, "application/json"); var response = await client.PostAsync("api/Editoras", content); if (response.IsSuccessStatusCode) { return RedirectToAction("Index"); } else { return Content("Ocorreu um erro: " + response.StatusCode); } } catch { return Content("Ocorreu um erro."); } }
3.4.6 Necessário instalar o package Nuget System.Net.Http.Formatting.Extension Bt. dir. do rato em cima do nome do projeto Visita > Manage Nuget Packages…
Search: System.Net.Http.Formatting.Extension Browse
Download, Install
3.4.7 Métodos Edit de EditorasController
Inicial:
// GET: Editoras/Edit/5 public async Task<ActionResult> Edit(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Editora editora = await db.Editoras.FindAsync(id); if (editora == null) { return HttpNotFound(); } return View(editora); } // POST: Editoras/Edit/5 // To protect from overposting attacks, please enable the specific properties you want to bind to, for // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost] [ValidateAntiForgeryToken] public async Task<ActionResult> Edit( [Bind(Include = "EditoraId,Nome")] Editora editora) { if (ModelState.IsValid) { db.Entry(editora).State = EntityState.Modified; await db.SaveChangesAsync(); return RedirectToAction("Index"); } return View(editora); }
Alterar para:
// GET: Editoras/Edit/5 public async Task<ActionResult> Edit(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } var client = WebApiHttpClient.GetClient(); HttpResponseMessage response = await client.GetAsync("api/Editoras/" + id); if (response.IsSuccessStatusCode) { string content = await response.Content.ReadAsStringAsync(); var editora = JsonConvert.DeserializeObject<Editora>(content); if (editora == null) return HttpNotFound(); return View(editora); } return Content("Ocorreu um erro: " + response.StatusCode); } // POST: Editoras/Edit/5 // To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost] [ValidateAntiForgeryToken] public async Task<ActionResult> Edit( [Bind(Include = "EditoraId,Nome")] Editora editora) { try { var client = WebApiHttpClient.GetClient(); string editoraJSON = JsonConvert.SerializeObject(editora); HttpContent content = new StringContent(editoraJSON, System.Text.Encoding.Unicode, "application/json"); var response = await client.PutAsync("api/Editoras/" + editora.EditoraId, content); if (response.IsSuccessStatusCode) { return RedirectToAction("Index"); } else { return Content("Ocorreu um erro: " + response.StatusCode); } } catch { return Content("Ocorreu um erro."); } }
3.4.8 Métodos Delete de EditorasController
Inicial:
// GET: Editoras/Delete/5 public async Task<ActionResult> Delete(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } Editora editora = await db.Editoras.FindAsync(id); if (editora == null) { return HttpNotFound(); } return View(editora); } // POST: Editoras/Delete/5 [HttpPost, ActionName("Delete")] [ValidateAntiForgeryToken] public async Task<ActionResult> DeleteConfirmed(int id) { Editora editora = await db.Editoras.FindAsync(id); db.Editoras.Remove(editora); await db.SaveChangesAsync(); return RedirectToAction("Index"); }
Alterar para: // GET: Editoras/Delete/5 public async Task<ActionResult> Delete(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } var client = WebApiHttpClient.GetClient(); HttpResponseMessage response = await client.GetAsync("api/Editoras/" + id); if (response.IsSuccessStatusCode) { string content = await response.Content.ReadAsStringAsync(); var editora = JsonConvert.DeserializeObject<Editora>(content); if (editora == null) return HttpNotFound(); return View(editora); } return Content("Ocorreu um erro: " + response.StatusCode); } // POST: Editoras/Delete/5 [HttpPost, ActionName("Delete")] [ValidateAntiForgeryToken] public async Task<ActionResult> DeleteConfirmed(int id) { try { var client = WebApiHttpClient.GetClient(); var response = await client.DeleteAsync("api/Editoras/" + id); if (response.IsSuccessStatusCode) { return RedirectToAction("Index"); } else { return Content("Ocorreu um erro: " + response.StatusCode); } } catch { return Content("Ocorreu um erro."); } }
3.4.9 Método Dispose de EditorasController
//protected override void Dispose(bool disposing) //{ // if (disposing) // { // db.Dispose(); // } // base.Dispose(disposing); //}
4. Executar o Serviço e o Cliente
Executar a aplicação Web API (WebApiLivros).
Copiar o endereço base do serviço e colocar na classe helper WebApiHttpClient da aplicação Cliente MVC (ClienteMvcLivros).
Executar a aplicação Cliente MVC (ClienteMvcLivros).
Na barra de endereços do browser acrescentar /Editoras
Testar as várias ações do controlador Editoras.
5. Alterar a classe LivrosController
Alterar os métodos Index, Details, Create, Edit e Delete de um modo semelhante às alterações
na classe EditorasController.