Saturday, February 20, 2010

Highlight button during Asynchronous PostBack

If you don’t want to use UpdateProgress during Asynchronous Postback from UpdatePanel ,There is an idea to highlight the button that fire the Asynchronous inside UpdatePanel.

To start with this approach you must be familiar with PageRequestManager class and it's events , PageRequestManager registered by ScriptManager. With PageRequestManager you can manages partial-page rendering in the browser.
On other hand you can’t access PageRequestManager event’s directly, just you can access it through getInstance method.

The most popular events, as well I use it in my example here are beginRequest and endRequest events.

beginRequest:Raised before the processing of an asynchronous postback starts.

endRequest: Raised after an asynchronous postback is finished and control has been returned to the browser.

Now lets take a look to the example:

>html xmlns="http://www.w3.org/1999/xhtml">
>head runat="server">
>title> check it >/title>
>/head>
>body>
>form id="form1" runat="server">
>div>
>asp:ScriptManager ID="sm1" runat="server" />
>script language="javascript" type="text/javascript">
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(update_begin);
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(update_end);
var btn = null;
var Counter = 0;
var timer;

function MyTimer() {
Counter++;
if (Counter % 2 == 0)
btn.style.background = "#dddddd";
else
btn.style.background = "#eeeeee";
timer = window.setTimeout("MyTimer()", 500);
}

function ClearTimer() {
window.clearTimeout(timer);
Counter = -1;
btn.style.background = "#dddddd";
}

function update_begin(sender, args) {
btn = args.get_postBackElement();
MyTimer();
}

function update_end() {
ClearTimer();
}
>/script>

>asp:UpdatePanel ID="UpdatePanel1" runat="server">
>ContentTemplate>
>asp:Button ID="btnSubmit1" runat="server" Text="Submit 1" BackColor="#dddddd"
OnClick="btnSubmit1_Click" />
>asp:Button ID="btnSubmit2" runat="server" Text="Submit 2" BackColor="#dddddd"
OnClick="btnSubmit2_Click" />
>br />
>asp:Label ID="lblMessage" runat="server" Text="">
>/ContentTemplate>
>/asp:UpdatePanel>
>/div>
>/form>
>/body>
>/html>

In code behind :

protected void btnSubmit1_Click(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(2400);
lblMessage.Text = "You Press button 1";
}
protected void btnSubmit2_Click(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(3000);
lblMessage.Text = "You Press button 2";
}

In the previous example we catch which Element caused the Asynchronous PostBack by args.get_postBackElement(), In this way you can get the Control ID throw args.get_postBackElement().id. And you can catch if the control which cased the Asynchronous PostBack not a button, in case your UpdatePanel contain many controls which cause Asynchronous PostBack.

On the other hand you can use your own style to highlight your controls.

The last note here that I add System.Threading.Thread.Sleep(3000); to the Click handler, which artificially creates a three-second delay and then displays the button Highlighted.

Sunday, February 7, 2010

ASP.NET SECURITY: AUTHENTICATION AND AUTHORIZATION

ASP.NET gives developers very flexible and powerful capabilities in to secure to make decisions considering user actions.To apply settings we want, we can edit web.config, machine.config, IIS.Besides this settings there are great classes and namespaces in .NET ( we will use generally system.web.security ).Let's start with element in web.config. (Authentication is the process that determines the identity of a user, in other words asking user his/her credentials.Authorization,on the other hand, after validating credential, giving the user access to any specific part of the application)

>authentication mode="Forms"> //possible values are "Windows|Forms|Passport|Name

>/authentication>
90% we use authentication mode "Forms" so no need to focus on other types.By using >authorization> we define accession rules for specific folders or pages or website as a whole.

>authorization>

>deny users="*"/>

>allow roles="administrator"/>

>/authorization>

This setting first of all denies all users (*) then gives the access right to the role administrator.If we place this xml in web.config on the root of the application then it uses these settings for whole website.But in specific folders it is applied only to that folder. ie in our example, it seems that this code is for admin directory ( it gives access rights just for administrator(s).) We have deny and allow tags and users and roles attributes.For our need we can use them appropriate combination.And an example of how to use system.web.security and its basic functionalities:

using System.Web.Security;
protected void LoginButton_Click(object sender, EventArgs e)
{
if (Membership.ValidateUser(TextBox1.Text, TextBox2.Text)) //this method takes two arguments username,password
{
FormsAuthentication.RedirectFromLoginPage(TextBox1.Text, true); //go to page which was intended
//before redirected to loginpage
}
else
FormsAuthentication.RedirectToLoginPage(); //otherwise go to loginpage again
}
}

