Associação e administração

por Erik Reitan

Esta série de tutoriais ensinará os conceitos básicos da criação de um aplicativo ASP.NET Web Forms usando ASP.NET 4.5 e Microsoft Visual Studio Express 2013 para Web. Um projeto Visual Studio 2013 com código-fonte C# está disponível para acompanhar esta série de tutoriais.

Este tutorial mostra como atualizar o aplicativo de exemplo Wingtip Toys para adicionar uma função personalizada e usar ASP.NET Identidade. Ele também mostra como implementar uma página de administração da qual o usuário com uma função personalizada pode adicionar e remover produtos do site.

ASP.NET Identity é o sistema de associação usado para criar ASP.NET aplicativo Web e está disponível no ASP.NET 4.5. ASP.NET Identity é usado no modelo de projeto Visual Studio 2013 Web Forms, bem como os modelos para ASP.NET MVC, ASP.NET Web API e ASP.NET Aplicativo de Página Única. Você também pode instalar especificamente o sistema de identidade ASP.NET usando o NuGet quando você começa com um aplicativo Web vazio. No entanto, nesta série de tutoriais, você usa o Web Forms projecttemplate, que inclui o sistema ASP.NET Identity. ASP.NET Identity facilita a integração de dados de perfil específicos do usuário aos dados do aplicativo. Além disso, a Identidade ASP.NET permite que você escolha o modelo de persistência para perfis de usuário em seu aplicativo. Você pode armazenar os dados em um banco de dados SQL Server ou em outro armazenamento de dados, incluindo armazenamentos de dados NoSQL, como Tabelas de Armazenamento do Windows Azure.

Este tutorial se baseia no tutorial anterior intitulado "Checkout and Payment with PayPal" na série de tutoriais Wingtip Toys.

O que você aprenderá:

  • Como usar o código para adicionar uma função personalizada e um usuário ao aplicativo.
  • Como restringir o acesso à pasta e à página de administração.
  • Como fornecer navegação para o usuário que pertence à função personalizada.
  • Como usar a associação de modelo para preencher um controle DropDownList com categorias de produto.
  • Como carregar um arquivo no aplicativo Web usando o controle FileUpload .
  • Como usar controles de validação para implementar a validação de entrada.
  • Como adicionar e remover produtos do aplicativo.

Esses recursos estão incluídos no tutorial:

  • ASP.NET Identity
  • Configuração e autorização
  • Model binding
  • Validação não discreta

ASP.NET Web Forms fornece recursos de associação. Usando o modelo padrão, você tem a funcionalidade de associação interna que pode ser usada imediatamente quando o aplicativo é executado. Este tutorial mostra como usar ASP.NET Identity para adicionar uma função personalizada e atribuir um usuário a essa função. Você aprenderá a restringir o acesso à pasta de administração. Você adicionará uma página à pasta de administração que permite que um usuário com uma função personalizada adicione e remova produtos e visualize um produto depois que ele for adicionado.

Adicionando uma função personalizada

