Поделиться через


Членство и администрирование

Эрик Рейтан (Erik Reitan)

В этой серии учебников вы узнаете об основах создания приложения ASP.NET Web Forms с помощью ASP.NET 4.5 и Microsoft Visual Studio Express 2013 для Интернета. В этой серии руководств доступен проект Visual Studio 2013 с исходным кодом C#.

В этом руководстве показано, как обновить пример приложения Wingtip Toys, чтобы добавить пользовательскую роль и использовать ASP.NET Identity. Здесь также показано, как реализовать страницу администрирования, с которой пользователь с настраиваемой ролью может добавлять и удалять продукты с веб-сайта.

ASP.NET Identity — это система членства, используемая для создания веб-приложения ASP.NET и доступная в ASP.NET 4.5. ASP.NET Identity используется в шаблоне проекта Visual Studio 2013 веб-формы, а также в шаблонах для ASP.NET MVC, веб-API ASP.NET и ASP.NET одностраничного приложения. Вы также можете установить систему удостоверений ASP.NET с помощью NuGet при запуске с пустым веб-приложением. Однако в этой серии руководств вы используете веб-формы projecttemplate, включающую систему ASP.NET Identity. ASP.NET Identity упрощает интеграцию данных профиля пользователя с данными приложения. Кроме того, ASP.NET Identity позволяет выбирать модель сохраняемости для профилей пользователей в приложении. Данные можно хранить в SQL Server базе данных или другом хранилище данных, включая хранилища данных NoSQL, такие как таблицы службы хранилища Windows Azure.

Этот учебник основан на предыдущем руководстве под названием "Извлечение и оплата с помощью PayPal" в серии учебников Wingtip Toys.

Из этого руководства вы узнаете, как выполнять такие задачи:

  • Использование кода для добавления пользовательской роли и пользователя в приложение.
  • Как ограничить доступ к папке и странице администрирования.
  • Как обеспечить навигацию для пользователя, который принадлежит к настраиваемой роли.
  • Использование привязки модели для заполнения элемента управления DropDownList категориями продуктов.
  • Отправка файла в веб-приложение с помощью элемента управления FileUpload .
  • Использование элементов управления для реализации проверки входных данных.
  • Добавление и удаление продуктов из приложения.

В этом руководстве содержатся следующие функции:

  • ASP.NET Identity
  • Настройка и авторизация
  • Привязка модели
  • Ненавязчивая проверка

ASP.NET Web Forms предоставляет возможности членства. Используя шаблон по умолчанию, у вас есть встроенные функции членства, которые можно использовать сразу при запуске приложения. В этом руководстве показано, как с помощью ASP.NET Identity добавить пользовательскую роль и назначить ей пользователя. Вы узнаете, как ограничить доступ к папке администрирования. Вы добавите в папку администрирования страницу, которая позволяет пользователю с настраиваемой ролью добавлять и удалять продукты, а также просматривать продукт после его добавления.

Добавление настраиваемой роли

С помощью ASP.NET Identity можно добавить пользовательскую роль и назначить ей пользователя с помощью кода.

  1. В Обозреватель решений щелкните правой кнопкой мыши папку Логика и создайте класс.

  2. Назовите новый класс RoleActions.cs.

  3. Измените код так, чтобы он выглядел следующим образом:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace WingtipToys.Logic
    {
        internal class RoleActions
        {
        }
    }
    
  4. В Обозреватель решений откройте файл Global.asax.cs.

  5. Измените файл Global.asax.cs , добавив выделенный желтым цветом код, чтобы он выглядел следующим образом:

    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. Обратите внимание, что выражение AddUserAndRole подчеркнуто красной чертой. Дважды щелкните код AddUserAndRole.
    Буква "A" в начале выделенного метода будет подчеркнута.

  7. Наведите указатель мыши на букву "A" и щелкните пользовательский интерфейс, который позволяет создать заглушку метода для AddUserAndRole метода.

    Членство и администрирование — создание заглушки метода

  8. Выберите параметр с заголовком:
    Generate method stub for "AddUserAndRole" in "WingtipToys.Logic.RoleActions"

  9. Откройте файл RoleActions.cs из папки Логика .
    Метод AddUserAndRole добавлен в файл класса.

  10. Измените файл RoleActions.cs , удалив NotImplementedException и добавив код, выделенный желтым цветом, чтобы он выглядел следующим образом:

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

