Анналы sb output aspx form. Тестирование динамического кода. Выполнение проверки достоверности
Перевод: Влад Мержевич
Посещая Интернет вы увидите ряд сайтов, которые используют калькулятор для расчёта разных вещей, таких как: погашение ссуды, ставки по ипотечным кредитам, налоги, страхование и многое другое. До сегодняшнего дня у вас не было способа семантической разметки результата таких вычислений. Встречайте - элемент
Определение
Элемент output представляет собой результат вычислений. Спецификация WHATWG HTML .
Как и следовало ожидать, если ввести только одно значение, функция возвращает NaN. Она пытается сложить число и значение undefined, в итоге 1 + undefined = undefined.
Использование атрибута for
Возьмём за основу предыдущий пример и добавим к
Пример 2. Использование атрибута for для элемента
Свойство valueAsNumber
В HTML5 представлено свойство JavaScript valueAsNumber для полей формы (в частности: number, date, range). Оно возвращает значение в виде числа, а не строки, то есть нам больше не нужно использовать parseInt или parseFloat , и оператор + складывает, а не склеивает.
Пример 3. Использование свойства valueAsNumber для получения числового значения из полей
Финансовый калькулятор: подробный пример
Для более реалистичного примера сделаем финансовый калькулятор, который умножает количество часов на почасовую ставку и добавляет налог для получения конечного результата (пример 4).
Пример 4. Финансовый калькулятор отображает результат в элементе
Ничего слишком сложного не происходит. На самом деле скрипты настолько простые, что даже я могу их сделать.
Немного спорный пример с использованием
Пока писалась эта статья я нашёл ряд примеров использования элемента
Пример. 5. Использование с элементом
Использование
Поддержка в браузерах
Хорошая новость - все современные браузеры поддерживают в некоторой степени элемент
Браузер | Поддержка |
---|---|
Chrome | 13+ |
Safari | 5.1+ |
Firefox | 6+ |
Opera | 9.20+ |
Internet Explorer | 10+ |
Все примеры, которые мы видели до сих пор, должны безупречно работать в Opera 11.5 +, Safari 5.1+ и Chrome 13 +. IE, как и следовало ожидать, несколько отстаёт,
This is the HttpHandler and HttpModule in real scenario article series. In this series we are learning various concepts and uses of HttpHandler and HttpModule. In our previous article we have covered various important concepts, you can read them here.
This is another example where we can measure the time gap between a request and its response. Sinice HttpModule is in the middle of a request and response, we can measure the time taken by a specific HTTP request.
In this example we will measure the time taken by one HTTP request to complete. Have a look at the following example.
using System;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Xml.Linq;
using Newtonsoft.Json;
namespace WebApp
public void Dispose()
Context.BeginRequest += new EventHandler (OnBeginRequest);
Context.EndRequest += new EventHandler (OnEndRequest);
// Record the time of the begin request event.
public void OnBeginRequest(Object sender, EventArgs e)
HttpApp.Context.Items[ "beginTime" ] = DateTime .Now;
public void OnEndRequest(Object sender, EventArgs e)
HttpApplication httpApp = (HttpApplication )sender;
// Get the time of the begin request event.
DateTime beginTime = (DateTime )httpApp.Context.Items[ "beginTime" ];
// Evaluate the time between the begin and the end request events.
TimeSpan ts = DateTime .Now - beginTime;
// Write the time span out as a request header.
HttpApp.Context.Response.AppendHeader("TimeSpan" , ts.ToString());
// Get the current user"s Machine Name.
string user = WindowsIdentity .GetCurrent().Name;
// Display the information in the page.
StringBuilder sb = new StringBuilder ();
Sb.AppendLine("RequestTimeInterval from HttpModule Output
"
);
Sb.AppendFormat("Current user: {0}
"
, user);
Sb.AppendFormat("Time span between begin-request and end-request events: {0}
"
,
Ts.ToString());
HttpApp.Context.Response.Output.WriteLine(sb.ToString());
The implementation is pretty simple. When a request is coming we are recording the time and when the request finishs we again measure the time and then calculate the time taken by that specific HTTP request to complete.
Add the following code to your web.config file to register the HttpModule.
< system.webServer >
< modules >
< add name = " mymodule1 " type = " WebApp.MyHttpModule1 " />
modules >
< system.webServer >
Here is the output of the receding implementation. We see that the HTTP request is taking nearly 2 miliseconds to finish. (Ha..Ha..Pretty fast execution).
Count number of requests by user by Form authentication
This is another real situation where we can implement HttpModule as a solution. Sometimes it’s very useful to count the number of login attemts from a specific user. There might be a business need or other motive behind that (we are not concerned with it).
So, if the requirement is something like. “We need to count the number of logins of a specific user, then we can implement the counting mechanism using HttpModule. I am not demanding that, this is the best and only one solution in this reqirement, but this is also a possible solution among others.
When we want to count the login attempts of a user then we need to count with respect to username and for that we will implement Form Authentication in the application.
Step 1: Create login form with a few controls
Here is the code of the login form. It’s very simple. We just must use two text boxes with one button.
<% @ Page Language ="C#" AutoEventWireup ="true" CodeBehind ="login.aspx.cs" Inherits ="WebApp.login" %>
< html xmlns ="http://www.w3.org/1999/xhtml">
< head runat ="server">
< title > title >
head >
< body >
< form id ="form1" runat ="server">
< div >
UserName:- < asp : TextBox ID ="TextBox1" runat ="server"> asp : TextBox >< br />
Password:- < asp : TextBox ID ="TextBox2" runat ="server"> asp : TextBox >< br />
< asp : Button ID ="Login" runat ="server" Text ="Button" OnClick ="Login_Click" />
div >
form >
body >
html >
Step 2: Write the following code in code behind of login form
This is the normal form of Authentication code, nothing special in this. We are checking the username and password with a constant string, in reality it might check with some persistence storage. Once both the username and password is “abc” we are setting the form authentication cookies and then redirecting the user to the Home page.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Security;
using System.Web.Security;
namespace WebApp
public partial class login : System.Web.UI. Page
protected void Page_Load(object sender, EventArgs e)
protected void Login_Click(object sender, EventArgs e)
if (this .TextBox1.Text == "abc" && this .TextBox2.Text == "abc" ){
FormsAuthentication .SetAuthCookie(
this .TextBox1.Text.Trim(), true );
Response.Redirect("Home.aspx" );
Step 3: Configure Form Authentication in web.config file
This is necessary when we want to configure Form Authentication in an ASP.NET application.
< authentication mode = " Forms " >
< forms loginUrl = " login.aspx " >
forms >
authentication >
Step 4: Implement HttpModule that will count user
Here is the core part of this example. We will implement one HttpModule that will count the user depending one URL.
Have a look at the following code. Here we will detect the user who will try to browse to the Home.aspx page.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Security.Principal;
using System.Text;
using System.Web;
using System.Xml.Linq;
using Newtonsoft.Json;
namespace WebApp
public class MyHttpModule1 : IHttpModule
public void Dispose()
throw new NotImplementedException ();
public void Init(HttpApplication context)
Context.AuthenticateRequest += new EventHandler (OnAuthentication);
void OnAuthentication(object sender, EventArgs a)
HttpApplication application = (HttpApplication )sender;
HttpContext context = application.Context;
if (context.Request.Url.AbsolutePath.Contains("Home" ))
String user = context.User.Identity.Name;
We are checking the URL, If the URL pattern contains the keyword Home then will check the username as it’s showing in the following example.
And when we are getting the username it’s very simple to implement a counting mechanism depending on username. I have skipped this part to make the example simple. With a little effort, you can implement the rest.
Conclusion
In this article we have learned two important concepts for implementing HttpModule as a solution. I hope you have understood the real example of HttpModule in this article.
Виртуальные пути
Между виртуальными и физическими путями существует стандартное отображение. Виртуальный путь наподобие /Content/RequestReporter.aspx соответствует файлу веб-формы /Content/RequestReporter.aspx. Главное преимущество такого отображения заключается в простоте - достаточно взглянуть на URL и немедленно понять, каким образом виртуальный путь будет применяться для генерации ответа.
Однако прямое отображение между виртуальными и физическими путями не всегда идеально. Например, модернизация приложения может привести к перемещению и переименованию файлов, из-за чего перестанут работать URL, помещенные пользователями в закладки. Может потребоваться согласование приложения Web Forms с более широкой схемой URL, которая не соответствует стандартному подходу. Подобная ситуация распространена в корпоративных приложениях, в которых согласованность URL расценивается как способ помочь пользователям в переходе непосредственно к нужному контенту или функциональности.
Короче говоря, существует множество причин для изменения URL, на которые реагирует приложение, и все они приводят к нарушению работы прямых ссылок между виртуальными и физическими путями. В последующих разделах мы опишем разнообразные подходы, доступные для управления виртуальными путями и позволяющие настраивать схему URL, которую приложение раскрывает внешнему миру.
Вы узнаете, что есть много способов достижения того же самого базового результата. Причина в том, что все эти средства постепенно добавлялись с течением времени. Самое последнее добавление - поддержка маршрутизации URL - является тем средством, с которого следует начинать. Однако мы также рассматриваем ряд удобных старых средств, т.к. часто требуется комбинировать одно из них с маршрутизацией URL, чтобы создавать специфическую функциональность в приложении.
Установка стандартных документов
По соглашению, принятому для приложений Web Forms, начальной веб-форме назначается имя Default.aspx. Это не является требованием, но его нужно придерживаться, поскольку сервер IIS сконфигурирован так, что он ищет стандартные файлы, если никакого файла в URL не указано.
Чтобы продемонстрировать это в действии, мы внесли в метод ProcessRequest(), определенный в файле SimpleModule.cs (который мы создали в предыдущей статье), небольшое изменение, которое обеспечивает вывод значения свойства FilePath и URL в окно Output среды Visual Studio. Изменение показано в примере ниже:
// ... private void ProcessRequest(HttpApplication app) { if (app.Request.FilePath == "/Test.aspx") { app.Server.Transfer("/Content/RequestReporter.aspx"); } WriteMsg("URL запроса: {0} {1}", app.Request.RawUrl, app.Request.FilePath); } // ...
Для тестирования встроенного поведения запустите приложение и запросите корневой URL (у нас он выглядит как http://localhost:32404/, но у вас может быть другой номер порта). Браузер отобразит содержимое файла Default.aspx, а в окне Output будут отображаться следующие сообщения:
Последнее из этих сообщений отражает попытку сервера IIS найти файл, с помощью которого должен быть обслужен запрос. (Первые два сообщения объясняются в следующем разделе.) Сервер IIS имеет возможность отыскать файл Default.aspx для обслуживания запроса корневого URL, т.к. мы соблюдали соглашение об именовании. В противном случае IIS Express потерпел бы неудачу и возвратил браузеру ошибку 404, указывающую на то, что файл найти не удалось.
Сервер IIS ищет следующие стандартные документы: Default.html, Default.asp, index.htm, index.html, iisstart.htm и, наконец, default.aspx. (Мы не знаем, почему имя файла default.aspx представлено символами нижнего регистра, но это не играет роли, потому что имена веб-форм нечувствительны к регистру.)
Переопределить эти стандартные документы можно в файле Web.config. Это стоит делать, если нужно, чтобы по умолчанию использовалась другая стандартная веб-форма, или требуется сократить количество местоположений, в которые сервер IIS просматривает, прежде чем передает веб-форму на обработку среде ASP.NET.
В примере ниже показаны изменения, внесенные в файл Web.config:
Элемент defaultDocument
добавлен в раздел
Внутри defaultDocument содержится элемент
Обратите внимание, что при указании стандартного документа в атрибуте value ведущий символ / отсутствует. Добавление ведущего символа / приводит к отображению сообщения об ошибке.
Чтобы увидеть результат, запустите приложение и запросите URL вида http://localhost:<порт>/, где <порт> это номер порта, прослушиваемого сервером IIS Express на предмет поступления запросов для этого приложения. Новая политика в отношении стандартного документа будет применена, и отобразится вывод, сгенерированный веб-формой RequestReporter.aspx.
Обработка запросов для URL без расширений
При отправке запроса к корневому URL в предыдущем разделе в окне Output среды Visual Studio отображались три сообщения:
URL запроса: / / URL запроса: / / URL запроса: / /default.aspx
Мы объяснили, что последнее сообщение говорит о применении политики IIS, касающейся стандартного документа. Первоначально это был запрос к Default.aspx, но мы изменили политику IIS в отношении стандартного документа. Перед тем, как IIS применяет такую политику, он предоставляет ASP.NET шанс обработать запрос - это причина, по которой отображено первое сообщение.
Среда ASP.NET имеет обработчик для этого запроса, однако по умолчанию он не делает ничего полезного. Таким обработчиком является внутренний класс TransferRequestHandler , отвечающий за обработку URL без расширений, которые позволяют ASP.NET обрабатывать запросы к виртуальным путям, не содержащим файловые расширения, такие как.aspx.
Класс TransferRequestHandler не делает особенно много с запросами для URL без расширений. Он просто указывает серверу IIS на необходимость создания и обработки второго запроса, не используя TransferRequestHandler в качестве обработчика - именно поэтому отображается второе сообщение.
Чтобы делать нечто полезное с запросами для URL без расширений, понадобится создать обработчик и заменить им TransferRequestHandler. Мы добавили в проект новый файл класса по имени ExtensionlessHandler.cs, содержимое которого приведено в примере ниже:
Using System.IO; using System.Web; namespace PathsAndURLs { public class ExtensionlessHandler: IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.Write("
HTTP-обработчик Expressionless
"); string vpath = context.Request.Path; if (vpath == "/") { context.Server.Transfer("/Default.aspx"); } else if (File.Exists(context.Request.MapPath(vpath + ".aspx"))) { context.Server.Transfer(vpath + ".aspx"); } else { context.Response.StatusCode = 404; context.ApplicationInstance.CompleteRequest(); } } public bool IsReusable { get { return false; } } } }Этот обработчик будет получать запросы для URL без расширений и с помощью метода HttpServerUtility.Transfer() передавать запросы веб-форме. Определение, какой веб-форме должен быть передан запрос, реализуется элементарно. Если запрошенным URL является /, мы направляем его Default.aspx, а для всех других запросов просто добавляем расширение.aspx к запрошенному URL и проверяем, существует ли в приложении файл с таким именем. Если это так, мы передаем ему запрос, а в противном случае возвращаем ответ с ошибкой 404.
Чтобы обработчик смог принимать запросы, его необходимо зарегистрировать. В примере ниже показаны изменения, внесенные в файл Web.config:
Для обработки URL без расширений мы устанавливаем атрибут path в "*." (символы звездочки и точки). Обработка URL без расширений выполняется перед применением политики IIS, касающейся стандартного документа, поэтому предыдущая конфигурация была переопределена и корневой URL (/) отображен на Default.aspx. В качестве дополнения мы можем запрашивать любую веб-форму, не указывая файловое расширение. Таким образом, например, запрос для виртуального пути /Content/RequestReporter сгенерирует ответ на основе веб-формы /Content/RequestReporter.aspx.
Переписывание путей
В предыдущем примере использовался метод HttpServerUtility.Transfer(), который нормально работает с веб-формами, но не очень хорошо с другими типами файлов, такими как обобщенные обработчики (файлы ashx). Мы могли бы применить прием с оболочкой для Page, но это грубый трюк, и мы не являемся его сторонниками.
Имея все это в виду, рассматриваемый далее подход может быть реализован более широко, однако это должно делаться внутри модуля. Прием называется переписыванием путей и представляет собой просто процесс изменения пути, связанного с запросом. Чтобы показать пример использования такого подхода, мы создали файл класса по имени PathModule.cs с содержимым, приведенным в примере ниже:
Using System; using System.IO; using System.Web; namespace PathsAndURLs { public class PathModule: IHttpModule { private static readonly string extensions = { ".aspx", ".ashx" }; public void Init(HttpApplication app) { app.BeginRequest += (src, args) => HandleRequest(app); } private void HandleRequest(HttpApplication app) { if (app.Request.CurrentExecutionFilePathExtension == String.Empty) { string target = null; string vpath = app.Request.CurrentExecutionFilePath; if (vpath == "/") { target = "/Default.aspx"; } else { foreach (string ext in extensions) { if (File.Exists(app.Request.MapPath(vpath + ext))) { target = vpath + ext; break; } } } if (target != null) { app.Context.RewritePath(target); } } } public void Dispose() { // Ничего не освобождается } } }
Так как это модуль, его необходимо зарегистрировать в файле Web.config:
Этот модуль обрабатывает событие BeginRequest и просматривает запросы, которые не имеют файлового расширения. В рассматриваемом примере изменяется способ обработки корневого URL, т.е. для обработки запросов применяется веб-форма Default.aspx, которую можно увидеть, запустив приложение и запросив /.
Главное улучшение по сравнению с предыдущим примером связано с проверкой существования файлов, имеющих расширения aspx или ashx, если запрошенным URL не является /. Это позволяет приложению поддерживать дружественные URL - именно так называются запросы веб-форм и обработчиков без указания файловых расширений. (Происхождение данного названия нам не известно, однако мы его придерживаемся.)
Прием является вариацией обработки URL без расширений и по-прежнему требует сопоставления виртуальных путей с файлами в приложении, но без указания расширений.aspx или.ashx, которые многие разработчики считают непривлекательными.
Ключевым в модуле является метод RewritePath() , который определен в классе HttpContext. Этот метод позволяет изменить путь при условии, что это делается перед событием жизненного цикла MapRequestHandler .
Метод RewritePath() не имеет ограничений, с которыми мы сталкиваемся при использовании методов класса HttpServerUtility, т.е. появляется возможность поддерживать запросы к обобщенным обработчикам, а также файлам веб-форм.
В классе HttpContext определено несколько перегруженных версий метода RewritePath(), которые описаны в таблице ниже:
Две перегруженных версии метода RewritePath() принимают аргумент типа bool по имени rebase, который отвечает за изменение путей, используемых элементами управления для создания URL - процесс, известный как изменение базы клиента .
В Microsoft предлагается загружаемый пакет под названием URL Rewriting Engine (Механизм переписывания URL) , который позволяет выражать правила переписывания в файле Web.config, а не в коде.
Реальный пример переписывания путей
Ранее метод HttpContext.RewritePath() использовался для добавления файлового расширения, т.е. мы могли бы поддерживать URL без расширений и дружественные URL. С помощью средства переписывания путей можно реализовать очень сложные действия, из-за чего мы применяем его в проектах, требующих поддержки необычных схем URL и таких, которые варьируются на основе характеристик запросов, отличных от путей.
В целях иллюстрации мы рассмотрим пример, основанный на одном из реальных проектов, над которым мы работали недавно. Нам необходимо было повторно построить приложение с применением ASP.NET, но старые URL были жестко закодированы в других приложениях и должны были остаться работоспособными.
Одна из проблем, с которой мы столкнулись, заключалась в том, что запросы к URL вида /accounts нужно было направлять двум веб-формам в зависимости от значения данных формы, имеющего имя function. Когда значение function не превышало 100, запрос должен отправляться веб-форме Default.aspx, а для всех других значений - веб-форме /Content/RequestReporter.aspx (разумеется, это не веб-формы из реального проекта; мы просто хотим воспользоваться уже готовыми файлами в примере приложения).
Чтобы продемонстрировать проблему, мы создали новую веб-форму по имени Split.aspx, контент которой представлен в примере ниже. Эта веб-форма будет эмулировать унаследованных клиентов с жестко закодированными URL:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Split.aspx.cs" Inherits="PathsAndURLs.Split" %>
Веб-форма содержит простую HTML-форму, которая позволяет ввести значение function и отправить его серверу по щелчку на кнопке "Отправить". Элемент