ADO.NET HIERARCHY

Whether we use ADO.NET or not generally we don't know about hierarcy of ADO.NET namespaces and classes. Therefore, I want to write its general hierarcy:

ADO.NET NAMESPACES

* System.Data
* System.Data.Common
* System.Data.SqlClient

System.Data: The core of ADO.NET. Tables, Rows, Columns and DataSet are all tools that are in System.Data. This namespace implements IDbCommand, IDbConnection, IDbDataAdapter interfaces.

System.Data.Common: This namespace is generally for custom data providers because it includes base classes of all providers in ASP.NET. For example if you want to write your own SQL provider, then you should use System.Data.Common.

System.Data.SqlClient: Data Provider for SQL. SqlCommand,SqlConnection etc. are in this class.

Now let's group ADO.NET classes considering their base features.

* Classes don't need live connection to database
* Classes do need live connection to database
* Base classes for Data Providers
* and Data Providers

Classes don't need live connection to database: Their most important and basic future is to recreate tables (with its rows, columns, functional dependencies and all its futures) in memory and manipulate them. When needed they send this tables to client side. These classes includes DataSets, DataTables.

Classes do need live connection to database: Like DataReader class, gets the actual form of database and sends it to the client. If there is an update on the server side it should be resent. To do so, it requires live connection.

Base classes for Data Providers : These classes are in System.Data.Common and are base classes for all Data Providers. (including our own custom providers)

DataProvider classes: For each Data Provider, we have a unique DataProvider class. We do all operation related to a specific data source by its own DataProvider. Each and every Data Provider has its own DataConnection, Command, Adapter and Reader objects.

Let's examine a portion of a data access layer class. (This is a general ADO.NET example. In subsequent entries, I'll give more specific examples)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Configuration;
using System.Data.SqlClient; //This is for MSSQL operations.

