Appartenenza e amministrazione

di Erik Reitan

Questa serie di esercitazioni illustra le nozioni di base per la creazione di un'applicazione Web Forms ASP.NET usando ASP.NET 4.5 e Microsoft Visual Studio Express 2013 per Web. Per questa serie di esercitazioni è disponibile un progetto di Visual Studio 2013 con codice sorgente C#.

Questa esercitazione illustra come aggiornare l'applicazione di esempio Wingtip Toys per aggiungere un ruolo personalizzato e usare ASP.NET Identity. Viene inoltre illustrato come implementare una pagina di amministrazione da cui l'utente con un ruolo personalizzato può aggiungere e rimuovere prodotti dal sito Web.

ASP.NET Identity è il sistema di appartenenza usato per compilare ASP.NET'applicazione Web ed è disponibile in ASP.NET 4.5. ASP.NET Identity viene usato nel modello di progetto Visual Studio 2013 Web Forms, nonché nei modelli per ASP.NET MVC, API Web ASP.NET e ASP.NET'applicazione a pagina singola. È anche possibile installare in modo specifico il sistema di identità ASP.NET usando NuGet quando si inizia con un'applicazione Web vuota. Tuttavia, in questa serie di esercitazioni si usa il Web Forms projecttemplate, che include il sistema di identità ASP.NET. ASP.NET Identity semplifica l'integrazione dei dati di profilo specifici dell'utente con i dati dell'applicazione. ASP.NET Identity consente inoltre di scegliere il modello di persistenza dei profili utente nell'applicazione. È possibile archiviare i dati in un database SQL Server o in un altro archivio dati, inclusi gli archivi dati NoSQL, ad esempio tabelle di archiviazione di Windows Azure.

Questa esercitazione si basa sull'esercitazione precedente intitolata "Checkout and Payment with PayPal" (Pagamento e pagamento con PayPal) nella serie di esercitazioni wingtip Toys.

Contenuto dell'esercitazione:

  • Come usare il codice per aggiungere un ruolo personalizzato e un utente all'applicazione.
  • Come limitare l'accesso alla cartella e alla pagina di amministrazione.
  • Come fornire lo spostamento per l'utente appartenente al ruolo personalizzato.
  • Come usare l'associazione di modelli per popolare un controllo DropDownList con categorie di prodotti.
  • Come caricare un file nell'applicazione Web usando il controllo FileUpload .
  • Come usare i controlli di convalida per implementare la convalida dell'input.
  • Come aggiungere e rimuovere prodotti dall'applicazione.

Queste funzionalità sono incluse nell'esercitazione:

  • Identità ASP.NET
  • Configurazione e autorizzazione
  • Associazione di modelli
  • Convalida non invasiva

Web Forms ASP.NET offre funzionalità di appartenenza. Usando il modello predefinito, sono disponibili funzionalità di appartenenza predefinite che è possibile usare immediatamente quando viene eseguita l'applicazione. Questa esercitazione illustra come usare ASP.NET Identity per aggiungere un ruolo personalizzato e assegnare un utente a tale ruolo. Si apprenderà come limitare l'accesso alla cartella di amministrazione. Si aggiungerà una pagina alla cartella di amministrazione che consente a un utente con un ruolo personalizzato di aggiungere e rimuovere prodotti e di visualizzare in anteprima un prodotto dopo l'aggiunta.

Aggiunta di un ruolo personalizzato

Usando ASP.NET Identity, è possibile aggiungere un ruolo personalizzato e assegnare un utente a tale ruolo usando il codice.

  1. In Esplora soluzioni fare clic con il pulsante destro del mouse sulla cartella Logica e creare una nuova classe.

  2. Assegnare alla nuova classe il nome RoleActions.cs.

  3. Modificare il codice in modo che venga visualizzato come segue:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace WingtipToys.Logic
    {
        internal class RoleActions
        {
        }
    }
    
  4. In Esplora soluzioni aprire il file Global.asax.cs.

  5. Modificare il file Global.asax.cs aggiungendo il codice evidenziato in giallo in modo che venga visualizzato come segue:

    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. Si noti che AddUserAndRole è sottolineato in rosso. Fare doppio clic sul codice AddUserAndRole.
    La lettera "A" all'inizio del metodo evidenziato verrà sottolineata.

  7. Passare il puntatore sulla lettera "A" e fare clic sull'interfaccia utente che consente di generare uno stub del metodo per il AddUserAndRole metodo .

    Appartenenza e amministrazione - Generare lo stub del metodo

  8. Fare clic sull'opzione intitolata:
    Generate method stub for "AddUserAndRole" in "WingtipToys.Logic.RoleActions"

  9. Aprire il file RoleActions.cs dalla cartella Logic .
    Il AddUserAndRole metodo è stato aggiunto al file di classe.

  10. Modificare il file RoleActions.cs rimuovendo NotImplementedException e aggiungendo il codice evidenziato in giallo, in modo che venga visualizzato come segue:

    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");
          }
        }
      }
    }
    