Приведенный выше код сначала устанавливает контекст базы данных для базы данных членства. База данных членства также хранится в виде MDF-файла в папке App_Data . Вы сможете просмотреть эту базу данных после того, как первый пользователь войдет в это веб-приложение.

Примечание

Если вы хотите сохранить данные членства вместе с данными о продукте, можно использовать тот же DbContext , который использовался для хранения данных продукта в приведенном выше коде.

Внутренний ключевое слово является модификатором доступа для типов (например, классов) и членов типов (таких как методы или свойства). Внутренние типы или члены доступны только в файлах, содержащихся в одной сборке (.dll файле). При сборке приложения создается файл сборки (.dll), содержащий код, выполняемый при запуске приложения.

Объект RoleStore , обеспечивающий управление ролями, создается на основе контекста базы данных.

Примечание

Обратите внимание, что при RoleStore создании объекта используется универсальный IdentityRole тип. Это означает, что объект RoleStore может содержать IdentityRole только объекты . Кроме того, с помощью универсальных шаблонов ресурсы в памяти обрабатываются лучше.

RoleManager Затем объект создается на основе только что созданного RoleStore объекта. RoleManager объект предоставляет API, связанный с ролью, который можно использовать для автоматического сохранения изменений в RoleStore. Объект RoleManager может содержать IdentityRole только объекты, так как в коде используется универсальный <IdentityRole> тип.

Вызывается метод , RoleExists чтобы определить, присутствует ли роль canEdit в базе данных членства. Если это не так, создайте роль.

UserManager Создание объекта представляется более сложным, чем RoleManager элемент управления, однако это почти то же самое. Он просто закодирован на одной строке, а не на нескольких. Здесь параметр, который вы передаете, создается как новый объект, содержащийся в скобках.

Затем создайте пользователя canEditUser, создав новый ApplicationUser объект . Затем, если вы успешно создали пользователя, добавьте его в новую роль.

Примечание

Обработка ошибок будет обновлена во время работы с руководством по обработке ошибок ASP.NET далее в этой серии руководств.

При следующем запуске приложения пользователь с именем canEditUser будет добавлен в качестве роли с именем canEdit приложения. Далее в этом руководстве вы войдете как пользователь canEditUser, чтобы отобразить дополнительные возможности, которые вы добавите в этом руководстве. Сведения об API ASP.NET Identity см. в разделе Пространство имен Microsoft.AspNet.Identity. Дополнительные сведения об инициализации системы удостоверений ASP.NET см. в разделе AspnetIdentitySample.

Ограничение доступа к странице "Администрирование"

Пример приложения Wingtip Toys позволяет анонимным и вошедым пользователям просматривать и приобретать продукты. Однако вошедший в систему пользователь с настраиваемой ролью canEdit может получить доступ к странице с ограниченным доступом для добавления и удаления продуктов.

Добавление папки и страницы администрирования

Далее вы создадите папку с именем Администратор для пользователя canEditUser, принадлежащего к пользовательской роли примера приложения Wingtip Toys.

  1. Щелкните правой кнопкой мыши имя проекта (Wingtip Toys) в Обозреватель решений и выберите Добавить ->Создать папку.
  2. Назовите новую папку Администратор.
  3. Щелкните правой кнопкой мыши папку Администратор и выберите Добавить ->Новый элемент.
    Откроется диалоговое окно Добавление нового элемента.
  4. Выберите группу шаблоны Visual C#>Web слева. В среднем списке выберите Веб-форма с главной страницей, назовите ее AdminPage.aspxи нажмите кнопку Добавить.
  5. Выберите файл Site.Master в качестве страницы master и нажмите кнопку ОК.

