The walkthrough below demonstrates step-by-step how to use them. In the demo, we use date-time to determine whether a page is cached (in the PageLoad event, we write the date-time in a Label control named “ lblResult ”.):

  1. The Duration attribute
  • Add @OutputCache in the ASPX markup and specify the expiration time. In this case, we assign 10s for it. For example: OutputCache Duration="10" VaryByParam="none" .
  • Run the ASP.NET web application and launch this page, and we will see that the date-time on the page won"t change 10s when the page is reloading.
<%@ OutputCache Duration =" 10" VaryByParam =" none" %> < !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" > < html xmlns =" http://www.w3.org/1999/xhtml" > < head runat =" server" > < title > OutPutCacheWithDuration< /title > < /head > < body > < form id =" form1" runat =" server" > < div > < asp:Label ID =" lblResult" runat =" server" > < /asp:Label > < br / > < br / > < asp:Button ID =" btnPostBack" runat =" server" Text =" Post Back" / > < p > The page will be cached 10s, and then you can click Button to update datetime. < /p > < /div > < /form > < /body > < /html >
  • The VaryByControl attribute
    • Drag and drop a DropDownList in the page and add three items to it.
    • Add @OutputCache in the ASPX markup and specify the expiration time and VaryByControl attribute. For example: OutputCache Duration="1000" VaryByControl="ddlOption" .
    • Run the ASP.NET web application and launch this page, we can see that the different items have their corresponding cache.
    <%@ OutputCache Duration =" 1000" VaryByControl =" ddlOption" %> < !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" > < html xmlns =" http://www.w3.org/1999/xhtml" > < head runat =" server" > < title > OutPutCacheWithVaryByControl< /title > < /head > < body > < form id =" form1" runat =" server" > < div > < asp:Label ID =" lblResult" runat =" server" > < /asp:Label > < br / > < br / > < asp:DropDownList ID =" ddlOption" runat =" server" AutoPostBack =" True" OnSelectedIndexChanged =" ddlOption_SelectedIndexChanged" > < asp:ListItem Selected =" True" > Option One< /asp:ListItem > < asp:ListItem > Option Two< /asp:ListItem > < asp:ListItem > Option Three< /asp:ListItem > < /asp:DropDownList > < p > The page will be rendered from cache basing on the selected item of DropDownList. The different item has corresponding cache. < /p > < /div > < /form > < /body > < /html >
  • The VaryByCustom attribute
    • Add @OutputCache in the ASPX markup and specify the expiration time and VaryByControl attribute with the "browser" value. For example: OutputCache Duration="1000"VaryByCustom="browser"VaryByParam="none" .
    • Run the ASP.NET web application and launch this page with IE and Firefox (or a browser with a different name, major version), and we will see that there is different cache versions for different browsers.
    <%@ OutputCache Duration =" 1000" VaryByCustom =" browser" VaryByParam =" none" %> < !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" > < html xmlns =" http://www.w3.org/1999/xhtml" > < head runat =" server" > < title > OutPutCacheWithVaryByCustom< /title > < /head > < body > < form id =" form1" runat =" server" > < div > < asp:Label ID =" lblResult" runat =" server" > < /asp:Label > < br / > < br / > < asp:Button ID =" btnPostBack" runat =" server" Text =" Post Back" / > < p > The page will be rendered from cache basing on the version of browser, such as IE and FireFox. < /p > < /div > < /form > < /body > < /html >
  • The VaryByParam attribute
    • Add @OutputCache in the ASPX markup and specify the expiration time and VaryByParam attribute with an " id " value. For example: OutputCache Duration="1000" VaryByParam="id" .
    • Run the ASP.NET web application and launch this page, and we can request it using a QueryString " id " with a different value.
    ~/OutputCacheWithParam.aspx?id=1 ~/OutputCacheWithParam.aspx?id=2 > <%@ OutputCache Duration =" 1000" VaryByParam =" id" %> < !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" > < html xmlns =" http://www.w3.org/1999/xhtml" > < head runat =" server" > < title > OutPutCacheWithVaryByParam< /title > < /head > < body > < form id =" form1" runat =" server" > < div > < asp:Label ID =" lblResult" runat =" server" > < /asp:Label > < p > The page will be rendered from cache until the value of QueryString named "id" is changed or Duration is expiration. < /p > < /div > < /form > < /body > < /html >

    Points of Interest

    If there is any problem, you can take a look at the ReadMe.txt file in each sample project, which contains a step by step tutorial of how to build the project.

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

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

    < body >

    < form id ="form1" runat ="server">

    < div >

    UserName:- < asp : TextBox ID ="TextBox1" runat ="server">< br />

    Password:- < asp : TextBox ID ="TextBox2" runat ="server">< br />

    < asp : Button ID ="Login" runat ="server" Text ="Button" OnClick ="Login_Click" />

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

    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.

    Перевод: Влад Мержевич

    Посещая Интернет вы увидите ряд сайтов, которые используют калькулятор для расчёта разных вещей, таких как: погашение ссуды, ставки по ипотечным кредитам, налоги, страхование и многое другое. До сегодняшнего дня у вас не было способа семантической разметки результата таких вычислений. Встречайте - элемент ! В этой статье мы расскажем об этом элементе и некоторых связанных с ним трюках JavaScript. Расщёлкнем этот орешек.

    Определение

    , новый элемент в HTML5, применяется в формах. Спецификации WHATWG HTML описывает очень просто.

    Элемент output представляет собой результат вычислений. Спецификация WHATWG HTML .

    Как и следовало ожидать, если ввести только одно значение, функция возвращает NaN. Она пытается сложить число и значение undefined, в итоге 1 + undefined = undefined.

    Использование атрибута for

    Возьмём за основу предыдущий пример и добавим к атрибут for (пример 2). Нам нужно добавить идентификаторы каждого связанного , это аналогично атрибуту for для

    Пример 2. Использование атрибута for для элемента

    + =

    Свойство valueAsNumber

    В HTML5 представлено свойство JavaScript valueAsNumber для полей формы (в частности: number, date, range). Оно возвращает значение в виде числа, а не строки, то есть нам больше не нужно использовать parseInt или parseFloat , и оператор + складывает, а не склеивает.

    Пример 3. Использование свойства valueAsNumber для получения числового значения из полей

    + =

    Финансовый калькулятор: подробный пример

    Для более реалистичного примера сделаем финансовый калькулятор, который умножает количество часов на почасовую ставку и добавляет налог для получения конечного результата (пример 4).

    Пример 4. Финансовый калькулятор отображает результат в элементе

    Invoice

    £

    Total: £0

    Ничего слишком сложного не происходит. На самом деле скрипты настолько простые, что даже я могу их сделать.

    Немного спорный пример с использованием

    Пока писалась эта статья я нашёл ряд примеров использования элемента в сочетании с , как показано в примере 5.

    Пример. 5. Использование с элементом

    0/100

    Использование для показа текущего значения пользователю кажется мне вполне разумным применением, но это не результат вычислений как описано в спецификации. Несколько человек на канале IRC согласились со мной, поэтому я подал отчёт об ошибке , где просил внести поправки в определение. С момента написания этой статьи ошибка была решена и определение расширили , так что использование , как показано выше, теперь корректно. Ура!

    Поддержка в браузерах

    Хорошая новость - все современные браузеры поддерживают в некоторой степени элемент . Плохая новость в том, что есть несколько подводных камней.

    Поддержка в браузерах
    Браузер Поддержка
    Chrome 13+
    Safari 5.1+
    Firefox 6+
    Opera 9.20+
    Internet Explorer 10+

    Все примеры, которые мы видели до сих пор, должны безупречно работать в Opera 11.5 +, Safari 5.1+ и Chrome 13 +. IE, как и следовало ожидать, несколько отстаёт, поддерживается в IE10 Platform Preview 2, а oninput поддерживается уже в IE9. Чтобы обойти это в наших простых примерах, мы должны вернуться к надёжному и проверенному getElementById и parseFloat (пример 6).

    But there I had a problem.

    I created an asp.net web application project and than copied .aspx files to _layouts folder and installed code-behind .dll into GAC.

    The AssociationForm.aspx source code was this:

    Code Snippet

    @ Page Language ="C#" AutoEventWireup ="true" CodeBehind ="AssociationForm.aspx.cs" ="SimpleCopyFileForms.AssociationForm.AssociationForm, SimpleCopyFileForms, Version=1.0.0.0, Culture=neutral, PublicKeyToken=****************" %> @ Register Tagprefix ="SharePoint" Namespace ="Microsoft.SharePoint.WebControls" Assembly %> @ Register Tagprefix ="Utilities" Namespace ="Microsoft.SharePoint.Utilities" Assembly ="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> @ Import Namespace ="Microsoft.SharePoint" %> @ Register Tagprefix ="WebPartPages" Namespace ="Microsoft.SharePoint.WebPartPages" Assembly ="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> asp : Content ContentPlaceHolderId ="PlaceHolderMain" runat ="server"> < div > < table > < tr >< td > < td > < asp : ListBox ID ="listBoxLibs" runat ="server"> < tr >< td > Select save type < td > < asp : RadioButtonList ID ="radioButtonListSaveType" runat ="server"> < asp : ListItem Selected ="True" Value ="Append"> Append a random number < asp : ListItem > Overwrite < tr >< td > < asp : Button ID ="btnSubmit" runat ="server" Text ="Submit" onclick ="btnSubmit_Click" /> < td > < asp : Button ID ="btnCancel" runat ="server" Text ="Cancel" onclick ="btnCancel_Click" />

    < SharePoint : FormDigest ID ="FormDigest1" runat ="server">

    < input type ="hidden" name ="WorkflowDefinition" value = <% _STSWriteHTML(Request.Form["WorkflowDefinition"]); %> > < input type ="hidden" name ="WorkflowName" value = <% _STSWriteHTML(Request.Form["WorkflowName"]); %> > < input type ="hidden" name ="AddToStatusMenu" value = <% _STSWriteHTML(Request.Form["AddToStatusMenu"]); %> > < input type ="hidden" name ="AllowManual" value = <% _STSWriteHTML(Request.Form["AllowManual"]); %> > < input type ="hidden" name ="RoleSelect" value = <% _STSWriteHTML(Request.Form["RoleSelect"]); %> > < input type ="hidden" name ="AutoStartCreate" value = <% _STSWriteHTML(Request.Form["AutoStartCreate"]); %> > < input type ="hidden" name ="AutoStartChange" value = <% _STSWriteHTML(Request.Form["AutoStartChange"]); %> > < input type ="hidden" name ="GuidAssoc" value = <% _STSWriteHTML(Request.Form["GuidAssoc"]); %> > asp : Content >

    Then I went to sharepoint library, workflow settings, and set all the necessary information on workflow association page. But after I clicked "Next" I received "Unknown Error". I looked in sharepoint logs and there I saw next exception:

    Code Snippet

    Exception Type: System.Web.HttpCompileException Exception Message: c:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\SimpleCopyFileForms\AssociationForm\AssociationForm.aspx(33): error CS0103: The name "_STSWriteHTML" does not exist in the current context

    Code Snippet

    < input type ="hidden" name ="WorkflowDefinition" value = <% _STSWriteHTML(Request.Form["WorkflowDefinition"]); %>>

    < input type ="hidden" name ="WorkflowName" value = <% _STSWriteHTML(Request.Form["WorkflowName"]); %>>

    < input type ="hidden" name ="AddToStatusMenu" value = <% _STSWriteHTML(Request.Form["AddToStatusMenu"]); %>>

    < input type ="hidden" name ="AllowManual" value = <% _STSWriteHTML(Request.Form["AllowManual"]); %>>

    < input type ="hidden" name ="RoleSelect" value = <% _STSWriteHTML(Request.Form["RoleSelect"]); %>>

    < input type ="hidden" name ="AutoStartCreate" value = <% _STSWriteHTML(Request.Form["AutoStartCreate"]); %>>

    < input type ="hidden" name ="AutoStartChange" value = <% _STSWriteHTML(Request.Form["AutoStartChange"]); %>>

    < input type ="hidden" name ="GuidAssoc" value = <% _STSWriteHTML(Request.Form["GuidAssoc"]); %>>

    tags from AssociationForm.aspx page and tried to associate workflow again. After clicking "Next" I finally was redirected to my AssociationForm.aspx page but when I clicked "Submit" it didn"t go to "Submit" button"s handler, instead it started page load again, so all data which was sent to my page from AddWrkfl.aspx page were lost.

    Can someone suggest what I did wrong?