Il codice precedente stabilisce innanzitutto un contesto di database per il database di appartenenza. Il database di appartenenza viene archiviato anche come file mdf nella cartella App_Data . Sarà possibile visualizzare questo database dopo che il primo utente ha eseguito l'accesso a questa applicazione Web.

Nota

Se si desidera archiviare i dati di appartenenza insieme ai dati del prodotto, è possibile usare lo stesso DbContext usato per archiviare i dati del prodotto nel codice precedente.

La parola chiave internal è un modificatore di accesso per i tipi (ad esempio le classi) e i membri del tipo (ad esempio metodi o proprietà). I tipi o i membri interni sono accessibili solo all'interno di file contenuti nello stesso assembly (.dll file). Quando si compila l'applicazione, viene creato un file di assembly (.dll) che contiene il codice eseguito quando si esegue l'applicazione.

Un RoleStore oggetto, che fornisce la gestione dei ruoli, viene creato in base al contesto del database.

Nota

Si noti che quando viene creato l'oggetto RoleStore usa un tipo Generic IdentityRole . Ciò significa che l'oggetto RoleStore è autorizzato a contenere IdentityRole solo oggetti. Usando anche i generics, le risorse in memoria vengono gestite meglio.

Successivamente, l'oggetto RoleManager viene creato in base all'oggetto RoleStore appena creato. L'oggetto espone l'API RoleManager correlata al ruolo che può essere usata per salvare automaticamente le modifiche apportate a RoleStore. È RoleManager consentito contenere IdentityRole solo oggetti perché il codice usa il <IdentityRole> tipo Generic.

Chiamare il RoleExists metodo per determinare se il ruolo "canEdit" è presente nel database di appartenenza. In caso contrario, si crea il ruolo.

La creazione dell'oggetto UserManager sembra essere più complessa del RoleManager controllo, ma è quasi la stessa. È semplicemente codificato su una riga anziché su più. In questo caso, il parametro che si sta passando crea un'istanza come nuovo oggetto contenuto tra parentesi.

Creare quindi l'utente "canEditUser" creando un nuovo ApplicationUser oggetto. Quindi, se l'utente viene creato correttamente, si aggiunge l'utente al nuovo ruolo.

Nota

La gestione degli errori verrà aggiornata durante l'esercitazione "gestione degli errori ASP.NET" più avanti in questa serie di esercitazioni.

Al successivo avvio dell'applicazione, l'utente denominato "canEditUser" verrà aggiunto come ruolo denominato "canEdit" dell'applicazione. Più avanti in questa esercitazione si accederà come utente "canEditUser" per visualizzare funzionalità aggiuntive che verranno aggiunte durante questa esercitazione. Per informazioni dettagliate sull'API su ASP.NET Identity, vedere spazio dei nomi Microsoft.AspNet.Identity. Per altri dettagli sull'inizializzazione del sistema di identità ASP.NET, vedere AspnetIdentitySample.

Limitazione dell'accesso alla pagina Amministrazione

L'applicazione di esempio Wingtip Toys consente sia agli utenti anonimi che agli utenti connessi di visualizzare e acquistare prodotti. Tuttavia, l'utente connesso con il ruolo personalizzato "canEdit" può accedere a una pagina con restrizioni per aggiungere e rimuovere prodotti.

Aggiungere una cartella e una pagina di amministrazione

Verrà quindi creata una cartella denominata Amministrazione per l'utente "canEditUser" appartenente al ruolo personalizzato dell'applicazione di esempio Wingtip Toys.

  1. Fare clic con il pulsante destro del mouse sul nome del progetto (Wingtip Toys) in Esplora soluzioni e scegliere Aggiungi ->Nuova cartella.
  2. Denominare la nuova cartella Amministrazione.
  3. Fare clic con il pulsante destro del mouse sulla cartella Amministrazione e quindi scegliere Aggiungi ->Nuovo elemento.
    La finestra di dialogo Aggiungi nuovo elemento viene visualizzata.
  4. Selezionare il gruppo Visual C#-Web templates ( Modelli Visual C#->Web ) a sinistra. Nell'elenco centrale selezionare Web Form con pagina master, denominarlo AdminPage.aspxe quindi selezionare Aggiungi.
  5. Selezionare il file Site.Master come pagina master e quindi scegliere OK.