Usando ASP.NET Identity, você pode adicionar uma função personalizada e atribuir um usuário a essa função usando código.

  1. Em Gerenciador de Soluções, clique com o botão direito do mouse na pasta Lógica e crie uma nova classe.

  2. Nomeie a nova classe RoleActions.cs.

  3. Modifique o código para que ele apareça da seguinte maneira:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace WingtipToys.Logic
    {
        internal class RoleActions
        {
        }
    }
    
  4. Em Gerenciador de Soluções, abra o arquivo Global.asax.cs.

  5. Modifique o arquivo Global.asax.cs adicionando o código realçado em amarelo para que ele apareça da seguinte maneira:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Optimization;
    using System.Web.Routing;
    using System.Web.Security;
    using System.Web.SessionState;
    using System.Data.Entity;
    using WingtipToys.Models;
    using WingtipToys.Logic;
    
    namespace WingtipToys
    {
        public class Global : HttpApplication
        {
            void Application_Start(object sender, EventArgs e)
            {
              // Code that runs on application startup
              RouteConfig.RegisterRoutes(RouteTable.Routes);
              BundleConfig.RegisterBundles(BundleTable.Bundles);
    
              // Initialize the product database.
              Database.SetInitializer(new ProductDatabaseInitializer());
    
              // Create the custom role and user.
              RoleActions roleActions = new RoleActions();
              roleActions.AddUserAndRole();
            }
        }
    }
    
  6. Observe que AddUserAndRole está sublinhado em vermelho. Clique duas vezes no código AddUserAndRole.
    A letra "A" no início do método realçado será sublinhada.

  7. Passe o mouse sobre a letra "A" e clique na interface do usuário que permite gerar um stub de método para o AddUserAndRole método .

    Associação e administração – Gerar stub de método

  8. Clique na opção intitulada:
    Generate method stub for "AddUserAndRole" in "WingtipToys.Logic.RoleActions"

  9. Abra o arquivo RoleActions.cs na pasta Lógica .
    O AddUserAndRole método foi adicionado ao arquivo de classe.

  10. Modifique o arquivo RoleActions.cs removendo o NotImplementedException e adicionando o código realçado em amarelo, para que ele apareça da seguinte maneira:

    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Linq;
    using System.Web;
    using WingtipToys.Models;
    using Microsoft.AspNet.Identity;
    using Microsoft.AspNet.Identity.EntityFramework;
    
    namespace WingtipToys.Logic
    {
      internal class RoleActions
      {
        internal void AddUserAndRole()
        {
          // Access the application context and create result variables.
          Models.ApplicationDbContext context = new ApplicationDbContext();
          IdentityResult IdRoleResult;
          IdentityResult IdUserResult;
    
          // Create a RoleStore object by using the ApplicationDbContext object. 
          // The RoleStore is only allowed to contain IdentityRole objects.
          var roleStore = new RoleStore<IdentityRole>(context);
    
          // Create a RoleManager object that is only allowed to contain IdentityRole objects.
          // When creating the RoleManager object, you pass in (as a parameter) a new RoleStore object. 
          var roleMgr = new RoleManager<IdentityRole>(roleStore);
    
          // Then, you create the "canEdit" role if it doesn't already exist.
          if (!roleMgr.RoleExists("canEdit"))
          {
            IdRoleResult = roleMgr.Create(new IdentityRole { Name = "canEdit" });
          }
    
          // Create a UserManager object based on the UserStore object and the ApplicationDbContext  
          // object. Note that you can create new objects and use them as parameters in
          // a single line of code, rather than using multiple lines of code, as you did
          // for the RoleManager object.
          var userMgr = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
          var appUser = new ApplicationUser
          {
            UserName = "canEditUser@wingtiptoys.com",
            Email = "canEditUser@wingtiptoys.com"
          };
          IdUserResult = userMgr.Create(appUser, ConfigurationManager.AppSettings["AppUserPasswordKey"]);
    
          // If the new "canEdit" user was successfully created, 
          // add the "canEdit" user to the "canEdit" role. 
          if (!userMgr.IsInRole(userMgr.FindByEmail("canEditUser@wingtiptoys.com").Id, "canEdit"))
          {
            IdUserResult = userMgr.AddToRole(userMgr.FindByEmail("canEditUser@wingtiptoys.com").Id, "canEdit");
          }
        }
      }
    }
    

O código acima primeiro estabelece um contexto de banco de dados para o banco de dados de associação. O banco de dados de associação também é armazenado como um arquivo .mdf na pasta App_Data . Você poderá exibir esse banco de dados depois que o primeiro usuário entrar neste aplicativo Web.

Observação

Se você quiser armazenar os dados de associação junto com os dados do produto, considere usar o mesmo DbContext usado para armazenar os dados do produto no código acima.

O palavra-chave interno é um modificador de acesso para tipos (como classes) e membros de tipo (como métodos ou propriedades). Tipos internos ou membros podem ser acessados somente em arquivos contidos no mesmo assembly (.dll arquivo). Quando você cria seu aplicativo, um arquivo de assembly (.dll) é criado que contém o código executado quando você executa seu aplicativo.

Um RoleStore objeto, que fornece gerenciamento de função, é criado com base no contexto do banco de dados.

Observação