Добавление файла Web.config

Добавив файлWeb.config в папку Администратор, можно ограничить доступ к странице, содержащейся в папке.

  1. Щелкните правой кнопкой мыши папку Администратор и выберите Добавить ->Новый элемент.
    Откроется диалоговое окно Добавление нового элемента.

  2. В списке веб-шаблонов Visual C# выберите Файл веб-конфигурациииз среднего списка, примите имя по умолчанию Web.config, а затем нажмите кнопку Добавить.

  3. Замените существующее XML-содержимое в файле Web.config на следующее:

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

Сохраните файл Web.config. Файл Web.config указывает, что только пользователь, принадлежащий к роли "canEdit" приложения, может получить доступ к странице, содержащейся в папке Администратор.

Включение навигации по пользовательским роли

Чтобы пользователь пользовательской роли canEdit мог переходить к разделу администрирования приложения, необходимо добавить ссылку на страницу Site.Master . Только пользователи, принадлежащие роли canEdit, смогут просмотреть ссылку Администратор и получить доступ к разделу администрирования.

  1. В Обозреватель решений найдите и откройте страницу Site.Master.

  2. Чтобы создать ссылку для пользователя роли canEdit, добавьте разметку, выделенную желтым цветом, в следующий неупорядоченный элемент списка <ul> , чтобы список выглядел следующим образом:

    <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. Откройте файл Site.Master.cs . Сделайте ссылку Администратор видимой только для пользователя canEditUser, добавив в обработчик выделенный желтым цветом Page_Load код. Обработчик Page_Load будет выглядеть следующим образом:

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

При загрузке страницы код проверяет, имеет ли пользователь, выполнивший вход, роль canEdit. Если пользователь принадлежит к роли canEdit, элемент span, содержащий ссылку на страницу AdminPage.aspx (и, следовательно, ссылку внутри диапазона), становится видимым.

Включение администрирования продуктов

На данный момент вы создали роль canEdit и добавили пользователя canEditUser, папку администрирования и страницу администрирования. Вы задали права доступа для папки и страницы администрирования и добавили в приложение ссылку навигации для пользователя роли canEdit. Затем вы добавите разметку на страницу AdminPage.aspx и код в файл кода программной части AdminPage.aspx.cs , который позволит пользователю с ролью canEdit добавлять и удалять продукты.

  1. В Обозреватель решений откройте файл AdminPage.aspx из папки Администратор.

  2. Замените существующую разметку следующей:

    <%@ 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. Затем откройте файл кода программной части AdminPage.aspx.cs , щелкнув правой кнопкой мыши AdminPage.aspx и выбрав Команду Просмотреть код.

  4. Замените существующий код в файле кода программной части AdminPage.aspx.cs следующим кодом:

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

В коде, введенном для файла кода программной части AdminPage.aspx.cs , класс с именем AddProducts выполняет фактическую работу по добавлению продуктов в базу данных. Этот класс еще не существует, поэтому вы создадите его сейчас.

  1. В Обозреватель решений щелкните правой кнопкой мыши папку Логика и выберите Добавить ->Новый элемент.
    Откроется диалоговое окно Добавление нового элемента.

  2. Выберите группу шаблоныVisual C#> слева. Затем выберите Классв среднем списке и назовите его AddProducts.cs.
    Отобразится новый файл класса.

  3. Замените существующий код следующим кодом:

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

Страница AdminPage.aspx позволяет пользователю, принадлежащему к роли canEdit, добавлять и удалять продукты. При добавлении нового продукта сведения о продукте проверяются, а затем вводятся в базу данных. Новый продукт сразу же становится доступным для всех пользователей веб-приложения.