Aggiungere un file di Web.config

Aggiungendo un file Web.config alla cartella Amministrazione, è possibile limitare l'accesso alla pagina contenuta nella cartella .

  1. Fare clic con il pulsante destro del mouse sulla cartella Amministrazione e scegliere Aggiungi ->Nuovo elemento.
    La finestra di dialogo Aggiungi nuovo elemento viene visualizzata.

  2. Nell'elenco dei modelli Web di Visual C# selezionare File di configurazione Webnell'elenco centrale, accettare il nome predefinito di Web.confige quindi selezionare Aggiungi.

  3. Sostituire il contenuto XML esistente nel file Web.config con il contenuto seguente:

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

Salvare il file Web.config. Il file Web.config specifica che solo l'utente appartenente al ruolo "canEdit" dell'applicazione può accedere alla pagina contenuta nella cartella Amministrazione.

Inclusione dello spostamento di ruoli personalizzati

Per consentire all'utente del ruolo personalizzato "canEdit" di passare alla sezione di amministrazione dell'applicazione, è necessario aggiungere un collegamento alla pagina Site.Master . Solo gli utenti che appartengono al ruolo "canEdit" potranno visualizzare il collegamento Amministrazione e accedere alla sezione amministrazione.

  1. In Esplora soluzioni trovare e aprire la pagina Site.Master.

  2. Per creare un collegamento per l'utente del ruolo "canEdit", aggiungere il markup evidenziato in giallo all'elemento elenco <ul> non ordinato seguente in modo che l'elenco venga visualizzato come segue:

    <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. Aprire il file Site.Master.cs . Rendere visibile il collegamento Amministrazione solo all'utente "canEditUser" aggiungendo il codice evidenziato in giallo al Page_Load gestore. Il Page_Load gestore verrà visualizzato come segue:

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

Quando la pagina viene caricata, il codice controlla se l'utente connesso ha il ruolo "canEdit". Se l'utente appartiene al ruolo "canEdit", l'elemento span contenente il collegamento alla pagina AdminPage.aspx (e di conseguenza il collegamento all'interno dell'intervallo) viene reso visibile.

Abilitazione dell'amministrazione del prodotto

Finora è stato creato il ruolo "canEdit" e è stato aggiunto un utente "canEditUser", una cartella di amministrazione e una pagina di amministrazione. Sono stati impostati i diritti di accesso per la cartella e la pagina di amministrazione e sono stati aggiunti un collegamento di spostamento per l'utente del ruolo "canEdit" all'applicazione. Successivamente, si aggiungerà markup alla pagina AdminPage.aspx e al codice al file code-behind AdminPage.aspx.cs che consentirà all'utente con il ruolo "canEdit" di aggiungere e rimuovere prodotti.

  1. In Esplora soluzioni aprire il file AdminPage.aspx dalla cartella Amministrazione.

  2. Sostituire il markup esistente con il codice seguente:

    <%@ 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. Aprire quindi il file code-behind AdminPage.aspx.cs facendo clic con il pulsante destro del mouse su AdminPage.aspx e scegliendo Visualizza codice.

  4. Sostituire il codice esistente nel file code-behind AdminPage.aspx.cs con il codice seguente:

    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.";
            }
          }
        }
      }
    }
    

Nel codice immesso per il file code-behind AdminPage.aspx.cs , una classe denominata AddProducts esegue il lavoro effettivo dell'aggiunta di prodotti al database. Questa classe non esiste ancora, quindi verrà creata ora.

  1. In Esplora soluzioni fare clic con il pulsante destro del mouse sulla cartella Logica e quindi scegliere Aggiungi ->Nuovo elemento.
    La finestra di dialogo Aggiungi nuovo elemento viene visualizzata.

  2. Selezionare il gruppo Visual C# -Code templates (Modelli di Visual C# ->Code ) a sinistra. Selezionare quindi Classedall'elenco centrale e denominarla AddProducts.cs.
    Viene visualizzato il nuovo file di classe.

  3. Sostituire il codice esistente con quello seguente:

    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;
            }
        }
    }
    

