The "lie"
In Asp.Net development many web form developers tend to think that a Form runat server is a necessity...
Several tutorials, bloggers tend to suggest that there must be a form (or there could be no .aspx page)
This is NOT the case, and I will show/prove it in numerous ways to rid yourself of this "lie"/misconception.
So what is a form (really) in (x)html
W3Scool has the following to tell.
There are 2 ways of sending data from a form, get and post. In Standard (x)Html one can have 0..to many forms.
There is no form
Just as in the movie "The Matrix" you must understand that there is no spoon, or Form runat server. So just because the Visual Studio template show a default form runat server does not mean one HAVE to use it, (the same can be said about the doctag!), in context it's just a text template that one can use as is or change either after creation OR the template itself.
Grasp "there is no form" and the journey towards a more free mind with asp.net webforms development has begun.
About Demo1
Use standard Request Querystring/Form to retrieve standard form values, this could be done automatically in a mvc-like "autobinder" fashion on own POCO's. Always HtmlEncode value to present on page to prevent XSS, this could be done automatically on the control with attribute Mode like: <asp:Literal ID="litResult" runat="server" Mode="Encode" />
Demo1.aspx
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Demo1.aspx.vb" Inherits="Demo1" %>
<!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>Demo 1 without form</title>
</head>
<body>
<h1>Demo with form - without runat server</h1>
<asp:Literal ID="litResult" runat="server" />
<h2>Form with post</h2>
<form action="Demo1.aspx" method="post">
<p>
<label for="name">Name</label>
<input type="text" id="name" name="name" />
</p>
<input type="submit" value="Send" />
</form>
<h2>Form with get</h2>
<form action="Demo1.aspx" method="get">
<p>
<label for="name2">Name</label>
<input type="text" id="name2" name="name" />
</p>
<input type="submit" value="Send" />
</form>
</body>
</html>
Partial Class Demo1
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim name = String.Empty
If Request.Form("name") = Nothing Then
name = If(Request.QueryString("name"), String.Empty)
Else
name = Request.Form("name")
End If
litResult.Text = String.Format("The name is: {0}", HttpUtility.HtmlEncode(name))
End Sub
End Class
About Demo2
Here databinding without a form is shown. Worth of interrest is the strongly typed way of databinding against a known datatype (Customer in this case) instead of the standard Eval("") - *shivers* way of reflecting the value with a magic string villain. (but more on that in a future blog post)
Demo 2
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Demo2.aspx.vb" Inherits="Demo2" %>
<!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>No Form runat server</title>
</head>
<body>
<h1>Databinding Demo with no form</h1>
<asp:Repeater ID="Repeater1" runat="server">
<HeaderTemplate><ul></HeaderTemplate>
<ItemTemplate>
<li><%#Item.ID%> - <%#Item.Name%></li>
</ItemTemplate>
<FooterTemplate></ul></FooterTemplate>
</asp:Repeater>
</body>
</html>
Partial Class Demo2
Inherits System.Web.UI.Page
Protected RandomInstance As New Random
Protected ReadOnly Property Item() As Customer
Get
Return DirectCast(Page.GetDataItem, Customer)
End Get
End Property
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim customers = New List(Of Customer)
customers.Add(New Customer() With {.ID = 42, .Name = "Alfred Futterkiste"})
customers.Add(New Customer() With {.ID = 101, .Name = "Tomas Edwards"})
Repeater1.DataSource = customers
Repeater1.DataBind()
End Sub
End Class
Public Class Customer
Private _id As Integer
Public Property ID() As Integer
Get
Return _id
End Get
Set(ByVal value As Integer)
_id = value
End Set
End Property
Private _name As String
Public Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
End Set
End Property
End Class
About Demo3
Here a form "required" control is rendered in memory and the output used on a non form runat server page.
Demo 3
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Demo3.aspx.vb" Inherits="Demo3" %>
<!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>Demo 3</title>
</head>
<body>
<h1>Render form runat server-controls without form</h1>
<asp:Literal ID="litAGridComeTrue" runat="server" />
</body>
</html>
Imports System.IO
Partial Class Demo3
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim customers = New List(Of Customer)
customers.Add(New Customer() With {.ID = 42, .Name = "Alfred Futterkiste"})
customers.Add(New Customer() With {.ID = 101, .Name = "Tomas Edwards"})
Dim g = New GridView
g.DataSource = customers
g.DataBind()
Dim sb = New StringBuilder()
Dim sw = New StringWriter(sb)
Dim htw = New HtmlTextWriter(sw)
g.RenderControl(htw)
litAGridComeTrue.Text = sb.ToString
End Sub
End Class
Finally
Hope you liked the demos, and that it removes the misconception about asp.net "required" form runat server.
// code on!
29ad0486-4b18-40bc-b6bd-1ef2c3a16520|3|2.3
ASP.NET
form, runat="server"