Ненавязчивая проверка

Сведения о продукте, предоставляемые пользователем на странице AdminPage.aspx , проверяются с помощью элементов управления проверки (RequiredFieldValidator и RegularExpressionValidator). Эти элементы управления автоматически используют ненавязчивую проверку. Ненавязчивая проверка позволяет элементам управления проверки использовать JavaScript для логики проверки на стороне клиента, что означает, что страница не требует обращения к серверу для проверки. По умолчанию ненавязчивая проверка включается в файл Web.config на основе следующего параметра конфигурации:

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

Регулярные выражения

Цена на продукт на странице AdminPage.aspx проверяется с помощью элемента управления RegularExpressionValidator . Этот элемент управления проверяет, соответствует ли значение связанного элемента управления ввода (TextBox AddProductPrice) шаблону, заданному регулярным выражением. Регулярное выражение — это нотация с сопоставлением шаблонов, которая позволяет быстро находить и сопоставлять определенные символьные шаблоны. Элемент управления RegularExpressionValidator содержит свойство с именем ValidationExpression , которое содержит регулярное выражение, используемое для проверки входных данных цены, как показано ниже:

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

Элемент управления FileUpload

Помимо элементов управления вводом и проверкой, вы добавили элемент управления FileUpload на страницу AdminPage.aspx . Этот элемент управления предоставляет возможность отправки файлов. В этом случае вы разрешаете отправлять только файлы изображений. В файле кода программной части (AdminPage.aspx.cs) при AddProductButton щелчке кода код проверяет HasFile свойство элемента управления FileUpload . Если элемент управления содержит файл и разрешен тип файла (на основе расширения файла), изображение сохраняется в папке Images и в папке Images/Thumbs приложения.

Привязка модели

Ранее в этом руководстве вы использовали привязку модели для заполнения элементов управления ListView , FormsView , GridView и DetailView . В этом руководстве используется привязка модели для заполнения элемента управления DropDownList списком категорий продуктов.

Разметка, добавленная в файл AdminPage.aspx , содержит элемент управления DropDownList с именем DropDownAddCategory:

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

Привязка модели используется для заполнения раскрывающегося списка путем задания атрибута ItemType и атрибута SelectMethod . Атрибут ItemType указывает, что при заполнении WingtipToys.Models.Category элемента управления используется тип . Этот тип был определен в начале этой серии руководств, создав Category класс (показано ниже). Класс Category находится в папке Models в файле 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; }
}

Атрибут SelectMethod элемента управления DropDownList указывает, что используется GetCategories метод (показан ниже), включенный в файл кода программной части (AdminPage.aspx.cs).

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

Этот метод указывает, что IQueryable интерфейс используется для вычисления запроса по типу Category . Возвращаемое значение используется для заполнения DropDownList в разметке страницы (AdminPage.aspx).

Текст, отображаемый для каждого элемента в списке, задается путем установки атрибута DataTextField . Атрибут DataTextField использует CategoryNameCategory класс класса (показан выше) для отображения каждой категории в элементе управления DropDownList . Фактическое значение, передаваемое при выборе элемента в элементе управления DropDownList , основано на атрибуте DataValueField . Атрибуту DataValueField присваивается значение , CategoryID как определено в Category классе (показано выше).

Как будет работать приложение

Когда пользователь, принадлежащий роли canEdit, впервые переходит на страницу, DropDownAddCategory элемент управления DropDownList заполняется, как описано выше. Элемент DropDownRemoveProduct управления DropDownList также заполняется продуктами, использующими тот же подход. Пользователь, принадлежащий роли canEdit, выбирает тип категории и добавляет сведения о продукте (имя, описание, цена и файл изображения). Когда пользователь, принадлежащий к роли canEdit, нажимает кнопку Добавить продукт , AddProductButton_Click запускается обработчик событий. Обработчик AddProductButton_Click событий, расположенный в файле кода программной части (AdminPage.aspx.cs), проверяет файл изображения на соответствие допустимым типам файлов (.gif, .png, .jpeg или .jpg). Затем файл изображения сохраняется в папке примера приложения Wingtip Toys. Затем новый продукт добавляется в базу данных. Чтобы добавить новый продукт, создается новый экземпляр AddProducts класса и называется products. Класс AddProducts имеет метод с именем AddProduct, а объект products вызывает этот метод для добавления продуктов в базу данных.

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

