В первой части учебного пособия «ASP.NET для разработчиков PHP» мы изучили основы ASP.NET и языка C #. Вторая часть основана на этом фундаменте и знакомит с некоторыми более продвинутыми функциями и методами, позволяющими вывести страницы ASP.NET на новый уровень.
Прежде чем ты начнешь…
Убедитесь, что вы прочитали и завершили примеры в первой части руководства . Мы будем использовать это приложение здесь. Стоит также подчеркнуть, что для продолжения вам необходимо хорошее понимание объектно-ориентированного программирования (ООП).
И прежде чем я начну …
В первой части учебного пособия я упомянул, что существует два варианта ASP.NET:
- ASP.NET WebForms : оригинальная платформа, позволяющая разработчикам создавать веб-приложения, используя многие из тех же методов, которые используются в настольных приложениях .NET Windows.
- ASP.NET MVC : новая платформа, предлагающая архитектуру Model-View-Controller и больший контроль над кодом на стороне клиента
Однако я не использую ни один из них, а скорее третий подход, разработанный мной. Это по нескольким причинам:
- Когда я начал писать серьезные приложения ASP.NET, я сохранил свои высокие стандарты вывода HTML, усвоенные при написании PHP. Если страница не прошла проверку, я чувствовал себя грязным. Есть много разработчиков, которые чувствуют то же самое . В то время ASP.NET WebForms давали ужасную разметку для многих стандартных элементов управления, поэтому мне пришлось придумать другое решение. Добавление
runat="server"
к элементам HTML давало много преимуществ истинных элементов управления ASP.NET, но давало мне полный контроль надrunat="server"
HTML. Вещи улучшились и выглядят еще лучше для ASP.NET 4.0 . - Я видел множество примеров кода ASP.NET, где было очевидно, что разработчик не заботился о конечном HTML. Возможно, они были разработчиками настольных приложений для Windows, делающими прыжок в Интернет, возможно, они никогда не кодировали HTML вручную. Какой бы ни была причина, я решил, что не буду одним из них.
- Многие стандартные элементы управления ASP.NET полностью полагались на JavaScript, который, честно говоря, непростителен для общедоступных веб-сайтов (в Великобритании доступность веб-сайтов является юридическим требованием ). Например, злая функция
javascript:__doPostBack
— это идеальный способ сделать ваш веб-сайт невозможным для использования значительной частью веб-аудитории — а также поисковыми системами. - Я хотел использовать свой собственный выбор библиотеки JavaScript (первоначально Prototype , но затем jQuery , теперь официально поддерживаемый ASP.NET). Если бы мне пришлось использовать библиотеку JavaScript ASP.NET Framework, это усложнило бы это.
- Так почему бы не ASP.NET MVC? Ну, этого не было, когда я начал писать приложения ASP.NET, и даже если бы это было так, это было бы еще одним препятствием, чтобы заставить что-то работать. Изучение платформы .Net и языка C # было достаточно сложной задачей!
Таким образом, вы можете понять, почему я выбрал такой подход. Когда ASP.NET повзрослел, и я обнаружил новые функции, я начал интегрировать их в свои приложения, и я полностью ожидаю, что со временем я буду делать больше этого.
Итак, давайте перенесем наше приложение ASP.NET на новый уровень.
Мастер Страницы
Моя вторая любимая особенность ASP.NET (после превращения элементов управления HTML в элементы управления сервером ) — это главные страницы. Главная страница — это файл шаблона, который вы можете использовать для инкапсуляции HTML, который вы используете на нескольких страницах. Например, ваша главная страница может содержать заголовок, меню и нижний колонтитул ваших страниц, в то время как ваши обычные страницы .aspx содержат фактический контент на этой странице. давайте посмотрим на пример веб-страницы:
Вы можете увидеть детали, которые используются на нескольких страницах, выделенных зеленым цветом. Содержимое, которое изменяется для каждой страницы сайта, выделяется красным. Главные страницы позволяют нам разделить код для этих двух разделов на несколько файлов. Если вы использовали шаблоны в своих приложениях PHP (например, в WordPress есть header.php
, footer.php
и sidebar.php
), вы увидите, насколько sidebar.php
мастер-страницы.
Создание главной страницы
Итак, давайте создадим главную страницу. В представлении «Решение» создайте новый каталог в приложении ASP.NET с именем «Master_Pages». В этом каталоге создайте новую главную страницу, щелкнув правой кнопкой мыши на папке Master_Pages, выбрав «Добавить> Новый файл», затем выберите «Главная страница с кодом позади» и назовите ее «DefaultMaster». Ваша новая главная страница будет создана, и вы увидите файлы «DefaultMaster.master», «DefaultMaster.master.cs» и «DefaultMaster.master.designer.cs» в папке Master_Pages.
Откройте файлы «DefaultMaster.master» и «DefaultMaster.master.cs». Файл с выделенным кодом (.cs) для главной страницы (.master) работает точно так же, как файл с выделенным кодом для страницы .aspx. Первое, на что нужно обратить внимание, это то, что главные страницы не наследуются от System.Web.UI.Page, как страницы ASPX. Вместо этого они наследуются от System.Web.UI.MasterPage. Вот код по умолчанию для кода.
1
2
3
4
5
6
7
8
9
|
using System;
using System.Web;
using System.Web.UI;
namespace WebApplication1
{
public partial class DefaultMaster : System.Web.UI.MasterPage
{
}
}
|
И для самого файла .master:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
<%@ Master Language=»C#» Inherits=»WebApplication1.DefaultMaster» %>
<!DOCTYPE html PUBLIC «-//W3C//DTD XHTML 1.0 Strict//EN» «http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd»>
<html>
<head>
<title>DefaultMaster</title>
</head>
<body>
<div id=»container»>
<form runat=»server»>
<asp:contentplaceholder id=»contentPlaceHolder» runat=»server» />
</form>
</div>
</body>
</html>
|
Поскольку мы не используем модель WebForms, давайте быстро удалим теги для элемента <form runat="server">
.
Вы должны привыкнуть к объявлениям страниц (бит <%@ Page ... %>
на страницах .aspx), поэтому объявление <%@ Master ... %>
будет сюрпризом. В этом коде отличается новый элемент управления: <asp:contentplaceholder>
.
1
|
<asp:contentplaceholder id=»contentPlaceHolder» runat=»server» />
|
Этот местозаполнитель содержимого — это место, где будет вставляться содержимое ваших страниц .aspx. Вы можете иметь столько их на странице .master, сколько захотите.
Ссылка на вашу главную страницу
Давайте вернемся к нашей обычной странице .aspx и внесем некоторые изменения. Первое, что нужно сделать, это удалить теги <html>
, <head>
и <body>
, так как они теперь будут на главной странице. Это оставляет:
1
2
3
|
<%@ Page Language=»C#» Inherits=»WebApplication1.Default» %>
<h1 id=»headertext» runat=»server»>This is the text</h1>
|
Теперь нам нужно указать, какой контент поместить в заполнитель контента. Мы делаем это, определяя, где находится главная страница, и помещая наш контент в элемент управления asp:Content
, например так:
1
2
3
4
|
<%@ Page Language=»C#» MasterPageFile=»~/Master_Pages/DefaultMaster.master» Inherits=»WebApplication1.Default» %>
<asp:Content id=»Content1″ ContentPlaceHolderID=»contentPlaceHolder» runat=»server»>
<h1 id=»headertext» runat=»server»>This is the text</h1>
</asp:Content>
|
Здесь есть пара вещей, на которые стоит обратить внимание. Во-первых, объявление страницы имеет дополнительный атрибут «MasterPageFile» со значением «~ / Master_Pages / DefaultMaster.master». В ASP.NET «~» означает корень приложения, остальная часть этого пути просто указывает на нашу главную страницу.
Во-вторых, вы видите, что новый элемент управления asp:Content
имеет атрибут «ContentPlaceHolderID» со значением «contentPlaceHolder», который является атрибутом «id» нашего <asp:contentplaceholder>
. Запуск приложения даст вам:
Проверка исходного кода страницы подтверждает, что главная страница (.master) и страница содержимого (.aspx) были бесшовно объединены. Теперь вы понимаете, почему я так люблю мастер-страницы.
Более сложная главная страница
Мы можем продвинуть мастер-страницы намного дальше, чем этот простой пример. Давайте попробуем создать нечто, похожее на настоящее веб-приложение, начиная с главной страницы. Во-первых, мы добавим еще несколько заполнителей контента и несколько серверных элементов управления:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
<%@ Master Language=»C#» Inherits=»WebApplication1.DefaultMaster» %>
<!DOCTYPE html PUBLIC «-//W3C//DTD XHTML 1.0 Strict//EN» «http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd»>
<html>
<head>
<title><asp:contentplaceholder id=»PageTitle» runat=»server» /></title>
<script src=»scripts/jquery.min.js»></script>
<asp:contentplaceholder id=»PageJS» runat=»server» />
<link rel=»stylesheet» href=»styles/default.css»></link>
<asp:contentplaceholder id=»PageCSS» runat=»server» />
</head>
<body>
<div id=»container»>
<h1 id=»sitename» runat=»server»></h1>
<ul id=»menu»>
<li><a href=»about.aspx»>About me</a></li>
<li><a href=»services.aspx»>My services</a></li>
<li><a href=»contact.aspx»>Contact me</a></li>
</ul>
<div id=»content»>
<asp:contentplaceholder id=»PageContent» runat=»server» />
</div>
<div id=»footer»>
<p id=»copyright» runat=»server»></p>
</div>
</div>
</body>
</html>
|
И в файле кода для нашей главной страницы мы поместим:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
using System;
using System.Web;
using System.Web.UI;
using System.Configuration;
namespace WebApplication1
{
public partial class DefaultMaster : System.Web.UI.MasterPage
{
protected void Page_Load(object sender, EventArgs e)
{
sitename.InnerHtml = ConfigurationSettings.AppSettings[«SiteName»];
copyright.InnerHtml = ConfigurationSettings.AppSettings[«CopyrightNotice»] + DateTime.Now.Year.ToString();
}
}
}
|
(Я оставлю это в качестве упражнения для вас, чтобы добавить настройки приложений SiteName и CopyrightNotice в web.config.)
Теперь для нашей страницы контента. У нас есть четыре заполнителя содержимого, которые мы можем использовать: PageTitle, PageJS, PageCSS и PageContent. Вот код для страницы содержимого .aspx:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
<%@ Page Language=»C#» MasterPageFile=»~/Master_Pages/DefaultMaster.master» Inherits=»WebApplication1.Default» %>
<asp:Content id=»PageTitle» ContentPlaceHolderID=»PageTitle» runat=»server»>
<asp:Literal id=»Title» runat=»server»></asp:Literal>
</asp:Content>
<asp:Content id=»PageCSS» ContentPlaceHolderID=»PageCSS» runat=»server»>
<style type=»text/css»>
h1 {
font-family: sans-serif;
color: #090;
}
</style>
</asp:Content>
<asp:Content id=»PageContent» ContentPlaceHolderID=»PageContent» runat=»server»>
<h2>Welcome, one and all</h2>
<p>This is my very first ASP.NET website, working with a master page!</p>
</asp:Content>
|
И код для нашей страницы контента .aspx:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
using System;
using System.Web;
using System.Web.UI;
using System.Configuration;
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Title.Text = «Welcome to my first ASP.NET Website»;
}
}
}
|
Пару новых вещей, чтобы заметить здесь. Во-первых, я вообще не использовал заполнитель содержимого PageJS — вполне нормально оставить его полностью (конечно, на этой области ничего не будет отображаться). Во-вторых, я представил еще один элемент управления ASP.NET, а именно <asp:Literal>
, который мы сейчас кратко рассмотрим.
Буквальный контроль
Элемент управления Literal очень полезен, когда вы хотите визуализировать что-либо на странице без какой-либо дополнительной разметки. Например, большую часть времени можно использовать:
1
2
3
|
<span id=»message» runat=»server»>
message.InnerHtml = «This is the message»
|
дает:
1
|
<span id=»message»>This is the message
|
Но если вам совсем не нужны теги span, например, для страницы <title>
, вам нужен элемент управления Literal. Установка свойства «Text» элемента управления Literal отображает на странице только этот текст:
1
2
3
|
<asp:Literal id=»message» runat=»server»></asp:Literal>
message.Text = «This is the message»;
|
дает:
1
|
This is the message
|
Готовая главная страница и страница контента
Итак, запуск нашего приложения должен дать нам это:
Это на самом деле просто царапает поверхность, так как возможно иметь несколько главных страниц (даже вложенных главных страниц!). Вы также можете установить главную страницу программно (но это необходимо сделать в событии Page_Init, так как Page_Load слишком поздно в жизненном цикле страницы). На сайте MSDN есть много более подробной информации о MasterPages.
Пользовательские классы
В вашем приложении можно создавать собственные классы, как в PHP. Давайте создадим класс безопасности, щелкнув правой кнопкой мыши корневой каталог приложения и выбрав «Добавить> Новый файл», затем выбрав «Пустой класс» в разделе «Общие» и назовем его «Безопасность».
Код для вашего нового класса выглядит следующим образом:
01
02
03
04
05
06
07
08
09
10
|
using System;
namespace WebApplication1
{
public class Security
{
public Security()
{
}
}
}
|
Я добавлю немного больше кода в этот файл:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
using System;
using System.Web;
namespace WebApplication1
{
public class Security
{
public bool IsLoggedIn;
public Security()
{
CheckSession();
}
private void CheckSession()
{
if (HttpContext.Current.Session[«loggedin»] != null && HttpContext.Current.Session[«loggedin»] == «true»)
{
IsLoggedIn = true;
}
else
{
IsLoggedIn = false;
}
}
}
}
|
Довольно просто пока. Единственным нововведением является использование HttpContext.Current.Session
а не просто Session
, потому что HttpContext.Current
неявно присутствует на веб-странице .aspx, но не в отдельном классе.
В нашем файле с выделенным кодом Default.aspx.cs мы пишем:
01
02
03
04
05
06
07
08
09
10
11
12
|
protected void Page_Load(object sender, EventArgs e)
{
Security security = new Security();
if (security.IsLoggedIn)
{
Title.Text = «Welcome back, you are logged in»;
}
else
{
Title.Text = «You are not logged in»;
}
}
|
Который создает новый экземпляр класса безопасности с именами «безопасность». Запуск приложения показывает это:
Как вы знакомы с ООП, вы можете увидеть, как это можно использовать для создания крупномасштабных веб-приложений. Единственное, что можно сказать о пользовательских классах, это как сделать их статичными. Вот код для статического класса:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
using System;
using System.Web;
namespace WebApplication1
{
public static class Security
{
public static bool IsLoggedIn;
public static void CheckSession()
{
if (HttpContext.Current.Session[«loggedin»] != null && HttpContext.Current.Session[«loggedin»] == «true»)
{
IsLoggedIn = true;
}
else
{
IsLoggedIn = false;
}
}
}
}
|
Вы можете видеть, что нет метода по умолчанию, так как этот класс никогда не создается. Я также добавил ключевое слово «static» в свойство и метод и сделал метод CheckSession()
общедоступным. Чтобы использовать этот статический класс, мы написали бы:
01
02
03
04
05
06
07
08
09
10
11
12
|
protected void Page_Load(object sender, EventArgs e)
{
Security.CheckSession();
if (Security.IsLoggedIn)
{
Title.Text = «Welcome back, you are logged in»;
}
else
{
Title.Text = «You are not logged in»;
}
}
|
Довольно просто, правда. Поскольку вы полностью осознаете преимущества, которые ООП может дать вам для абстракции, инкапсуляции и наследования, вы увидите, насколько это мощно. Но если мы собираемся использовать объекты, нам действительно нужны серьезные данные для моделирования в наших объектах. Нам нужна база данных.
Базы данных, источники данных и привязка данных
ASP.NET действительно хорошо работает с базами данных, но лучше всего работает с Microsoft SQL Server (что неудивительно). Даже если ваше приложение ASP.NET работает на компьютере с Linux, вы все равно можете подключиться к SQL Server на сервере Windows для использования в качестве хранилища данных. Я продемонстрирую это ниже, но пока я пишу это руководство по Linux, я также продемонстрирую использование MySQL в качестве базы данных ASP.NET . Чтобы использовать MySQL, вам понадобится драйвер ADO.NET для MySQL — эта отличная статья мне очень помогла.
Конфигурация базы данных
Первое, что нужно сделать, это настроить способ подключения к нашему серверу базы данных. Вы можете сделать это в файле web.config, добавив этот код в раздел «конфигурация» (код MySQL и SQL Server должен быть довольно очевидным). Обратите внимание, что это стандартные строки подключения .
1
2
3
4
|
<connectionStrings>
<add name=»MySQL» connectionString=»Server=mysqlserver;Database=aspnetdb1;User ID=root;Password=mypassword;Pooling=false»/>
<add name=»SQLServer» connectionString=»Server=sqlserver;Database=aspnetdb1;User ID=sa;Password=myPassword;»/>
</connectionStrings>
|
Я также создал таблицу под названием «пользователи» с этим кодом (это для MySQL, незначительные изменения заставят его работать в большинстве других систем баз данных):
1
2
3
4
5
6
7
|
CREATE TABLE users (
id int NOT NULL AUTO_INCREMENT,
username varchar(50) NOT NULL,
password varchar(32) NOT NULL,
email varchar(255) NOT NULL,
PRIMARY KEY (id)
);
|
Для доступа к строке подключения вы можете использовать класс ConfigurationManager, который мы использовали в части 1 руководства, для доступа к глобальным настройкам конфигурации. Вот код:
1
|
string conn = ConfigurationManager.ConnectionStrings[«MySQL»].ConnectionString;
|
Подключение и запуск простого запроса
Итак, теперь мы готовы подключиться к нашей базе данных и выполнить запрос. Сначала вставьте пару строк в таблицу «users», чтобы у нас было что запросить:
1
2
3
4
|
insert into users
(username, password, email)
values
(‘User 1’, ‘user1password’, ‘[email protected]’)
|
Затем нам нужно убедиться, что мы ссылаемся на правильные сборки. Для MySQL убедитесь, что у вас есть это в верхней части файла с выделенным кодом:
1
2
|
using System.Data;
using MySql.Data.MySqlClient;
|
Amd для SQL Server используйте это:
1
2
|
using System.Data;
using System.Data.SqlClient;
|
Краткое примечание о подключении к MySQL в Linux. У меня были небольшие проблемы с компиляцией моего приложения, когда я впервые попробовал это. Я сделал различные поиски, но не нашел ответа, который работал для меня. Я получил сообщение об ошибке «Не удалось найти тип или имя пространства имен` MySqlConnection ‘». который выглядел так, как будто MySQL Connector не был установлен должным образом. Исправление (для меня) заключалось в том, чтобы вручную добавить ссылку, щелкнув правой кнопкой мыши папку «Ссылки» в моем приложении и выбрав «Изменить ссылки». Затем я нашел файл MySQL.Data.dll на вкладке .Net Assembly и сослался на него. Мне также пришлось вручную ссылаться на сборки System.Data и System.Configuration на вкладке Пакеты.
Надеюсь, вам не нужно будет прыгать через эти обручи.
Теперь мы открываем соединение с нашей базой данных, как это для MySQL:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
protected void Page_Load(object sender, EventArgs e)
{
// get the connection string
string conn = ConfigurationManager.ConnectionStrings[«MySQL»].ConnectionString;
// create a new MySQL connection
MySqlConnection dbcon;
using (dbcon = new MySqlConnection(conn))
{
// open the connection
dbcon.Open();
// create the query
string query = «SELECT username, email FROM users»;
// create a new adapter between the connection and query
MySqlDataAdapter adapter = new MySqlDataAdapter(query, dbcon);
// create a new dataset to store the query results
DataSet ds = new DataSet();
// fill the dataset with the results from the adapter,
// the name of the dataset is «result»
adapter.Fill(ds, «result»);
}
}
|
И это для SQL Server:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
protected void Page_Load(object sender, EventArgs e)
{
// get the connection string
string conn = ConfigurationManager.ConnectionStrings[«SQLServer»].ConnectionString;
// create a new SQL Server connection
SqlConnection dbcon;
using (dbcon = new SqlConnection(conn))
{
// open the connection
dbcon.Open();
// create the query
string query = «SELECT username, email FROM users»;
// create a new adapter between the connection and query
SqlDataAdapter adapter = new SqlDataAdapter(query, dbcon);
// create a new dataset to store the query results
DataSet ds = new DataSet();
// fill the dataset with the results from the adapter,
// the name of the dataset is «result»
adapter.Fill(ds, «result»);
}
}
|
Видите, довольно легко, и не за миллион миль от эквивалентного кода PHP. Здесь есть пара моментов, которые я объясню более подробно. Во-первых, оператор using
:
1
|
using (something here) { … }
|
Объект, который вы установили в скобках, автоматически уничтожается, когда ваш код выходит из фигурной скобки «}». Это действительно полезная структура, чтобы узнать о ней, поэтому прочитайте все об этом здесь .
Во-вторых, DataSet
. В приведенном выше коде результаты запроса к базе данных передаются в DataSet, который представляет собой объект, содержащий одну или несколько таблиц, каждая таблица содержит строки и столбцы. Это означает, что вы можете делать полезные вещи, такие как:
1
2
3
4
5
6
7
8
|
DataSet ds = new DataSet();
// we put some data from the database in the DataSet here…
// get the number of tables
int tables = ds.Tables.Count;
// get the first table
DataTable dt = ds.Tables[0];
// get the number of rows in the first table
int rows = ds.Tables[0].Rows.Count;
|
И есть много других вкусностей в классе DataSet . Вы также можете зацикливать строки, как в PHP, например:
1
2
3
4
|
for (int x = 0; x < ds.Tables[0].Rows.Count; x++)
{
Response.Write(ds.Tables[0].Rows[x][«fieldname»].ToString() + <br />);
}
|
Но есть гораздо лучший способ отображения простых петель, использующий элемент управления Repeater.
Использование повторителей и привязки данных
Сначала признание. Я написал большое приложение ASP.NET, в котором не используются элементы управления ASP.NET, кроме Literal (который мы рассмотрели выше) и Repeater. Элемент управления Repeater позволяет вам «привязывать» данные, например, из DataSet, и отображать их циклически. Во-первых, нам нужно добавить что-то в код нашей базы данных выше:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
protected void Page_Load(object sender, EventArgs e)
{
// get the connection string
string conn = ConfigurationManager.ConnectionStrings[«MySQL»].ConnectionString;
// create a new MySQL connection
MySqlConnection dbcon;
using (dbcon = new MySqlConnection(conn))
{
// open the connection
dbcon.Open();
// create the query
string query = «SELECT username, email FROM users»;
// create a new adapter between the connection and query
MySqlDataAdapter adapter = new MySqlDataAdapter(query, dbcon);
// create a new dataset to store the query results
DataSet ds = new DataSet();
// fill the dataset with the results from the adapter,
// the name of the dataset is «result»
adapter.Fill(ds, «result»);
// below is the new code…
// set the DataSource of the repeater
myRepeater.DataSource = ds;
// bind the data
myRepeater.DataBind();
}
}
|
И на странице .aspx мы помещаем:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<asp:Repeater id=»myRepeater» runat=»server»>
<HeaderTemplate>
<table>
<tr>
<th>Username</th>
<th>Email</th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%# Eval(«username») %></td>
<td><%# Eval(«email») %></td>
</tr>
</ItemTemplate>
<AlternatingItemTemplate>
<tr class=»alt»>
<td><%# Eval(«username») %></td>
<td><%# Eval(«email») %></td>
</tr>
</AlternatingItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
|
Вы можете увидеть, что здесь происходит. Когда данные привязаны к элементу управления Repeater, отображается раздел HeaderTemplate. Затем каждая строка отображается в разделах ItemTemplate и AlternatingItemTemplate (имена должны дать вам представление о том, как они отображаются). Затем, наконец, отображается раздел FooterTemplate. Использование этого простого элемента управления дает вам простой способ отображать повторяющиеся данные с полным контролем над получающимся HTML-кодом, как в PHP. Вот результаты (с некоторыми стилями CSS):
Поскольку Repeater генерирует исключение, если к нему привязан пустой DataSet, вам необходимо проверить, есть ли данные, которые должны быть связаны в первую очередь. Простой оператор if
будет работать, проверяя, есть ли таблицы в DataSet и есть ли в первой таблице строки:
1
2
3
4
5
|
if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
myRepeater.DataSource = ds;
myRepeater.DataBind();
}
|
Я думаю, вы согласитесь, что наличие элемента управления, который устанавливает шаблоны для повторения данных так же легко, как огромная помощь для разработчика. Одна вещь, которую следует отметить с элементом управления Repeater — если вы связываете DataSet с ним по умолчанию, используется первая таблица. Если вы используете хранимые процедуры вместо встроенного SQL для выполнения команд для своей базы данных, вы можете вернуть несколько таблиц, то есть вы можете загрузить несколько наборов данных для использования на странице одновременно. В этом случае вы будете использовать такой код (чтобы связать вторую таблицу в наборе данных с повторителем):
1
2
|
myRepeater.DataSource = ds.Tables[1];
myRepeater.DataBind();
|
Создание класса доступа к данным
Давайте свяжем последние пару разделов и создадим класс доступа к данным, который упростит подключение и запуск команд в вашей базе данных. Этот код для MySQL, но, как вы видели, код для SQL Server очень похож. Создайте новый пустой класс с именем «DB» и вставьте его в новый файл:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
using System;
using System.Configuration;
using System.Data;
using MySql.Data.MySqlClient;
namespace WebApplication1
{
public class DB
{
private string ConnectionString;
public DB()
{
// get the connection string
this.ConnectionString = ConfigurationManager.ConnectionStrings[«MySQL»].ConnectionString;
}
public DataSet Select(string query)
{
MySqlConnection dbcon;
using (dbcon = new MySqlConnection(this.ConnectionString))
{
// open the connection
dbcon.Open();
// create a new adapter between the connection and query
MySqlDataAdapter adapter = new MySqlDataAdapter(query, dbcon);
// create a new dataset to store the query results
DataSet ds = new DataSet();
// fill the dataset with the results from the adapter,
adapter.Fill(ds, «result»);
// return the dataset
return ds;
}
}
public bool Execute(string query)
{
MySqlConnection dbcon;
using (dbcon = new MySqlConnection(this.ConnectionString))
{
// create a new SQL command on thie connection
MySqlCommand command = new MySqlCommand(query, dbcon);
// open the connection
dbcon.Open();
// execute the query and return the number of affected rows
int affectedrows = command.ExecuteNonQuery();
// there were no rows affected — the command failed
if (affectedrows == 0)
{
return false;
// the command affected at least one row
} else {
return true;
}
}
}
}
}
|
Чтобы использовать это в своем файле с выделенным кодом, вы должны добавить:
1
2
3
4
5
6
7
|
DB db = new DB();
DataSet ds = db.Select(«SELECT username, email FROM users»);
if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
myRepeater.DataSource = ds;
myRepeater.DataBind();
}
|
Этот класс доступа к данным знакомит вас с новым стилем синтаксиса подключения к базе данных, используя класс MySqlCommand (SqlCommand для SQL Server) и метод ExecuteNonQuery. Как говорится в коде, метод ExecuteNonQuery выполняет запрос и возвращает количество затронутых строк. Очень полезно для команд INSERT
, UPDATE
и DELETE
.
Те из вас, кто хорошо знает WordPress , увидят, как этот класс похож на глобальный класс $wpdb
в WP, который предлагает такие методы, как $wpdb->get_results("select * from table");
и $wpdb->query("delete * from table");
, Вам будет легко расширить этот класс доступа к данным, чтобы иметь более полезные свойства и методы для ваших приложений.
Элементы управления пользователя
До сих пор мы использовали только два элемента управления ASP.NET — Literal и Repeater — в честь нашей цели сохранить полный контроль над выходным HTML. Но иногда полезно инкапсулировать функциональность для ваших собственных элементов управления. ASP.NET позволяет создавать пользовательские элементы управления со своими свойствами и методами. Эти пользовательские элементы управления можно рассматривать как отдельные блоки HTML, которые можно использовать внутри страницы .aspx, точно так же, как если бы вы включали отдельный файл в файл .php.
Мы собираемся создать очень простой элемент управления, который отображает усеченную ссылку. Сначала добавьте новый файл типа «Элемент управления с файлом с выделенным кодом» и назовите его «ShortLink».
Вы можете заметить, что новый файл имеет расширение .ascx, это расширение для пользовательских элементов управления. Откройте файл .ascx, и вы увидите это:
1
|
<%@ Control Language=»C#» Inherits=»WebApplication1.ShortLink» %>
|
Откройте файл с выделенным кодом (MyControl.ascx.cs), и вы увидите это:
01
02
03
04
05
06
07
08
09
10
|
using System;
using System.Web;
using System.Web.UI;
namespace WebApplication1
{
public partial class MyControl : System.Web.UI.UserControl
{
}
}
|
Теперь мы готовы создать наш пользовательский элемент управления. Вставьте этот код в файл .ascx.cs (code-behind) (я не буду объяснять этот код, он достаточно прост):
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
using System;
using System.Web;
using System.Web.UI;
namespace WebApplication1
{
public partial class ShortLink : System.Web.UI.UserControl
{
public string Link;
protected void Page_Load(object sender, EventArgs e)
{
// set the href attribute
theLink.Attributes[«href»] = Link;
// declare the short link, replacing protocols
string shortlink = Link.Replace(«http://», «»).Replace(«https://», «»);
// if the link is longer than 15 characters
if (shortlink.Length > 15)
{
// show the first 6 and last 6 characters
theLink.InnerHtml = shortlink.Substring(0, 6) + «…» + shortlink.Substring(shortlink.Length-6);
}
else
{
// show the full link
theLink.InnerHtml = shortlink;
}
}
}
}
|
Да, пользовательские элементы управления используют тот же обработчик событий Page_Load, что и обычные страницы ASPX. Теперь откройте файл .ascx и вставьте его в него:
1
2
|
<%@ Control Language=»C#» Inherits=»WebApplication1.ShortLink» %>
<a href=»» id=»theLink» runat=»server»></a>
|
Здесь вы можете увидеть вместо объявления страницы у нас есть объявление Control, но то же свойство Inherits, чтобы связать его с файлом code-behind. У нас также есть стандартный элемент <a>
со runat="server"
чтобы сделать его серверным элементом управления.
Чтобы использовать этот элемент управления на своей странице, просто зарегистрируйте префикс тега (это может быть что угодно) в верхней части страницы следующим образом:
1
2
|
<%@ Page Language=»C#» MasterPageFile=»~/Master_Pages/DefaultMaster.master» Inherits=»WebApplication1.Default» %>
<%@ Register TagPrefix=»My» TagName=»ShortLink» Src=»ShortLink.ascx» %>
|
Затем используйте элемент управления, где вы хотите. Чтобы продемонстрировать этот элемент управления, я использую два его экземпляра:
1
2
|
<p><My:ShortLink id=»Link1″ Link=»http://www.google.com» Runat=»server»></My:ShortLink></p>
<p><My:ShortLink id=»Link2″ Link=»http://www.google.com/search?q=asp.net+for+php+developers» Runat=»server»></My:ShortLink></p>
|
Свойство TagPrefix является первой частью тега элемента управления, а TagName — второй частью, разделенной знаком «:» — My: ShortLink. И вот результат:
Здесь вы можете видеть, что свойство public string, которое я объявил в своем классе пользовательских элементов управления ShortCode ( public string Link;
), может быть установлено в свойстве Link
элемента управления. Вы можете иметь любое количество свойств, и они могут быть любого типа. Вы можете устанавливать только строковые типы в самом теге Link1.DatasetProperty = new DataSet();
(т. Link1.DatasetProperty = new DataSet();
Link="http://www.google.com"
), так как вы можете устанавливать свойства программно из файла с Link1.DatasetProperty = new DataSet();
кодом (например, Link1.DatasetProperty = new DataSet();
).
Здесь есть один кусочек кода, который требует немного большего объяснения.
Использование собственного префикса тега
Ваши пользовательские элементы управления должны иметь свой собственный префикс тега. В нашем примере выше это «My», но, конечно, это может быть любая простая строка. В приведенном выше примере префикс тега был зарегистрирован, поэтому ASP.NET знал, что делать, когда столкнулся с ним, используя объявление в верхней части страницы:
1
|
<%@ Register TagPrefix=»My» TagName=»ShortLink» Src=»ShortLink.ascx» %>
|
Однако можно зарегистрировать префиксы тегов в файле web.config, так что вам не нужно делать это на каждой странице (как объяснил Скотт Гатри — это один блог, за которым вы хотите следить). Вот как, но прежде чем вы броситесь в погоню за ошибкой, которую я получил:
1
|
Parser Error Message: The page ‘/Default.aspx’ cannot use the user control ‘/ShortLink.ascx’, because it is registered in web.config and lives in the same directory as the page.
|
Поэтому поместите ваши пользовательские элементы управления в подпапку, например «Элементы управления».
01
02
03
04
05
06
07
08
09
10
|
<?xml version=»1.0″?>
<configuration>
<system.web>
<pages>
<controls>
<add tagPrefix=»My» src=»~/Controls/ShortLink.ascx» tagName=»ShortLink»/>
</controls>
</pages>
</system.web>
</configuration>
|
Теперь вы захотите разместить пользовательские элементы управления везде. И самое лучшее, что есть в пользовательских элементах управления, это то, что они похожи на страницы (без тегов <html>, <head> и <body>), в них можно помещать все, что угодно. Фактически было бы возможно написать целое приложение в пользовательских элементах управления, включая соответствующие элементы управления на вашей странице в зависимости от некоторых параметров, переданных ему. Удивительный.
Компиляция и развертывание
Как уже упоминалось в первой части учебника , C # — это скомпилированный язык. Вместо PHP, который компилируется в язык, понятный компьютеру во время выполнения, C # предварительно компилируется (или иногда компилируется при первом запуске) и сохраняется в сборках для обработки компьютером.
Это означает, что C # работает быстрее (да, это правда, извините ), и что вы можете поймать много ошибок в своем коде * перед * попыткой его запуска. Вы уже видели это, когда мы обсуждали ошибки выше. Однако это означает, что вы не можете просто удалить приложение ASP.NET на сервере и ожидать его запуска. Это также означает, что вы не можете выполнять живой взлом ваших файлов с выделенным кодом в работающем приложении. К развертыванию нужно подходить немного более методично, чем в PHP.
Есть несколько других статей, которые объясняют это гораздо лучше, чем я, поэтому я просто сошлюсь на них .
Следующие шаги
Надеюсь, что между первой частью и этим учебным пособием у вас теперь есть намного лучшее представление о том, что такое ASP.NET и какие преимущества он может предоставить разработчикам. Для дальнейшего чтения, вы можете проверить некоторые из моих любимых мест:
- Официальный сайт Microsoft ASP.NET
- Блог Скотта Гатри
- Блог Криса Лава
- ASPAlliance.com
- 15seconds.com
- Твиттер Ильи Мэнор
Наконец, удачи! Много лет мне, как парню из PHP, было нелегко разобраться с ASP.NET. Тем не менее, я нашел много хороших вещей во фреймворке и начал ценить силу языка C # — не теряя своей любви к PHP. Я надеюсь, что вы можете сделать то же самое.
- Подпишитесь на нас в Твиттере или подпишитесь на ленту Nettuts + RSS для получения лучших учебных материалов по веб-разработке.