Observe que, quando o RoleStore objeto é criado, ele usa um tipo genérico IdentityRole . Isso significa que o RoleStore só tem permissão para conter IdentityRole objetos. Além disso, usando Genéricos, os recursos na memória são tratados melhor.

Em seguida, o RoleManager objeto é criado com base no RoleStore objeto que você acabou de criar. o objeto expõe a RoleManager API relacionada à função que pode ser usada para salvar automaticamente as alterações no RoleStore. O RoleManager só tem permissão para conter IdentityRole objetos porque o código usa o <IdentityRole> tipo Genérico.

Você chama o RoleExists método para determinar se a função "canEdit" está presente no banco de dados de associação. Se não for, você criará a função.

A criação do UserManager objeto parece ser mais complicada do que o RoleManager controle, no entanto, é quase a mesma coisa. Ele é codificado apenas em uma linha em vez de várias. Aqui, o parâmetro que você está passando é instanciando como um novo objeto contido no parêntese.

Em seguida, você cria o usuário "canEditUser" criando um novo ApplicationUser objeto. Em seguida, se você criar o usuário com êxito, adicione o usuário à nova função.

Observação

O tratamento de erros será atualizado durante o tutorial "tratamento de erros ASP.NET" posteriormente nesta série de tutoriais.

Na próxima vez que o aplicativo for iniciado, o usuário chamado "canEditUser" será adicionado como a função chamada "canEdit" do aplicativo. Posteriormente neste tutorial, você fará logon como o usuário "canEditUser" para exibir recursos adicionais que você adicionará durante este tutorial. Para obter detalhes da API sobre ASP.NET Identity, consulte o Namespace Microsoft.AspNet.Identity. Para obter detalhes adicionais sobre como inicializar o sistema de identidade ASP.NET, consulte AspnetIdentitySample.

Restringindo o acesso à página Administração

O aplicativo de exemplo Wingtip Toys permite que usuários anônimos e usuários conectados exibam e comprem produtos. No entanto, o usuário conectado que tem a função personalizada "canEdit" pode acessar uma página restrita para adicionar e remover produtos.

Adicionar uma pasta e uma página de administração

Em seguida, você criará uma pasta chamada Administração para o usuário "canEditUser" pertencente à função personalizada do aplicativo de exemplo Wingtip Toys.

  1. Clique com o botão direito do mouse no nome do projeto (Wingtip Toys) em Gerenciador de Soluções e selecione Adicionar ->Nova Pasta.
  2. Nomeie a nova pasta Administração.
  3. Clique com o botão direito do mouse na pasta Administração e selecione Adicionar ->Novo Item.
    A caixa de diálogo Adicionar novo item é exibida.
  4. Selecione o grupo Modelos do Visual C#->Web à esquerda. Na lista intermediária, selecione Formulário da Web com Página Mestra, nomeie-o como AdminPage.aspx e, em seguida, selecione Adicionar.
  5. Selecione o arquivo Site.Master como a página master e escolha OK.

Adicionar um arquivo de Web.config

Ao adicionar um arquivo Web.config à pasta Administração, você pode restringir o acesso à página contida na pasta.

  1. Clique com o botão direito do mouse na pasta Administração e selecione Adicionar ->Novo Item.
    A caixa de diálogo Adicionar novo item é exibida.

  2. Na lista de modelos da Web do Visual C#, selecione Arquivo de Configuração da Webna lista intermediária, aceite o nome padrão de Web.confige selecione Adicionar.

  3. Substitua o conteúdo XML existente no arquivo Web.config pelo seguinte:

    <?xml version="1.0"?>
    <configuration>
      <system.web>
        <authorization>
          <allow roles="canEdit"/>
          <deny users="*"/>
        </authorization>
      </system.web>
    </configuration>
    

Salvar o arquivo Web.config. O arquivo Web.config especifica que somente o usuário pertencente à função "canEdit" do aplicativo pode acessar a página contida na pasta Administração.

Incluindo navegação de função personalizada