Если код успешно добавляет новый продукт в базу данных, страница перезагружается со значением ProductAction=addстроки запроса .

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

При перезагрузке страницы строка запроса включается в URL-адрес. Перезагрузив страницу, пользователь, принадлежащий роли canEdit, может сразу же увидеть обновления в элементах управления DropDownList на странице AdminPage.aspx . Кроме того, если включить строку запроса с URL-адресом, страница может отобразить сообщение об успешном выполнении для пользователя, принадлежащего к роли canEdit.

При перезагрузке страницы Page_LoadAdminPage.aspx вызывается событие .

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

Обработчик Page_Load событий проверяет значение строки запроса и определяет, следует ли отображать сообщение об успешном выполнении.

Запуск приложения

Теперь вы можете запустить приложение, чтобы узнать, как добавлять, удалять и обновлять элементы в корзине. Итог корзины будет отражать общую стоимость всех товаров в корзине.

  1. В Обозреватель решений нажмите клавишу F5, чтобы запустить пример приложения Wingtip Toys.
    Откроется браузер, где отображается страница Default.aspx .

  2. Щелкните ссылку Вход в верхней части страницы.

    Членство и администрирование — ссылка для входа

    Отобразится страница Login.aspx .

  3. Введите имя пользователя и пароль.

    Членство и администрирование — страница входа

  4. Нажмите кнопку Вход в нижней части страницы.

  5. В верхней части следующей страницы щелкните ссылку Администратор, чтобы перейти на страницу AdminPage.aspx.

    Членство и администрирование — ссылка Администратор

  6. Чтобы протестировать входную проверку, нажмите кнопку Добавить продукт без добавления сведений о продукте.

    Членство и администрирование — страница Администратор

    Обратите внимание, что отображаются обязательные сообщения полей.

  7. Добавьте сведения о новом продукте и нажмите кнопку Добавить продукт .

    Членство и администрирование — добавление продукта

  8. Выберите Продукты в верхнем меню навигации, чтобы просмотреть добавленный продукт.

    Членство и администрирование — показать новый продукт

  9. Щелкните ссылку Администратор, чтобы вернуться на страницу администрирования.

  10. В разделе Удалить продукт на странице выберите новый продукт, добавленный в DropDownListBox.

  11. Нажмите кнопку Удалить продукт , чтобы удалить новый продукт из приложения.

    Членство и администрирование — удаление продукта

  12. Выберите Продукты в верхнем меню навигации, чтобы убедиться, что продукт удален.

  13. Щелкните Выйти, чтобы существовать в режиме администрирования.
    Обратите внимание, что в верхней области навигации больше не отображается пункт меню Администратор.

Итоги

В этом руководстве вы добавили пользовательскую роль и пользователя, принадлежащего к этой роли, ограничили доступ к папке и странице администрирования, а также предоставили навигацию для пользователя, принадлежащего к этой роли. Вы использовали привязку модели для заполнения элемента управления DropDownList данными. Реализованы элементы управления FileUpload и элементы управления проверки. Кроме того, вы узнали, как добавлять и удалять продукты из базы данных. В следующем руководстве вы узнаете, как реализовать маршрутизацию ASP.NET.

Дополнительные ресурсы

Web.config — элемент authorization
ASP.NET Identity
Развертывание безопасного приложения ASP.NET Web Forms с членством, OAuth и База данных SQL на веб-сайте Azure
Microsoft Azure — бесплатная пробная версия