public static void Insert_Customers(Guid? userID, string name, string surname, string tel_no)
{
SqlConnection conn = null; //for database connection
SqlCommand cmd = null;
// with this object we send necessary commands (sql queries)
// to database
SqlTransaction trans = null; //SqlTransaction is used for insert and delete
//when there is an exception, we can undo our operations
//with this object
try
{
conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ImaletConnectionString"].ConnectionString);
conn.Open();
trans = conn.BeginTransaction();
cmd = new SqlCommand("Insert_Customer",conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Transaction = trans;
cmd.Parameters.Add("@UserID", SqlDbType.UniqueIdentifier);
//add sql parameters with the same name in sql queries
cmd.Parameters.Add("@Name", SqlDbType.NVarChar, 20);
cmd.Parameters.Add("@Surname", SqlDbType.NVarChar, 20);
cmd.Parameters.Add("@Tel_No", SqlDbType.NVarChar, 20);
cmd.Parameters[1].Value = name;
cmd.Parameters[2].Value = surname;
cmd.Parameters[3].Value = tel_no;
cmd.ExecuteNonQuery();
trans.Commit();
}
catch (Exception pr)
{
if (trans != null)
trans.Rollback();
//if there is an exception undo current operation
throw new Exception();
}
finally
{
if (conn != null)
conn.Close();
// with Dispose() we prompt C# compiler to delete our objects
cmd.Dispose();
trans.Dispose();
conn.Dispose();
}
}

NET IO - 1 ( Creating and Deleting Files and Directories and Listing subfiles and subdirectories )

There are advanced classes in .NET for IO processing. Even though we have some classes that allow us to carry out low level IO operations, we can usually do our work with several static methods. Now let's see how a directory and a file is created, deleted and how directory hierarchy in a disk volume or in a directory can be displayed in tree view. Although IO operations are same in all .NET projects, to make easier our article I use ASP.NET. Hence you can easily copy and paste code below in, for example, WPF. Classes, we will use, are:
· DriveInfo
· DirectoryInfo
· FileInfo
· Directory
· File
To create a directory or file
Directory and File classes in System.IO namespace allow us to create and delete directories or files:

Directory.Create(@"C:\exampleDirectory");
Directory.Delete(@"C:\exampleDirectory");
If we want to work on files and directories in current project folder,
Directory.Create(@"Server.MapPath("exampleDirectory"));
Directory.Delete(@"Server.MapPath("exampleDirectory"));
we can use. When operating on files, use File class:
File.Create(@"C:\exampleFile.doc")
File.Delete(@"C:\exampleFile.doc")
or
File.Create(@"Server.MapPath("exampleFile"));
File.Delete(@"Server.MapPath("exampleFile"));
Now let's work on displaying directory and file hierarchy in treeView like "windows explorer" style. We will use these classes:
· System.IO.DriveInfo //allows us to access the name, available space, total space etc. of a disk volume
· System.IO.DirectoryInfo //allows us to access the name, available space, total space etc. of directory
Create a new site, add TreeView and wrote below code in Page_Load event:
rotected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
System.IO.DriveInfo drive = new System.IO.DriveInfo(@"D:\");
//work on local disk D
TreeNode node = new TreeNode();
//we create TreeNode's dinamically

node.Value = drive.Name;
TreeView1.Nodes.Add(node);
//add local disk D to main node

loadDirectories (node, drive.Name);//in this recursive method,
// we pass name and full address of the local disk
// as parameters
}
}

private void loadDirectories(TreeNode parent, string path)
{
System.IO.DirectoryInfo directory = new System.IO.DirectoryInfo(path);
//now we don't work on drives but directories

try
{
//with GetDirectories(), we get all sub directories
foreach (System.IO.DirectoryInfo d in directory.GetDirectories())
{
TreeNode node = new TreeNode(d.Name, d.FullName);

parent.ChildNodes.Add(node);

//call the same method (call "loadDirectories()" recursively )
loadDirectories(node, d.FullName);
}
}
catch (System.UnauthorizedAccessException e)
{
parent.Text += "(acces forbiddeni)";
}

catch (System.IO.IOException e)
{
parent.Text += "(unknown error hata: " + e.Message + ")";
}
}
We displayed just content of volume D by writing ”System.IO.DriveInfo drive = new System.IO.DriveInfo(@"D:\");". If we wanted to display all files and directories in computer hard disk, we would write:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
foreach (System.IO.DriveInfo drive in System.IO.DriveInfo.GetDrives())
//to work on all volumes
{
TreeNode node = new TreeNode();
node.Value = drive.Name;

if (drive.IsReady)
{
node.Text = drive.Name;
loadDirectories(node, drive.Name);
}

TreeView1.Nodes.Add(node);
}
}
}
The code below takes several minutes. As you can estimate, our recursive method "loadDirectories()" needs many IO operations.

Now add a GridView to the project. We want to select a file from the TreeView we just created, and see alll subfiles and subdirectories with their name, space, last access time etc. Select SelectedNodeChanged event in "Properties Window" after clicking on TreeView and write the code below.
protected void TreeView1_SelectedNodeChanged(object sender, EventArgs e)
{
DirectoryInfo directory = new DirectoryInfo(TreeView1.SelectedNode.Value);

GridView1.DataSource = directory.GetFiles();
GridView1.DataBind();
}
We learned how to create and delete files and directories and displaying all subdirectories and files in a disk, hierarchically in a TreeView.

NEW FEATURES COME WITH ASP.NET 4.0

Like ASP.NET 3.5, ASP.NET 4.0 comes with many new features. In Mix09 there were several sessions, I haven't yet written about, about new features ASP.NET will make available in version 4.0 We'll see them but to show you the path ASP.NET has pursuit, first, which improvements ASP.NET 3.5 made:
  1. Microsoft Entity Framework
  2. ADO.NET Data Services
  3. Dynamic Data
  4. Microsoft Ajax Improvements
--Browser History
--Script Combining

Now new features of ASP.NET 4.0 in its all sub-framework:

Web Forms:.net hierachy
  • .. tags. This is important because almost all developers use
    ..
    tags with .css files to control the layout of their pages.

  • ..... Although clearly defining the layout sometimes can be very useful event crucial, in many situations developers use ListView for simple and easy situations and don't need it.

  • ViewState is disabled default. ViewState is a major improvement of ASP.NET in web technologies. However many developers use it in situations that actually don't require ViewState and this results in waste of bandwidth (in big web pages, ViewState can be very big in terms of amount) So we have now for each ASP.NET control and also for Page ( Page is also a control ), "ViewStateMode=enabled,disabled,inherit" so we have more control over it.

  • More control on Client IDs. ASP.NET has produce Client IDs for html output sent to the client considering layout and containers of the specific controls. This is useful because we can't control all the ids of all controls (especially for controls in data binding containers) However when we try to work on these controls, whose name is not known by us, with JavaScript problems start to arise. For example, when we refer to a control like "document.getElementByID(controlID)" we can't do anything. ASP.NET 4.0 solves this problem with (control.clientIdMode -->> legacy,static,predictable,inherit(default)). ( Static means "use the id I gave. I am responsible all errors) (Predictable means "give an id considering containers but in a more clear way)

  • Description and Keyword attributes for @Page for better search engine optimization.

  • Enhancements in web standards (xhtml standarts,accessibility standarts section508,wcag,aria) and checking them in VS2010.

  • A new ASP.NET control, QueryExtender, makes easy to query on entities that implements IQueriable

  • In ASP.NET 4.0 developers will be able to write their own custom cache providers.

  • Session state compression (out-of-proc) with GZip.
ASP.NET Ajax 4.0
  • New data binding features on client side by using templates like ASP.NET databinding controls.

  • jquery comes as part of the visual studio 2010

  • More enhanced Ajax Control Toolkit (there is also client side libraries)
ASP.NET MVC
  • Comes as a separate, stand-alone framework
ASP.NET Dynamic Data
  • New controls and more control for developer

Taking Snapshots in ASP.NET

Taking snapshots of web pages is used by many applications, for example Wordpress shows a small snapshot image of the page that a link directs to. In this post, I'll show how can we get snapshot image of a web page by using a small program, an .exe executable. Hence, it is the executable that creates the image actually and our asp.net page will make use of that .exe. First create a website, add a textbox and a button like below:



Define a class level string imageName code button's click event:

  1. public partial class _Default : System.Web.UI.Page
  2. {
  3. string imageName = "shot.png";

  4. protected void Button1_Click(object sender, EventArgs e)
  5. {
  6. string path = this.GetImage(TextBox1.Text, imageName, Request.PhysicalApplicationPath , 200, 100);

  7. Response.Redirect("~/Default2.aspx?path=" + path);
  8. }

Click event above uses GetImage() method, we will talk about soon, and assigns the path of the image to the QueryString of Default2.aspx, the page responsible for displaying snapshot image.

  1. public string GetImage(string url, string name, string rootDir, int width, int height)
  2. {
  3. string fName = rootDir + "\\" + imageName;
  4. Shot(url, rootDir);
  5. System.Drawing.Image snapshotImage = System.Drawing.Image.FromFile(fName);

  6. fName = rootDir + "\\" + "snapshots" + "\\" + name + ".png";
  7. if (File.Exists(fName))
  8. File.Delete(fName);
  9. snapshotImage .Save(fName, ImageFormat.Png);
  10. return name;
  11. }

The GetImage() method, uses Shot() by assigning relative path of the image and root directory. After invoking Shot() method, it gets the image file that Shot() got and saved.

  1. private void Shot(string url, string rootDir)
  2. {
  3. try
  4. {
  5. Process p = new Process();
  6. p.StartInfo.FileName = rootDir + "IECapt.exe";
  7. p.StartInfo.Arguments = String.Format("\"{0}\" \"{1}\"", url, rootDir + "\\" + imageName);
  8. p.StartInfo.UseShellExecute = false;
  9. p.StartInfo.CreateNoWindow = false;
  10. p.Start();
  11. p.WaitForExit();
  12. p.Dispose();

  13. Label1.Text = "Success :) !!!!!";
  14. }
  15. catch (Exception ex)
  16. {
  17. Label1.Text = ex.ToString();
  18. }
  19. }

This method defines a Process to start and execute a file. Then it sets up arguments (the sequence of them are same with the ones if you would use this .exe in command line).

If you want to add the feature of Wordpress (showing snapshots when hovering on links) you can implement the code above as a Web Service. Then using that service via JavaScript, or with JQuery library to make it more easy, you can get that functionality.

Note: IECapt.exe can be downloaded from here
Note: Because IECapt.exe takes snapshot of the whole page with very big resolution you should scale it in many scenarios.

Our simple Default2.aspx just has a Image control and two lines of code in Page_Load event handler to show the image:

  1. protected void Page_Load(object sender, EventArgs e)
  2. {
  3. if (!string.IsNullOrEmpty(Request.QueryString["path"]))
  4. {
  5. Image1.ImageUrl = "~//" + Request.QueryString["path"].ToString();
  6. Response.Write(Image1.ImageUrl);
  7. }
  8. }
protected void Page_Load(object sender, EventArgs e)
{
    if (!string.IsNullOrEmpty(Request.QueryString["path"]))
    {
        Image1.ImageUrl = "~//" + Request.QueryString["path"].ToString();
        Response.Write(Image1.ImageUrl);
    }
}