Para habilitar o usuário da função "canEdit" personalizada para navegar até a seção de administração do aplicativo, você deve adicionar um link à página Site.Master . Somente os usuários que pertencem à função "canEdit" poderão ver o link Administração e acessar a seção de administração.

  1. Em Gerenciador de Soluções, localize e abra a página Site.Master.

  2. Para criar um link para o usuário da função "canEdit", adicione a marcação realçada em amarelo ao seguinte elemento de lista <ul> não ordenado para que a lista apareça da seguinte maneira:

    <ul class="nav navbar-nav">
        <li><a runat="server" id="adminLink" visible="false" 
          href="~/Admin/AdminPage">Admin</a></li>
        <li><a runat="server" href="~/">Home</a></li>
        <li><a runat="server" href="~/About">About</a></li>
        <li><a runat="server" href="~/Contact">Contact</a></li>
        <li><a runat="server" href="~/ProductList">Products</a></li>
        <li><a runat="server" href="~/ShoppingCart" 
          ID="cartCount">&nbsp;</a></li>
    </ul>
    
  3. Abra o arquivo Site.Master.cs . Torne o link Administração visível apenas para o usuário "canEditUser" adicionando o código realçado em amarelo ao Page_Load manipulador. O Page_Load manipulador aparecerá da seguinte maneira:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (HttpContext.Current.User.IsInRole("canEdit"))
        {
            adminLink.Visible = true;
        }
    }
    

Quando a página é carregada, o código verifica se o usuário conectado tem a função de "canEdit". Se o usuário pertencer à função "canEdit", o elemento span que contém o link para a página AdminPage.aspx (e, consequentemente, o link dentro do intervalo) ficará visível.

Habilitando a administração de produtos

