ASP .NET MVC - Usando Autenticação, imagens, Repositório, Unit of Work e Entity Framework (C#) - II


Na primeira parte deste artigo criamos o projeto e definimos as referências necessárias; também definimos o Model , aplicamos o padrão repositório e o padrão unit of work preparando assim toda a infraestrutura da nossa aplicação.

Vamos agora definir os nosso controladores que por tabela irão definir quais as views teremos que criar para atuar como interface com o usuário.

Definindo os Controladores

O primeiro controller que iremos definir na verdade ja foi criado quando criamos o projeto e escolhemos o template ASP .NET MVC 3 Web Application: o HomeController.cs.

Abra este arquivo e altere o seu conteúdo conforme abaixo:

using System.Web.Mvc;

namespace Repositorio_EF.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = "Bem-Vindo a Escola Macoratti";
            return View();
        }
        //
        public ActionResult About()
        {
            return View();
        }
        public ImageResult GetImage()
        {
            return new ImageResult("c:\\dados\\Imagens\\ponte.jpg");
        }

    }
}

Outro arquivo que vamos alterar é o arquivo _Layout.cshtml que esta na pasta Views -> Shared. Embora ele não seja um controlador temos que definir os itens que desejamos exibir no menu da aplicação. Abra então este arquivo e altere o seu conteúdo conforme abaixo:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
</head>
<body>
    <div class="page">
        <header>
            <div id="title">
                <h1>Macoratti .net</h1>
            </div>
            <div id="logindisplay">
                @Html.Partial("_LogOnPartial")
            </div>
            <nav>
                <ul id="menu">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("Sobre", "About", "Home")</li>
                    <li>@Html.ActionLink("Cursos", "Index", "Cursos")</li>
                    <li>@Html.ActionLink("Alunos", "Index", "Alunos")</li>
                </ul>
            </nav>
        </header>
        <section id="main">
            @RenderBody()
        </section>
        <footer>
        </footer>
    </div>
</body>
</html>

Além disso para podermos exibir a página inicial tenha certeza de que a view Index.cshtml tenha o seguinte conteúdo:

Obs: Note que estamos usando a Action Getimage definida no controller HomeController.cs da classe ImageResult.cs definida em nosso Model:

@{
    ViewBag.Title = "Home Page";
}
<h2>@ViewBag.Message</h2>
<p>
<h2>
Gerencie Cursos e Alunos - Com ASP .NET MVC 
</h2>
 <p><img src="/Home/GetImage" alt="logo"/></p>
</p>

Após estas alterações executando a aplicação iremos obter a seguinte página:

Definindo o controlador para os Cursos

Clique com o botão direito do mouse sobre a pasta Controllers e selecione Add -> Controller e a seguir informe o nome CursosController na janela Add Controller:

Após clicar no botão Add o arquivo CursosController será criado na pasta Controllers; altere então seu conteúdo para estar conforme o código a seguir:

using System.Web.Mvc;
using Repositorio_EF.Models;

namespace Repositorio_EF.Controllers
{
    [Authorize(Roles = "Administrador")]
    public class CursosController : Controller
    {
            private UnitOfWork unitOfWork = new UnitOfWork();
            //
            public ActionResult Index()
            {
                return View(unitOfWork.CursoRepositorio.Cursos);
            }
            //
            public ActionResult Create()
            {
                return View();
            }
            //
            public ActionResult Delete(int id)
            {
                Curso curso = unitOfWork.CursoRepositorio.Busca(id);
                return View(curso);
            }
            //
            [HttpPost]
            [ActionName("Delete")]
            public ActionResult DeleteConfirmed(int id)
            {
                unitOfWork.CursoRepositorio.Remove(id);
                unitOfWork.Salva();
                return RedirectToAction("Index");
            }
            //
            protected override void Dispose(bool disposing)
            {
                unitOfWork.Dispose();
                base.Dispose(disposing);
            }
            //
            [HttpPost]
            public ActionResult Create(Curso curso)
            {
                if (ModelState.IsValid)
                {
                    unitOfWork.CursoRepositorio.Adiciona(curso);
                    unitOfWork.Salva();
                    return RedirectToAction("Index");
                }
                return View(curso);
            }
        }
}
Note que estamos usando um filtro de autorização na classe CursosController:

[Authorize(Roles = "Administrador")]

Dessa forma o acesso à classe somente poderá ser feita por usuário autenticado
com perfil de administrador;

Estamos usando o padrão Unit of Work definido para realizar a persistência das
entidades definidas via Entity Framework;

