Передача інформації між сторінками

Одним з найбільш серйозних обмежень стану подання є його тісний зв'язок з конкретною сторінкою. Коли користувач переходить на іншу сторінку, ця інформація втрачається. Існує кілька варіантів розв'язання проблеми та те, яке з них буде найкращим, залежить від наявних вимог.

рядок запиту

Перевага рядки запиту в тому, що вона проста і не привносить ніякого навантаження на сервер. На відміну від міжсторінкових відправки, рядок запиту може переносити одну і ту ж інформацію зі сторінки на сторінку. Однак з нею пов'язано кілька обмежень:

Інформація візуально доступна користувачу і будь-якого іншого працює в Інтернеті людині.

Заповзятливий користувач може вирішити змінити рядок запиту і надати нові значення, які програма ніяк не очікує отримати, і від яких вона не захищена.

Але все одно додавання інформації в рядок запиту є корисним прийомом. Він особливо підходить для додатків баз даних, в яких користувачеві відображається список елементів, відповідних записів в базі даних (наприклад, це може бути список товарів). Користувач вибирає елемент, після чого він перенаправляється на іншу сторінку, яка містить детальну інформацію про вибраний елемент.

Один з найбільш простих способів реалізувати таке проектне рішення - змусити першу сторінку відправляти ідентифікатор елемента другій сторінці. Друга сторінка потім шукає цей елемент в базі даних і відображає детальну інформацію про нього. Ця технологія часто застосовується на сайтах електронної комерції, наприклад, Amazon.com.

Щоб зберегти інформацію в рядку запиту, її необхідно помістити туди самостійно. На жаль, способу зробити це за допомогою колекцій не існує. Як правило, це означає, що доведеться використовувати спеціальний елемент керування HyperLink або оператор Response.Redirect (), подібний показаному нижче:

Для відправки безлічі параметрів вони повинні розділятися за допомогою амперсанда ():

Яка отримує сторінці легше працювати з рядком запиту. Вона може витягувати значення з словникової колекції QueryString. наданої вбудованим об'єктом Request, як показано нижче:

Якщо рядок запиту не містить параметр recordID або якщо вона містить цей параметр, але без значення, рядок ідентифікатора встановлюється в null. Зверніть увагу, що інформація завжди витягується у вигляді рядка, яка потім може бути перетворена в інший простий тип даних. Значення в колекції QueryString індексуються на ім'я змінної.

На жаль, ASP.NET не надає механізму для автоматичної перевірки або шифрування даних рядка запиту. Він міг би працювати в основному так само, як механізм захисту стану уявлення. Без цієї функціональності рядок запиту дуже вразлива.

URL-кодування

Більш того, деякі символи мають спеціальне значення. Наприклад, символ служить для поділу параметрів в рядку запиту, символ + є альтернативним способом для подання пробілу, а символ # застосовується для вказівки на конкретну закладку на веб-сторінці. Спроба відправити в рядку запиту значення, що включають будь-який з цих символів, обов'язково призведе до втрати будь-яких даних.

За допомогою методів класу HttpServerUtility можна забезпечити автоматичне кодування даних. Наприклад, нижче показано, як закодувати рядок довільних даних для використання в рядку запиту. Цей код просто замінює все неприпустимі символи послідовностями перетворених символів:

Для повернення рядку з закодованим URL початкового значення можна використовувати метод HttpServerUtility.UrlDecode (). Однак в разі рядки запиту виконувати цей крок немає необхідності, оскільки ASP.NET автоматично декодує значення при отриманні доступу до них через колекцію Request.QueryString.

Зазвичай безпечніше викликати метод UrlDecode () вдруге, тому що декодування даних, які вже були декодовані, не викликає проблем. Єдиним винятком є ​​наявність значення, яке обґрунтовано включає знак +. В такому випадку виклик методу UrlDecode () призведе до перетворення цього знака в символ пропуску.

Міжсторінкових зворотна відправка

Ви вже знаєте, яким чином сторінки ASP.NET виконують зворотну відправку самим собі. При такого зворотного відправлення поточний зміст всіх елементів управління сторінки (разом з вмістом прихованого поля стану подання) відправляється в формі для цієї ж самої сторінки.

Для передачі інформації з однієї сторінки на іншу можна використовувати точно такий же механізм, але тільки відправляти дані іншій сторінці. Цей прийом виглядає досить просто в теорії, але на практиці може мати багато "підводних каменів". У разі недотримання запобіжних заходів, все може закінчитися отриманням інформації, занадто тісно пов'язаних між собою і вкрай незручних для розширення і налагодження.