Até agora, você criou a função "canEdit" e adicionou um usuário "canEditUser", uma pasta de administração e uma página de administração. Você definiu os direitos de acesso para a pasta e a página de administração e adicionou um link de navegação para o usuário da função "canEdit" ao aplicativo. Em seguida, você adicionará a marcação à página AdminPage.aspx e ao código ao arquivo code-behind AdminPage.aspx.cs que permitirá que o usuário com a função "canEdit" adicione e remova produtos.

  1. Em Gerenciador de Soluções, abra o arquivo AdminPage.aspx da pasta Administração.

  2. Substitua a marcação existente pelo seguinte:

    <%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="AdminPage.aspx.cs" Inherits="WingtipToys.Admin.AdminPage" %>
    <asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
        <h1>Administration</h1>
        <hr />
        <h3>Add Product:</h3>
        <table>
            <tr>
                <td><asp:Label ID="LabelAddCategory" runat="server">Category:</asp:Label></td>
                <td>
                    <asp:DropDownList ID="DropDownAddCategory" runat="server" 
                        ItemType="WingtipToys.Models.Category" 
                        SelectMethod="GetCategories" DataTextField="CategoryName" 
                        DataValueField="CategoryID" >
                    </asp:DropDownList>
                </td>
            </tr>
            <tr>
                <td><asp:Label ID="LabelAddName" runat="server">Name:</asp:Label></td>
                <td>
                    <asp:TextBox ID="AddProductName" runat="server"></asp:TextBox>
                    <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" Text="* Product name required." ControlToValidate="AddProductName" SetFocusOnError="true" Display="Dynamic"></asp:RequiredFieldValidator>
                </td>
            </tr>
            <tr>
                <td><asp:Label ID="LabelAddDescription" runat="server">Description:</asp:Label></td>
                <td>
                    <asp:TextBox ID="AddProductDescription" runat="server"></asp:TextBox>
                    <asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" Text="* Description required." ControlToValidate="AddProductDescription" SetFocusOnError="true" Display="Dynamic"></asp:RequiredFieldValidator>
                </td>
            </tr>
            <tr>
                <td><asp:Label ID="LabelAddPrice" runat="server">Price:</asp:Label></td>
                <td>
                    <asp:TextBox ID="AddProductPrice" runat="server"></asp:TextBox>
                    <asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server" Text="* Price required." ControlToValidate="AddProductPrice" SetFocusOnError="true" Display="Dynamic"></asp:RequiredFieldValidator>
                    <asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server" Text="* Must be a valid price without $." ControlToValidate="AddProductPrice" SetFocusOnError="True" Display="Dynamic" ValidationExpression="^[0-9]*(\.)?[0-9]?[0-9]?$"></asp:RegularExpressionValidator>
                </td>
            </tr>
            <tr>
                <td><asp:Label ID="LabelAddImageFile" runat="server">Image File:</asp:Label></td>
                <td>
                    <asp:FileUpload ID="ProductImage" runat="server" />
                    <asp:RequiredFieldValidator ID="RequiredFieldValidator4" runat="server" Text="* Image path required." ControlToValidate="ProductImage" SetFocusOnError="true" Display="Dynamic"></asp:RequiredFieldValidator>
                </td>
            </tr>
        </table>
        <p></p>
        <p></p>
        <asp:Button ID="AddProductButton" runat="server" Text="Add Product" OnClick="AddProductButton_Click"  CausesValidation="true"/>
        <asp:Label ID="LabelAddStatus" runat="server" Text=""></asp:Label>
        <p></p>
        <h3>Remove Product:</h3>
        <table>
            <tr>
                <td><asp:Label ID="LabelRemoveProduct" runat="server">Product:</asp:Label></td>
                <td><asp:DropDownList ID="DropDownRemoveProduct" runat="server" ItemType="WingtipToys.Models.Product" 
                        SelectMethod="GetProducts" AppendDataBoundItems="true" 
                        DataTextField="ProductName" DataValueField="ProductID" >
                    </asp:DropDownList>
                </td>
            </tr>
        </table>
        <p></p>
        <asp:Button ID="RemoveProductButton" runat="server" Text="Remove Product" OnClick="RemoveProductButton_Click" CausesValidation="false"/>
        <asp:Label ID="LabelRemoveStatus" runat="server" Text=""></asp:Label>
    </asp:Content>
    
  3. Em seguida, abra o arquivo code-behind AdminPage.aspx.cs clicando com o botão direito do mouse em AdminPage.aspx e clicando em Exibir Código.

  4. Substitua o código existente no arquivo code-behind AdminPage.aspx.cs pelo seguinte código:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using WingtipToys.Models;
    using WingtipToys.Logic;
    
    namespace WingtipToys.Admin
    {
      public partial class AdminPage : System.Web.UI.Page
      {
        protected void Page_Load(object sender, EventArgs e)
        {
          string productAction = Request.QueryString["ProductAction"];
          if (productAction == "add")
          {
            LabelAddStatus.Text = "Product added!";
          }
    
          if (productAction == "remove")
          {
            LabelRemoveStatus.Text = "Product removed!";
          }
        }
    
        protected void AddProductButton_Click(object sender, EventArgs e)
        {
          Boolean fileOK = false;
          String path = Server.MapPath("~/Catalog/Images/");
          if (ProductImage.HasFile)
          {
            String fileExtension = System.IO.Path.GetExtension(ProductImage.FileName).ToLower();
            String[] allowedExtensions = { ".gif", ".png", ".jpeg", ".jpg" };
            for (int i = 0; i < allowedExtensions.Length; i++)
            {
              if (fileExtension == allowedExtensions[i])
              {
                fileOK = true;
              }
            }
          }
    
          if (fileOK)
          {
            try
            {
              // Save to Images folder.
              ProductImage.PostedFile.SaveAs(path + ProductImage.FileName);
              // Save to Images/Thumbs folder.
              ProductImage.PostedFile.SaveAs(path + "Thumbs/" + ProductImage.FileName);
            }
            catch (Exception ex)
            {
              LabelAddStatus.Text = ex.Message;
            }
    
            // Add product data to DB.
            AddProducts products = new AddProducts();
            bool addSuccess = products.AddProduct(AddProductName.Text, AddProductDescription.Text,
                AddProductPrice.Text, DropDownAddCategory.SelectedValue, ProductImage.FileName);
            if (addSuccess)
            {
              // Reload the page.
              string pageUrl = Request.Url.AbsoluteUri.Substring(0, Request.Url.AbsoluteUri.Count() - Request.Url.Query.Count());
              Response.Redirect(pageUrl + "?ProductAction=add");
            }
            else
            {
              LabelAddStatus.Text = "Unable to add new product to database.";
            }
          }
          else
          {
            LabelAddStatus.Text = "Unable to accept file type.";
          }
        }
    
        public IQueryable GetCategories()
        {
          var _db = new WingtipToys.Models.ProductContext();
          IQueryable query = _db.Categories;
          return query;
        }
    
        public IQueryable GetProducts()
        {
          var _db = new WingtipToys.Models.ProductContext();
          IQueryable query = _db.Products;
          return query;
        }
    
        protected void RemoveProductButton_Click(object sender, EventArgs e)
        {
          using (var _db = new WingtipToys.Models.ProductContext())
          {
            int productId = Convert.ToInt16(DropDownRemoveProduct.SelectedValue);
            var myItem = (from c in _db.Products where c.ProductID == productId select c).FirstOrDefault();
            if (myItem != null)
            {
              _db.Products.Remove(myItem);
              _db.SaveChanges();
    
              // Reload the page.
              string pageUrl = Request.Url.AbsoluteUri.Substring(0, Request.Url.AbsoluteUri.Count() - Request.Url.Query.Count());
              Response.Redirect(pageUrl + "?ProductAction=remove");
            }
            else
            {
              LabelRemoveStatus.Text = "Unable to locate product.";
            }
          }
        }
      }
    }
    