Após criar o controlador clique com o botão direito do mouse sobre o seu interior e selecione Add View e a seguir na janela Add View selecione o Model Curso e o respectivo Scaffold template. Assim você deve clicar no interior do controlador no método Index e selecionar List, para o método Create e selecionar Create , no interior do método Delete e selecionar Delete, etc.

Dessa forma serão criadas as views Index.cshtml, Create.cshtml e Delete.cshtml na pasta Views->Cursos;

Vamos repetir o procedimento feito acima para criar o controlador para os Alunos de forma que o arquivo AlunosController.cs deverá ser criado com o seguinte conteúdo:

using System.Web.Mvc;
using Repositorio_EF.Models;

namespace Repositorio_EF.Controllers
{
    [Authorize(Roles = "Administrador")]
    public class AlunosController : Controller
    {
        // GET: /Alunos/
        public ActionResult Index()
        {
            return View(unitOfWork.AlunoRepositorio.Alunos);
        }
        //
        private UnitOfWork unitOfWork = new UnitOfWork();
        public ActionResult Create()
        {
             ViewBag.CursoId = new SelectList(unitOfWork.CursoRepositorio.Cursos, "CursoId", "Descricao");
             return View();
        }
        //
        [HttpPost]
        public ActionResult Create(Aluno aluno)
        {
           if (ModelState.IsValid)
           {
                unitOfWork.AlunoRepositorio.Adiciona(aluno);
                unitOfWork.Salva();
           }
           ViewBag.CursoId = new SelectList(unitOfWork.CursoRepositorio.Cursos, "CursoId", "Descricao");
           return View();
         }
         //
         public ActionResult Delete(int id)
         {
             Aluno aluno = unitOfWork.AlunoRepositorio.Busca(id);
             return View(aluno);
         }
         //
         [HttpPost]
         [ActionName("Delete")]
         public ActionResult DeleteConfirmed(int id)
         {
            unitOfWork.AlunoRepositorio.Remove(id);
            unitOfWork.Salva();
            return RedirectToAction("Index");
         } 
         //
         protected override void Dispose(bool disposing)
         {
            unitOfWork.Dispose();
            base.Dispose(disposing);
         }
     }
}
Note que estamos usando um filtro de autorização na classe CursosController:

[Authorize(Roles = "Administrador")]

Dessa forma o acesso à classe somente poderá ser feita por usuário autenticado
com perfil de administrador;

Estamos usando o padrão Unit of Work definido para realizar a persistência das
entidades definidas via Entity Framework;

Após criar o controlador clique com o botão direito do mouse sobre o seu interior e selecione Add View e a seguir na janela Add View selecione o Model Aluno e o respectivo Scaffold template. Assim você deve clicar no interior do controlador no método Index e selecionar List, para o método Create e selecionar Create , no interior do método Delete e selecionar Delete, etc.

Dessa forma serão criadas as views Index.cshtml, Create.cshtml e Delete.cshtml na pasta Views->Alunos;

Agora com base no controlador AccountController que foi criado por padrão quando da criação do projeto vamos criar um novo controlador chamado UsuarioController.cs que deverá ter o seguinte código:

using System;
using System.Web.Mvc;
using System.Web.Security;
using Repositorio_EF.Models;

namespace Repositorio_EF.Controllers
{
    public class UsuarioController : Controller
    {
        //
        // GET: /Usuario/
        public ActionResult Index()
        {
            return View();
        }
        //
        public ActionResult LogOn()
        {
            return View();
        }
        //
        [HttpPost]
        public ActionResult LogOn(LogOnModel model, string returnUrl)
        {
             if (ModelState.IsValid)
             {
                  if (Membership.ValidateUser(model.UserName, model.Password))
                  {
                    FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                    if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                        && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
                    {
                      return Redirect(returnUrl);
                    }
                    else
                    {
                       return RedirectToAction("Index", "Home");
                    }
                  }
                  else
                  {
                        ModelState.AddModelError("", "O usuário e/ou a senha está incorreto.");
                  }
            }
            return View(model);
         }
         // GET: /Usuario/LogOff
         public ActionResult LogOff()
         {
            FormsAuthentication.SignOut();
            return Redirect("/");
         }
         //
         public ActionResult Register()
         {
             return View();
         }