La pagina AdminPage.aspx consente all'utente appartenente al ruolo "canEdit" di aggiungere e rimuovere prodotti. Quando viene aggiunto un nuovo prodotto, i dettagli sul prodotto vengono convalidati e quindi immessi nel database. Il nuovo prodotto è immediatamente disponibile per tutti gli utenti dell'applicazione Web.

Convalida non invasiva

I dettagli del prodotto forniti dall'utente nella pagina AdminPage.aspx vengono convalidati usando i controlli di convalida (RequiredFieldValidator e RegularExpressionValidator). Questi controlli usano automaticamente la convalida non invasiva. La convalida non invasiva consente ai controlli di convalida di usare JavaScript per la logica di convalida lato client, il che significa che la pagina non richiede la convalida di un viaggio al server. Per impostazione predefinita, la convalida non invasiva viene inclusa nel file Web.config in base all'impostazione di configurazione seguente:

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

Espressioni regolari

Il prezzo del prodotto nella pagina AdminPage.aspx viene convalidato usando un controllo RegularExpressionValidator . Questo controllo verifica se il valore del controllo di input associato (il controllo TextBox "AddProductPrice" corrisponde al criterio specificato dall'espressione regolare. Un'espressione regolare è una notazione basata su criteri di ricerca che consente di trovare e trovare rapidamente modelli di carattere specifici. Il controllo RegularExpressionValidator include una proprietà denominata ValidationExpression che contiene l'espressione regolare usata per convalidare l'input del prezzo, come illustrato di seguito:

<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>

Controllo FileUpload

Oltre ai controlli di input e convalida, è stato aggiunto il controllo FileUpload alla pagina AdminPage.aspx . Questo controllo offre la possibilità di caricare i file. In questo caso, è possibile caricare solo i file di immagine. Quando si fa clic sul file code-behind (AdminPage.aspx.cs), AddProductButton il codice controlla la HasFile proprietà del controllo FileUpload . Se il controllo ha un file e se il tipo di file (in base all'estensione di file) è consentito, l'immagine viene salvata nella cartella Images e nella cartella Images/Thumbs dell'applicazione.

Associazione di modelli

In precedenza in questa serie di esercitazioni è stata usata l'associazione di modelli per popolare un controllo ListView , un controllo FormsView , un controllo GridView e un controllo DetailView . In questa esercitazione si usa l'associazione di modelli per popolare un controllo DropDownList con un elenco di categorie di prodotti.

Il markup aggiunto al file AdminPage.aspx contiene un controllo DropDownList denominato DropDownAddCategory:

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

Per popolare l'oggetto DropDownList , usare l'associazione di modelli impostando l'attributo ItemType e l'attributo SelectMethod . L'attributo ItemType specifica che si utilizza il WingtipToys.Models.Category tipo durante il popolamento del controllo. Questo tipo è stato definito all'inizio di questa serie di esercitazioni creando la Category classe (illustrata di seguito). La Category classe si trova nella cartella Models all'interno del file 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; }
}

L'attributo SelectMethod del controllo DropDownList specifica che si usa il GetCategories metodo (illustrato di seguito) incluso nel file code-behind (AdminPage.aspx.cs).

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

Questo metodo specifica che un'interfaccia IQueryable viene utilizzata per valutare una query su un Category tipo. Il valore restituito viene usato per popolare DropDownList nel markup della pagina (AdminPage.aspx).

Il testo visualizzato per ogni elemento nell'elenco viene specificato impostando l'attributo DataTextField . L'attributo DataTextField usa l'oggetto CategoryName della Category classe (illustrato sopra) per visualizzare ogni categoria nel controllo DropDownList . Il valore effettivo passato quando viene selezionato un elemento nel controllo DropDownList è basato sull'attributo DataValueField . L'attributo DataValueFieldCategoryID è impostato su come definire nella Category classe (illustrato sopra).

Funzionamento dell'applicazione

Quando l'utente appartenente al ruolo "canEdit" passa alla pagina per la prima volta, il DropDownAddCategory controllo DropDownList viene popolato come descritto in precedenza. Il DropDownRemoveProduct controllo DropDownList viene popolato anche con prodotti che usano lo stesso approccio. L'utente appartenente al ruolo "canEdit" seleziona il tipo di categoria e aggiunge i dettagli del prodotto (Nome, Descrizione, Prezzo e File immagine). Quando l'utente appartenente al ruolo "canEdit" fa clic sul pulsante Aggiungi prodotto , viene attivato il AddProductButton_Click gestore eventi. Il AddProductButton_Click gestore eventi che si trova nel file code-behind (AdminPage.aspx.cs) controlla il file di immagine per assicurarsi che corrisponda ai tipi di file consentiti (.gif, .png, .jpeg o .jpg). Il file di immagine viene quindi salvato in una cartella dell'applicazione di esempio Wingtip Toys. Successivamente, il nuovo prodotto viene aggiunto al database. Per aggiungere un nuovo prodotto, viene creata e denominata products una nuova istanza della AddProducts classe . La AddProducts classe ha un metodo denominato AddProducte l'oggetto products chiama questo metodo per aggiungere prodotti al database.

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

Se il codice aggiunge correttamente il nuovo prodotto al database, la pagina viene ricaricata con il valore ProductAction=adddella stringa di query .

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

Quando la pagina viene ricaricata, la stringa di query viene inclusa nell'URL. Ricaricando la pagina, l'utente appartenente al ruolo "canEdit" può visualizzare immediatamente gli aggiornamenti nei controlli DropDownList nella pagina AdminPage.aspx . Includendo anche la stringa di query con l'URL, la pagina può visualizzare un messaggio di operazione riuscita all'utente appartenente al ruolo "canEdit".

Quando la pagina AdminPage.aspx viene ricaricata, viene chiamato l'evento Page_Load .

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!";
    }
}