No código que você inseriu para o arquivo code-behind AdminPage.aspx.cs , uma classe chamada AddProducts faz o trabalho real de adicionar produtos ao banco de dados. Essa classe ainda não existe, portanto, você a criará agora.

  1. Em Gerenciador de Soluções, clique com o botão direito do mouse na pasta Lógica e selecione Adicionar ->Novo Item.
    A caixa de diálogo Adicionar novo item é exibida.

  2. Selecione o grupo de modelos Visual C# ->Code à esquerda. Em seguida, selecione Classena lista intermediária e nomeie-a como AddProducts.cs.
    O novo arquivo de classe é exibido.

  3. Substitua o código existente pelo seguinte:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using WingtipToys.Models;
    
    namespace WingtipToys.Logic
    {
        public class AddProducts
        {
            public bool AddProduct(string ProductName, string ProductDesc, string ProductPrice, string ProductCategory, string ProductImagePath)
            {
                var myProduct = new Product();
                myProduct.ProductName = ProductName;
                myProduct.Description = ProductDesc;
                myProduct.UnitPrice = Convert.ToDouble(ProductPrice);
                myProduct.ImagePath = ProductImagePath;
                myProduct.CategoryID = Convert.ToInt32(ProductCategory);
    
                using (ProductContext _db = new ProductContext())
                {
                    // Add product to DB.
                    _db.Products.Add(myProduct);
                    _db.SaveChanges();
                }
                // Success.
                return true;
            }
        }
    }
    

A página AdminPage.aspx permite que o usuário que pertence à função "canEdit" adicione e remova produtos. Quando um novo produto é adicionado, os detalhes sobre o produto são validados e inseridos no banco de dados. O novo produto está imediatamente disponível para todos os usuários do aplicativo Web.

Validação não discreta

Os detalhes do produto que o usuário fornece na página AdminPage.aspx são validados usando controles de validação (RequiredFieldValidator e RegularExpressionValidator). Esses controles usam automaticamente a validação discreta. A validação não discreta permite que os controles de validação usem JavaScript para a lógica de validação do lado do cliente, o que significa que a página não requer uma viagem ao servidor para ser validada. Por padrão, a validação não discreta é incluída no arquivo Web.config com base na seguinte configuração:

<add key="ValidationSettings:UnobtrusiveValidationMode" value="WebForms" />

Expressões regulares

O preço do produto na página AdminPage.aspx é validado usando um controle RegularExpressionValidator . Esse controle valida se o valor do controle de entrada associado (a Caixa de Texto "AddProductPrice") corresponde ao padrão especificado pela expressão regular. Uma expressão regular é uma notação de correspondência de padrões que permite localizar e corresponder rapidamente a padrões de caracteres específicos. O controle RegularExpressionValidator inclui uma propriedade chamada ValidationExpression que contém a expressão regular usada para validar a entrada de preço, conforme mostrado abaixo:

<asp:RegularExpressionValidator 
    ID="RegularExpressionValidator1" runat="server"
    Text="* Must be a valid price without $." ControlToValidate="AddProductPrice" 
    SetFocusOnError="True" Display="Dynamic" 
    ValidationExpression="^[0-9]*(\.)?[0-9]?[0-9]?$">
</asp:RegularExpressionValidator>

Controle FileUpload

Além dos controles de entrada e validação, você adicionou o controle FileUpload à página AdminPage.aspx . Esse controle fornece a capacidade de carregar arquivos. Nesse caso, você só está permitindo que arquivos de imagem sejam carregados. No arquivo code-behind (AdminPage.aspx.cs), quando o AddProductButton é clicado, o código verifica a HasFile propriedade do controle FileUpload . Se o controle tiver um arquivo e se o tipo de arquivo (com base na extensão de arquivo) for permitido, a imagem será salva na pasta Imagens e na pasta Imagens/Polegares do aplicativo.

Model binding

Anteriormente nesta série de tutoriais, você usou a associação de modelo para preencher um controle ListView , um controle FormsView , um controle GridView e um controle DetailView . Neste tutorial, você usa a associação de modelo para preencher um controle DropDownList com uma lista de categorias de produtos.

A marcação que você adicionou ao arquivo AdminPage.aspx contém um controle DropDownList chamado DropDownAddCategory:

<asp:DropDownList ID="DropDownAddCategory" runat="server" 
        ItemType="WingtipToys.Models.Category" 
        SelectMethod="GetCategories" DataTextField="CategoryName" 
        DataValueField="CategoryID" >
    </asp:DropDownList>

Você usa a associação de modelo para preencher esse DropDownList definindo o ItemType atributo e o SelectMethod atributo . O ItemType atributo especifica que você usa o WingtipToys.Models.Category tipo ao preencher o controle. Você definiu esse tipo no início desta série de tutoriais criando a Category classe (mostrada abaixo). A Category classe está na pasta Modelos dentro do arquivo Category.cs .

public class Category
{
    [ScaffoldColumn(false)]
    public int CategoryID { get; set; }

    [Required, StringLength(100), Display(Name = "Name")]
    public string CategoryName { get; set; }

    [Display(Name = "Product Description")]
    public string Description { get; set; }

    public virtual ICollection<Product> Products { get; set; }
}

O SelectMethod atributo do controle DropDownList especifica que você usa o GetCategories método (mostrado abaixo) incluído no arquivo code-behind (AdminPage.aspx.cs).

public IQueryable GetCategories()
{
  var _db = new WingtipToys.Models.ProductContext();
  IQueryable query = _db.Categories;
  return query;
}

Esse método especifica que uma IQueryable interface é usada para avaliar uma consulta em relação a um Category tipo. O valor retornado é usado para preencher o DropDownList na marcação da página (AdminPage.aspx).

O texto exibido para cada item na lista é especificado definindo o DataTextField atributo . O DataTextField atributo usa o CategoryName da Category classe (mostrado acima) para exibir cada categoria no controle DropDownList . O valor real que é passado quando um item é selecionado no controle DropDownList é baseado no DataValueField atributo . O DataValueField atributo é definido como o CategoryID conforme definido na Category classe (mostrado acima).

Como o aplicativo funcionará

Quando o usuário pertencente à função "canEdit" navega para a página pela primeira vez, o DropDownAddCategory controle DropDownList é preenchido conforme descrito acima. O DropDownRemoveProduct controle DropDownList também é preenchido com produtos que usam a mesma abordagem. O usuário que pertence à função "canEdit" seleciona o tipo de categoria e adiciona detalhes do produto (Nome, Descrição, Preço e Arquivo de Imagem). Quando o usuário que pertence à função "canEdit" clica no botão Adicionar Produto , o AddProductButton_Click manipulador de eventos é disparado. O AddProductButton_Click manipulador de eventos localizado no arquivo code-behind (AdminPage.aspx.cs) verifica o arquivo de imagem para garantir que ele corresponda aos tipos de arquivo permitidos (.gif, .png, .jpeg ou .jpg). Em seguida, o arquivo de imagem é salvo em uma pasta do aplicativo de exemplo Wingtip Toys. Em seguida, o novo produto é adicionado ao banco de dados. Para fazer a adição de um novo produto, uma nova instância da AddProducts classe é criada e nomeada produtos. A AddProducts classe tem um método chamado AddProduct, e o objeto products chama esse método para adicionar produtos ao banco de dados.