У показаному нижче фрагменті коду визначається форма з двома текстовими полями і кнопкою, яка відправляє дані сторінці по імені CrossPage2.aspx:

Сторінка CrossPage2.aspx може взаємодіяти з об'єктами сторінки CrossPagel.aspx, використовуючи властивість PreviousPage. наприклад:

Зверніть увагу, що перед спробою доступу до об'єкта PreviousPage ця сторінка перевіряє посилання на предмет null. Якщо об'єкт PreviousPage не існує, міжсторінкових зворотна відправка не виконується.

Щоб ця система працювала, ASP.NET застосовує цікавий трюк. Коли друга сторінка вперше намагається отримати доступ до об'єкта Page.PreviousPage, середа ASP.NET повинна створити об'єкт попередньої сторінки. Для цього ASP.NET фактично запускає цикл обробки сторінки, але перериває його прямо перед початком етапу PreRender. По ходу справи ASP.NET також створює об'єкт-заступник HttpResponse, який мовчки перехоплює і ігнорує всі вступники з попередньої сторінки команди Response.Write ().

Однак відбуваються ще деякі цікаві побічні ефекти. Наприклад, спрацьовують всі події попередньої сторінки, включаючи Page.Load, Page.Init і навіть Button.Click для кнопки, яка запустила зворотний відправку (якщо вона визначена). Спрацьовування цих подій є обов'язковим, тому що вони необхідні для коректної ініціалізації сторінки.

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

Отримання специфічної для сторінки інформації

У розглянутому вище прикладі витягує з попередньої сторінки інформація обмежувалася тільки членами класу Page. Якщо потрібно отримати більш специфічні деталі, такі як значення елементів управління, знадобиться привести посилання PreviousPage до відповідного типу.

Нижче показаний приклад того, як це повинно робитися. Спочатку проводиться перевірка, чи є об'єкт PreviousPage екземпляром очікуваного джерела (CrossPage1):

У беспроектном веб-сайті Visual Studio може помітити такий код як помилку, вказуючи на відсутність інформації про тип класу початкової сторінки (в даному прикладі це CrossPage1). Однак після компіляції веб-сайту ця помилка зникає.

Цю проблему можна вирішити і іншим способом. Замість того щоб вручну приводити посилання до відповідного типу, можна додати в код сторінки директиву елемента управління PreviousPageType. яка позначає очікуваний тип сторінки, яка ініціює міжсторінкових зворотну відправку, наприклад:

Однак такий підхід є менш гнучким, тому що передбачає використання єдиного типу, не дозволяючи мати справу з ситуаціями, коли необхідно, щоб міжсторінкових зворотну відправку ініціювало більше однієї сторінки. Тому підхід, який передбачає приведення до відповідного типу, потребує менше часу.

Оскільки властивість PostBackUrl дозволяє вказувати тільки на одну сторінку, може здатися, що міжсторінкових зворотну відправку допускається встановлювати тільки між двома сторінками. Однак це не так - ця модель дуже легко розширюється за допомогою різноманітних технологій. Наприклад, можна змінити властивість PostBackUrl програмно, щоб вибрати іншу цільову сторінку. Або навпаки зробити так, щоб цільова сторінка в міжсторінкових зворотного відправлення даних могла перевіряти значення властивості PreviousPage і визначати, чи стосується воно до одного з декількох класів. Потім в залежності від того, яка сторінка ініціювала міжсторінкових відправку, можна вирішувати різні завдання.

Після приведення попередньої сторінки до відповідного типу отримувати безпосередньо доступ до значень її елементів управління як і раніше не вийде. Це пов'язано з тим, що елементи управління оголошені як захищені члени. Вирішити цю проблему можна, додавши в клас сторінки властивості, які є оболонками для змінних елементів управління, наприклад:

Однак, як правило, такий підхід не є найкращим. Проблема в тому, що він розкриває занадто багато деталей, тим самим надаючи цільовій сторінці можливість зчитувати властивості всіх елементів управління. Якщо пізніше виникне необхідність змінити сторінку так, щоб в ній використовувалися інші елементи управління, зберегти ці властивості буде дуже важко і тому, швидше за все, доведеться просто переписати код обох сторінок.

Більш вдалий варіант - визначити специфічні обмежені методи або властивості, извлекающие тільки необхідну інформацію. наприклад:

При такому підході відносини між сторінками є добре документовані і не уявляють складності для розуміння. У разі зміни елементів управління на вихідній сторінці інтерфейс для загальнодоступних методів або властивостей, швидше за все, вдасться залишити той же. Наприклад, в разі зміни елементів управління, що відповідають за отримання інформації про ім'я в попередньому прикладі, все одно довелося б вносити поправки в код властивості FullName. Однак після внесення всіх цих поправок в CrossPage1.aspx сторінку CrossPage2.aspx змінювати взагалі не потрібно.

У деяких випадках замість міжсторінкових зворотного відправлення краще використовувати різновид елемента управління, що імітує безліч сторінок або безліч кроків, наприклад, окремі елементи управління Panel, Multiview або Wizard. Такі елементи управління дозволяють забезпечувати для користувача багато в чому точно такий же результат і спрощують модель кодування.

Виконання міжсторінкових відправки в будь-якому обробнику подій

Як розповідалося в попередньому розділі, міжсторінкових відправка доступна тільки з елементами управління, які реалізують інтерфейс IButtonControl. Однак існує і обхідний шлях. Цей шлях має на увазі використання перевантаженої версії методу Server.Transfer () для перемикання на нову ASP.NET-сторінку, не зачіпаючи інформацію стану уявлення. Все, що потрібно - це додати в даний метод булевский параметр preserveForm і встановити для нього значення true, як показано нижче:

Цікаво те, що існує спосіб, що дозволяє розрізняти, коли міжсторінкових зворотна відправка ініціюється безпосередньо через кнопку, а коли - через метод Server.Transfer (). Хоча доступ до об'єкта Page.PreviousPage можливий в обох випадках, в ситуації, коли використовується метод ServerTransfer (), властивість Page.PreviousPage.IsCrossPagePostBack має значення false. Нижче показаний код, який демонструє, як працює ця логіка:

Міжсторінкових зворотна відправка і перевірка достовірності

Коли перевірка достовірності використовується в сценарії з міжсторінкових зворотного відправкою, завжди існує ймовірність виникнення яких-небудь проблем. Давайте подивимося, що відбувається, коли застосовується міжсторінкових зворотна відправка, а вихідна сторінка включає елементи управління перевіркою достовірності. На малюнку нижче показаний приклад сторінки, яка містить елемент керування RequiredFieldValidator, що вимагає введення в текстовому полі:

Передача інформації між сторінками

Обидві кнопки на цій сторінці мають властивість CausesValidation, встановлене в true. В результаті, якщо ви клацнете на кнопці міжсторінкових зворотна відправка, клієнтський код перевірки достовірності в браузері не дозволить це зробити. Замість цього з'явиться повідомлення про помилку.

Можна також подивитися, що відбувається, коли клієнтський сценарій не підтримується браузером, встановивши властивість RequiredFieldValidator.EnableClientScript в false. (Після поліпшення коду його слід знову встановити в true.) Якщо тепер клацнути на одній з кнопок, сторінка буде відправлена ​​назад сервера і з'явиться нова сторінка.

Щоб виключити таку поведінку, перш ніж виконувати будь-яке інше дію, на цільовій сторінці необхідно перевірити достовірність вихідної сторінки за допомогою властивості Page.IsValid. Це стандартний метод захисту, який використовується в будь-який веб-формі, яка реалізує перевірку достовірності. Різниця полягає лише в тому, що якщо дані на сторінці є недійсними, просто нічого не робити буде недостатньо. Тут доведеться виконати ще один додатковий крок: повернути користувача на вихідну сторінку. Ось який для цього знадобиться код в цільовій сторінці:

Наведений код можна поліпшити. Зараз, коли користувач повертається на вихідну сторінку, повідомлення про помилку не виникає, тому що сторінка просто запитується повторно (а не відправляється назад). Це можна виправити, встановивши прапор, який дозволить вихідної сторінці дізнатися, що дана сторінка була відхилена цільової сторінкою. Нижче показаний фрагмент коду, який додає такий прапор в рядок запиту:

Тепер вихідна сторінка повинна просто перевірити наявність цього значення в рядку запиту і відповідним чином виконати перевірку достовірності. Для будь-яких неприпустимих даних відображаються повідомлення про помилки:

Цей приклад демонструє, що міжсторінкових зворотні відправки часто виявляються складніше, ніж спочатку очікують розробники. Невміле їх використання може призводити до отримання тісно пов'язаних між собою сторінок з важко виявляються залежностями, які ускладнюють зміна сторінок в майбутньому. Тому перш ніж застосовувати їх в якості методу для передачі інформації, обов'язково зважте всі "за" і "проти".

Схожі статті