Il Page_Load gestore eventi controlla il valore della stringa di query e determina se visualizzare un messaggio di operazione riuscita.

Esecuzione dell'applicazione

È ora possibile eseguire l'applicazione per vedere come è possibile aggiungere, eliminare e aggiornare gli elementi nel carrello acquisti. Il totale del carrello acquisti rifletterà il costo totale di tutti gli articoli nel carrello acquisti.

  1. In Esplora soluzioni premere F5 per eseguire l'applicazione di esempio Wingtip Toys.
    Il browser si apre e mostra la pagina Default.aspx .

  2. Fare clic sul collegamento Accedi nella parte superiore della pagina.

    Appartenenza e amministrazione - Collegamento di accesso

    Viene visualizzata la pagina Login.aspx .

  3. Immettere il nome utente e la password.

    Appartenenza e amministrazione - Pagina Accesso

  4. Fare clic sul pulsante Accedi nella parte inferiore della pagina.

  5. Nella parte superiore della pagina successiva selezionare il collegamento Amministrazione per passare alla pagina AdminPage.aspx.

    Appartenenza e amministrazione - Collegamento Amministrazione

  6. Per testare la convalida dell'input, fare clic sul pulsante Aggiungi prodotto senza aggiungere dettagli sul prodotto.

    Appartenenza e amministrazione - pagina Amministrazione

    Si noti che vengono visualizzati i messaggi di campo obbligatori.

  7. Aggiungere i dettagli per un nuovo prodotto e quindi fare clic sul pulsante Aggiungi prodotto .

    Appartenenza e amministrazione - Aggiungi prodotto

  8. Selezionare Prodotti dal menu di spostamento superiore per visualizzare il nuovo prodotto aggiunto.

    Appartenenza e amministrazione - Mostra nuovo prodotto

  9. Fare clic sul collegamento Amministrazione per tornare alla pagina di amministrazione.

  10. Nella sezione Rimuovi prodotto della pagina selezionare il nuovo prodotto aggiunto in DropDownListBox.

  11. Fare clic sul pulsante Rimuovi prodotto per rimuovere il nuovo prodotto dall'applicazione.

    Appartenenza e amministrazione - Rimuovi prodotto

  12. Selezionare Prodotti dal menu di spostamento superiore per verificare che il prodotto sia stato rimosso.

  13. Fare clic su Disconnettersi per esistere la modalità di amministrazione.
    Si noti che il riquadro di spostamento superiore non visualizza più la voce di menu Amministrazione.

Riepilogo

In questa esercitazione sono stati aggiunti un ruolo personalizzato e un utente appartenente al ruolo personalizzato, l'accesso limitato alla cartella e alla pagina di amministrazione e sono stati forniti gli spostamenti per l'utente appartenente al ruolo personalizzato. È stata usata l'associazione di modelli per popolare un controllo DropDownList con i dati. Sono stati implementati i controlli di convalida e controllo FileUpload . Si è inoltre appreso come aggiungere e rimuovere prodotti da un database. Nell'esercitazione successiva si apprenderà come implementare ASP.NET routing.

Risorse aggiuntive

Web.config - Elemento authorization
Identità ASP.NET
Distribuire un'app di Web Forms ASP.NET sicura con appartenenza, OAuth e database SQL in un sito Web di Azure
Microsoft Azure - Versione di valutazione gratuita