// Add product data to DB.
AddProducts products = new AddProducts();
bool addSuccess = products.AddProduct(AddProductName.Text, AddProductDescription.Text,
    AddProductPrice.Text, DropDownAddCategory.SelectedValue, ProductImage.FileName);

Se o código adicionar com êxito o novo produto ao banco de dados, a página será recarregada com o valor ProductAction=addda cadeia de caracteres de consulta .

Response.Redirect(pageUrl + "?ProductAction=add");

Quando a página é recarregada, a cadeia de caracteres de consulta é incluída na URL. Ao recarregar a página, o usuário que pertence à função "canEdit" pode ver imediatamente as atualizações nos controles DropDownList na página AdminPage.aspx . Além disso, incluindo a cadeia de caracteres de consulta com a URL, a página pode exibir uma mensagem de êxito para o usuário que pertence à função "canEdit".

Quando a página AdminPage.aspx é recarregada, o Page_Load evento é chamado.

protected void Page_Load(object sender, EventArgs e)
{
    string productAction = Request.QueryString["ProductAction"];
    if (productAction == "add")
    {
        LabelAddStatus.Text = "Product added!";
    }

    if (productAction == "remove")
    {
        LabelRemoveStatus.Text = "Product removed!";
    }
}

O Page_Load manipulador de eventos verifica o valor da cadeia de caracteres de consulta e determina se deve mostrar uma mensagem de êxito.

Executando o aplicativo

Agora você pode executar o aplicativo para ver como pode adicionar, excluir e atualizar itens no carrinho de compras. O total do carrinho de compras refletirá o custo total de todos os itens no carrinho de compras.

  1. Em Gerenciador de Soluções, pressione F5 para executar o aplicativo de exemplo Wingtip Toys.
    O navegador é aberto e mostra a página Default.aspx .

  2. Clique no link Fazer logon na parte superior da página.

    Associação e administração – Link de logon

    A página Login.aspx é exibida.

  3. Digite um nome de usuário e uma senha.

    Associação e Administração – Página de Logon

  4. Clique no botão Fazer logon próximo à parte inferior da página.

  5. Na parte superior da próxima página, selecione o link Administração para navegar até a página AdminPage.aspx.

    Associação e Administração – Link Administração

  6. Para testar a validação de entrada, clique no botão Adicionar Produto sem adicionar detalhes do produto.

    Associação e Administração – Página Administração

    Observe que as mensagens de campo necessárias são exibidas.

  7. Adicione os detalhes de um novo produto e clique no botão Adicionar Produto .

    Associação e Administração – Adicionar Produto

  8. Selecione Produtos no menu de navegação superior para exibir o novo produto que você adicionou.

    Associação e administração – Mostrar novo produto

  9. Clique no link Administração para retornar à página de administração.

  10. Na seção Remover Produto da página, selecione o novo produto que você adicionou no DropDownListBox.

  11. Clique no botão Remover Produto para remover o novo produto do aplicativo.

    Associação e Administração – Remover Produto

  12. Selecione Produtos no menu de navegação superior para confirmar se o produto foi removido.

  13. Clique em Fazer logoff para existir no modo de administração.
    Observe que o painel de navegação superior não mostra mais o item de menu Administração.

Resumo

Neste tutorial, você adicionou uma função personalizada e um usuário que pertence à função personalizada, restringiu o acesso à pasta e à página de administração e forneceu navegação para o usuário que pertence à função personalizada. Você usou a model binding para preencher um controle DropDownList com dados. Você implementou o controle FileUpload e os controles de validação. Além disso, você aprendeu a adicionar e remover produtos de um banco de dados. No próximo tutorial, você aprenderá a implementar ASP.NET roteamento.

Recursos adicionais

Web.config – Elemento authorization
ASP.NET Identity
Implantar um aplicativo de ASP.NET Web Forms seguro com associação, OAuth e Banco de Dados SQL em um site do Azure
Microsoft Azure – Avaliação gratuita