         //
         // POST: /Usuario/Register
         [HttpPost]
         public ActionResult Register(RegisterModel model)
         {
             if (ModelState.IsValid)
             {
                 // Attempt to register the user
                 MembershipCreateStatus createStatus;
                 Membership.CreateUser(model.UserName, model.Password, model.Email,null, null, true, null, out createStatus);

                 if (createStatus == MembershipCreateStatus.Success)
                 {
                     FormsAuthentication.SetAuthCookie(model.UserName, false /*-createPersistentCookie */);
                     return Redirect("/");
                 }
                 else
                 {
                     ModelState.AddModelError("", ErrorCodeToString(createStatus));
                 }
             }
             return View(model);
         }
         //
         // GET: /Usuario/ChangePassword
         [Authorize]
         public ActionResult ChangePassword()
         {
             return View();
         }
         //
         // POST: /Usuario/ChangePassword
         [Authorize]
         [HttpPost]
         public ActionResult ChangePassword(ChangePasswordModel model)
         {
             if (ModelState.IsValid)
             {
                 bool changePasswordSucceeded;
                 try
                 {
                     MembershipUser currentUser = Membership.GetUser(User.Identity.Name, true /* userIsOnline */);
                     changePasswordSucceeded = currentUser.ChangePassword(model.OldPassword, model.NewPassword);
                 }
                 catch (Exception)
                 {
                     changePasswordSucceeded = false;
                 }

                 if (changePasswordSucceeded)
                 {
                     return RedirectToAction("ChangePasswordSuccess");
                 }
                 else
                 {
                     ModelState.AddModelError("", "A senha atual ou a confirmação está incorreta.");
                 }
             }
             return View(model);
         }
         //
         // GET: /Usuario/ChangePasswordSuccess

         public ActionResult ChangePasswordSuccess()
         {
             return View();
         }

         private static string ErrorCodeToString(MembershipCreateStatus createStatus)
         {
             // See http://go.microsoft.com/fwlink/?LinkID=177550 for
             // a full list of status codes.
             switch (createStatus)
             {
                 case MembershipCreateStatus.DuplicateUserName:
                     return "Este nome de usuário já existe. Defina outro usuário.";

                 case MembershipCreateStatus.DuplicateEmail:
                     return "Este email já foi cadastrado. Defina outro email.";

                 case MembershipCreateStatus.InvalidPassword:
                     return "Senha incorreta.";

                 case MembershipCreateStatus.InvalidEmail:
                     return "Email inválido.";

                 case MembershipCreateStatus.InvalidAnswer:
                     return "Resposta inválida para recuperar a senha.";

                 case MembershipCreateStatus.InvalidQuestion:
                     return "Questão inválida para recuperar a senha.";

                 case MembershipCreateStatus.InvalidUserName:
                     return "Usuário inválido.";

                 case MembershipCreateStatus.ProviderError:
                     return "Ocorreu um erro durante a autenticação. Se o problema persistir, contate o administrador.";

                 case MembershipCreateStatus.UserRejected:
                     return "O cadastro do usuário foi cancelado. Se o problema persistir, contate o administrador.";

                 default:
                     return "Um erro inesperado ocorreu. Se o problema persistir, contate o administrador.";
             }
         }

         public ImageResult GetImage()
         {
             return new ImageResult("c:\\dados\\Imagens\\chgpass.jpg");
         }
    }
}

Este controlador irá permitir a autenticação do usuário para ter acesso às páginas dos Cursos e Alunos.

A partir deste controlador iremos criar as views LogOn.chstml, Register.cshtml, ChangePassword.cshtml e ChangePasswordSuccess.cshtml na pasta Views->Usuario;

Incluindo um usuário Admininistrador com ASP .NET Configuration

Vamos agora definir um usuário com perfil de administrador usando a ferramenta ASP .NET Configuration;

Para ativar a ferramenta clique no ícone indicado na figura na janela Solution Explorer:

Será aberta a página abaixo no seu navegador padrão; Clique no link Security;

Na próxima página clique no link - Create or Manage roles;

Informe o nome perfil informando administrador Add Role para adicionar o novo perfil criado;

Clique no botão Back e a seguir clique em Create User e informe o nome, senha e email e marque o perfil do usuário como administrador:

Pronto com isso já temos um usuário com perfil de administrador que poderá acessar as páginas para Cursos e Alunos;

Definindo um controlador para tratamento de erros

Clique na pasta Controllers com o botão direito do mouse e selecione Add->Controller informando o nome ErroControler e a seguir digite o código abaixo neste arquivo:

using System.Web.Mvc;

namespace Repositorio_EF.Controllers
{
    public class ErroController : Controller
    {
        //
        // GET: /Erro/
        public ActionResult Desconhecido()
        {
            return View();
        }
        //
        // GET: /Erro/PaginaNaoEncontrada
        public ActionResult PaginaNaoEncontrada()
        {
            return View();
        }
    }
}
ErroController.cs

No código acima definimos duas Actions para tratar erros desconhecidos e uma Action para página não encontrada.

Agora vamos criar uma view para cada Action clicando sobre o código do método Action correspondente e selecionando Add View;

Repita o procedimento para o método Action PaginaNaoEncontrada e a seguir defina o código para cada view conforme abaixo:

@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
 <title> no servidor</title>
 </head>
 <body>
 <h2>Desculpe, Sua solicitação não pode ser atendida. Volte dentro de alguns instantes. -
</h2>
 <p>Entre em contato com o suporte. Envie uma mensagem para os administradores do sistema.</p>
 @using (Html.BeginForm("Envia", "Email"))
 {
 <div class="editor-label">
 @Html.Label("Mensagem")
 </div>
 <div class="editor-field">
 @Html.TextArea("Mensagem")
 </div>
 <input type="submit" value="Enviar" />
 }
 </body>
 </html>
<!-- ~/Views/Erro/PaginaNaoEncontrada.cshtml -->
@{
Layout = null;
}
<!DOCTYPE html>

<html>
<head>
<title>Página não encontrada</title>
</head>
<body>
<h2>Página não encontrada</h2>
</body>
</html>
/Views/Erro/Desconhecido.cshtml /Views/Erro/PaginaNaoEncontrada.cshtml

Vamos agora definir um controlador para enviar Email

Clique na pasta Controllers com o botão direito do mouse e selecione Add->Controller informando o nome EmailControler e a seguir digite o código abaixo neste arquivo:

using System.Web.Mvc;
using System.Web.Helpers;

namespace Repositorio_EF.Controllers
{
    public class EmailController : Controller
    {
        public EmailController()
        {
            WebMail.SmtpServer = "smtp.gmail.com";
            WebMail.EnableSsl = true;
            WebMail.SmtpPort = 587;
            WebMail.From = "USUARIO@gmail.com";
            WebMail.UserName = "USUARIO@gmail.com";
            WebMail.Password = "SENHA";
        }
        //
        // POST: /Email/Envia
        [HttpPost]
        public ActionResult Envia(string mensagem)
        {
            WebMail.Send("EMAIL", "Alunos - Erro", mensagem);
            return View();
        }
    }
}
EmailController.cs

Agora vamos criar uma view para a Action Envia clicando sobre o código do método Action correspondente e selecionando Add View;

A seguir digite o código abaixo para esta view:

@{
Layout = null;
}

<!DOCTYPE html>

<html>
 <head>
 <title>Envia</title>
 </head>
 <body>
 <div>
 Mensagem enviada com sucesso.
 </div>
 <div>
 @Html.ActionLink("Voltar para página inicial", "Index", "Selecoes")
 </div>
 </body>
 </html>
Views/Email/Envia.cshtml

O arquivo Envia.cshtml será criado na pasta Email.

Neste ponto já podemos executar a aplicação e clicar na aba Cursos e Alunos e neste caso iremos obter o formulário para autenticação;

Após fazer a autenticação será a apresentada a página cadastrar Cursos e/ou Alunos conforme abaixo:

Note que como foi a primeira execução o banco de dados e as tabelas foram criados e estão vazios.

Em cada página temos um link para cadastrar um novo curso e criar um novo Aluno;

Primeiro devemos cadastrar um novo curso:

 
 

Em seguida criar um novo Aluno:

 
 

E assim temos nossa aplicação ASP .NET MVC funcional usando alguns recursos básicos de uma aplicação web.

O projeto serve para estudo e também pode ser melhorado e expandido com por exemplo : a criação de página para avaliação ou uma página de notas.

Pegue o projeto completo aqui: Repositorio_EF.zip

Rom 8:34 Quem os condenará? Cristo Jesus é quem morreu, ou antes quem ressurgiu dentre os mortos, o qual está à direita de Deus, e também intercede por nós;
Rom 8:35
quem nos separará do amor de Cristo? a tribulação, ou a angústia, ou a perseguição, ou a fome, ou a nudez, ou o perigo, ou a espada?
Rom 8:36
Como está escrito: Por amor de ti somos entregues à morte o dia todo; fomos considerados como ovelhas para o matadouro.
Rom 8:37
Mas em todas estas coisas somos mais que vencedores, por aquele que nos amou.

Referências:


José Carlos Macoratti