Thursday, April 30, 2009

Merge DataGrid Header



Introduction

This article describes the technique to merge the header of a DataGrid by redirecting the Render method of the DataGrid items.

Background

I found many times the need to merge the header of a DataGrid. So, when I was having spare time, I tried to find a way to do it, and here it is. I know that if you need to merge headers, you can use the Repeater control instead. But if you are fond of DataGrid (just like me), or may be you already used DataGrid, then this article is for you.

Using the code

When rendered, a DataGrid will be converted into a HTML Table element and the header will be the first HTML TR element. So, to have a merged header, we need to have control in the rendering of the header. This can be achieved by redirecting the Render method of the DataGrid header using the SetRenderMethodDelegate of the DataGrid header on ItemCreated event, like this


private void Datagrid1_ItemCreated(object sender,
System.Web.UI.WebControls.DataGridItemEventArgs e)
{
//*** Examine if the item created is the header item

ListItemType lit = e.Item.ItemType;
if(ListItemType.Header == lit)
{
//*** Redirect the default header rendering method to our own method

e.Item.SetRenderMethodDelegate(new RenderMethod(NewRenderMethod));
}
}

And here is our own Render method:

/// <summary>

/// This is our custom render method for the grid header item

/// </summary>

/// <param name="writer"></param>

/// <param name="ctl"></param>

private void NewRenderMethod(HtmlTextWriter writer, Control ctl)
{
//*** We don't need to write the tag

// because it's already written by the writer

// so now we write the Name column

writer.Write("Name\n");

//*** The Age column must have the rowspan attribute

// and must be rendered inside the

// first row so it will centered vertically

TableCell cell = (TableCell)ctl.Controls[ctl.Controls.Count-1];
cell.Attributes.Add("rowspan","2");
cell.RenderControl(writer);

//*** Now we close the first row, so we can insert the second one

writer.Write("\n");

//*** Add the style attributes that was defined in design time

// to our second row so they both will have the same appearance

DataGrid1.HeaderStyle.AddAttributesToRender(writer);

//*** Insert the second row

writer.RenderBeginTag("TR");

//*** Render all the cells that was defined

// in design time, except the last one

// because we already rendered it above

for(int i=0; i<= ctl.Controls.Count-2; i++)
{
ctl.Controls[i].RenderControl(writer);
}

//*** We don't need to write the close tag

// because the writer will do that for us

// and so we're done :)

}

I have created a decorator class to decorate a DataGrid (ASPNetDatagridDecorator class) to have a merge header, and all you need to do is define the header cell like this (you can use the auto format feature, but doesn't work for all):


private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here

if(!this.IsPostBack)
{
TableCell cell = null;
DataGrid1.DataSource = GetData();
DataGrid1.DataBind();

m_add.DatagridToDecorate = Datagrid2;
ArrayList header = new ArrayList();

// cell = new TableCell();

// cell.Text = "Code";

// cell.RowSpan = 2;

// cell.HorizontalAlign = HorizontalAlign.Center;

// header.Add(cell);


cell = new TableCell();
cell.Text = "Name";
cell.RowSpan = 2;
cell.HorizontalAlign = HorizontalAlign.Center;
header.Add(cell);

cell = new TableCell();
cell.Text = "Name";
cell.ColumnSpan = 3;
cell.HorizontalAlign = HorizontalAlign.Center;
header.Add(cell);

cell = new TableCell();
cell.Text = "Age";
cell.RowSpan = 2;
cell.HorizontalAlign = HorizontalAlign.Center;
header.Add(cell);

cell = new TableCell();
cell.Text = "School";
cell.ColumnSpan = 3;
cell.HorizontalAlign = HorizontalAlign.Center;
header.Add(cell);

cell = new TableCell();
cell.Text = "Religion";
cell.RowSpan = 2;
cell.HorizontalAlign = HorizontalAlign.Center;
header.Add(cell);

m_add.AddMergeHeader(header);

Datagrid2.DataSource = GetData();
Datagrid2.DataBind();

}

}

By Courtesy of Codeproject

Merge Header - Gridview/DataGrid


Introduction

During development with GridView, we might come across many situations in which we need to extend GridView for our requirements. For example, we need to have a separate header other than the header provided by GridView. In that case we need to add new GridView item of header type. In this article we will see how merge two or more columns.

Requirement

In this example we have simple GridView which is fetching data from xml file and displaying that in the table structure using GridView. In this GridView, we need to add two additional Header with text "Department" and "Employee". First department column should occupy first two columns and Employee column should occupy rest three columns.

Problem

I found in the internet that there are many ways to do this, but we might end up with column alignment problems.

Solution

Here we are going to see one of the best method to do that. To have additional header, we need to add one GridViewRow of header type to GridView inside OnRowCreated event method. The code snippet for doing this,

protected void GridView_Merge_Header_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
//Build custom header.
GridView oGridView = (GridView)sender;
GridViewRow oGridViewRow = new GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Insert);
TableCell oTableCell = new TableCell();

//Add Department
oTableCell.Text = "Department";
oTableCell.ColumnSpan = 2;
oGridViewRow.Cells.Add(oTableCell);

//Add Employee
oTableCell = new TableCell();
oTableCell.Text = "Employee";
oTableCell.ColumnSpan = 3;
oGridViewRow.Cells.Add(oTableCell);
oGridView.Controls[0].Controls.AddAt(0, oGridViewRow);
}
}

By Courtesy of Codeproject

Wednesday, April 29, 2009

Convert HTML To Plain Text By RegularExpressions

// Return Plain Text
private string ConvertHtmlToPlainText(string htmlText)
{
return System.Text.RegularExpressions.Regex.Replace(htmlText, "<[^>]*>", string.Empty);
}

Tuesday, April 28, 2009

How to Encrypt Query String Parameters in ASP.NET

There are some circumstances when you need to encrypt query string parameters in your URLs in order to secure your web applications. There are many reasons and many cases but as one of my recent experiences in Waegis a user activation requires such a system. The reason is to prevent anyone to use other’s plain email address to activate his or her account without receiving the activation mail!

Of course, there are some solutions and I’m not using this solution on Waegis (I replaced the solution with a simpler and secure mathematical algorithm that I inspired myself) but the incoming solution is the most common way to encrypt your query string parameters.

The basic idea of this method is using DES cryptography system to encrypt query string parameters on one side and then decrypting it on the other side. But the key point about this method is that DES algorithm is a symmetric algorithm that requires two keys. How do you want to work around this?

You may want to pass your sector vector or initialization vector as a secondary parameter in query string and keep the other key private but this is an insecure solution because having those two parameters, your key is predictable so your algorithm is breakable!

But what’s the solution? The solution is to define both keys on your side and use them to encrypt your text and only pass the encrypted text to query string then retrieve the text and decrypt it with these keys.

Having this background, the implementation is easy and straightforward and contains nothing but some .NET cryptography code.

The main part of this workflow is building a simple cryptographic class that manages the encryption and decryption of string values with your keys. Below code represents the class that you can port for your application. There are two fields that define and hold sector vector and initialization vector. You need to define them once and add them to your application. The rest of the code should be familiar to you because it’s just a set of regular .NET cryptography operations.

using System;

using System.Data;

using System.Configuration;

using System.Linq;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Linq;

using System.Text;

using System.Security.Cryptography;

using System.IO;

namespace QueryStringEncryption

{

public class Cryptography

{

#region Fields

private static byte[] key = { };

private static byte[] IV = { 38, 55, 206, 48, 28, 64, 20, 16 };

private static string stringKey = "!5663a#KN";

#endregion

#region Public Methods

public static string Encrypt(string text)

{

try

{

key = Encoding.UTF8.GetBytes(stringKey.Substring(0, 8));

DESCryptoServiceProvider des = new DESCryptoServiceProvider();

Byte[] byteArray = Encoding.UTF8.GetBytes(text);

MemoryStream memoryStream = new MemoryStream();

CryptoStream cryptoStream = new CryptoStream(memoryStream,

des.CreateEncryptor(key, IV), CryptoStreamMode.Write);

cryptoStream.Write(byteArray, 0, byteArray.Length);

cryptoStream.FlushFinalBlock();

return Convert.ToBase64String(memoryStream.ToArray());

}

catch (Exception ex)

{

// Handle Exception Here

}

return string.Empty;

}

public static string Decrypt(string text)

{

try

{

key = Encoding.UTF8.GetBytes(stringKey.Substring(0, 8));

DESCryptoServiceProvider des = new DESCryptoServiceProvider();

Byte[] byteArray = Convert.FromBase64String(text);

MemoryStream memoryStream = new MemoryStream();

CryptoStream cryptoStream = new CryptoStream(memoryStream,

des.CreateDecryptor(key, IV), CryptoStreamMode.Write);

cryptoStream.Write(byteArray, 0, byteArray.Length);

cryptoStream.FlushFinalBlock();

return Encoding.UTF8.GetString(memoryStream.ToArray());

}

catch (Exception ex)

{

// Handle Exception Here

}

return string.Empty;

}

#endregion

}

}

Now the rest of this post exemplify how to use this Cryptography class. I implement a UserActivation class that manages the activation process. It generates activation links by getting a username and also activates a user by getting the encrypted username key. The final class is shows below.

using System;

using System.Data;

using System.Configuration;

using System.Linq;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Linq;

using System.IO;

namespace QueryStringEncryption

{

public static class UserActivation

{

#region Public Methods

public static void ActivateUser(string key)

{

string username = Cryptography.Decrypt(key);

// TODO: Activation Login

}

public static string GetActivationLink(string username)

{

string key = Cryptography.Encrypt(username);

StringWriter writer = new StringWriter();

HttpContext.Current.Server.UrlEncode(key, writer);

return string.Format("/default.aspx?key={0}", writer.ToString());

}

#endregion

}

}

Here the important point is to not forget to UrlEncrypt the encrypted key because usually it contains some characters that will be ignored by ASP.NET and can cause exceptions on decryption.

I finally wrap up this example by applying it in a simple page. This page generates an activation link when there is no query string parameter and it also decrypts the key parameter when it is provided. In real world scenarios you can use this decrypted username to activate the user’s account.

using System;

using System.Collections;

using System.Configuration;

using System.Data;

using System.Linq;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Linq;

namespace QueryStringEncryption

{

public partial class _Default : System.Web.UI.Page

{

protected void Page_Load(object sender, EventArgs e)

{

if (string.IsNullOrEmpty(Request["key"]))

Response.Write(UserActivation.GetActivationLink("keyvannayyeri"));

else

Response.Write(Cryptography.Decrypt(Request["key"]));

}

}

}

Encrypting QueryStrings with .NET

Encrypting QueryStrings with .NET

Once upon a time in the tech world, obscurity was security - this being most true in the early years of the industry, when there were gaping holes in privacy policies and confidential client information was bandied about from site to site without a care as to who actually could read the information.

With the new Cryptography classes in .NET, there's absolutely no excuse for not hiding even the most innocuous user data. If you ever need to 'piggy-back' information from one web page to another, whether it is within a POST or a GET parameter, you're passing clear information that anyone can sniff - and that's a bad thing.

If you're not going to use a session variable for storing end user information, you're most likely going to keep some sort of State by passing the information to a cookie or push it around with GET/POST parameters. If you're passing around any sort of ID or user information like their name, it's better to err on the side of caution and encrypt the information.

GET Vs. POST

A POST parameter keeps the information out of the URL, but it can still be sniffed quite easily as it passes in clear text across your network or the Internet. Using POST will keep the mere curious at bay, as the information is not contained in the URL - but this will not stop someone determined to snag out your data.

A QueryString parameter passes information within the site's URL. Why would you even use a QueryString? Well, maybe you need to let your user bookmark a particular page, or maybe you have to refer directly to a page in a URL via a link - you can't do either if you're using POST. A QueryString puts data in the URL for the entire world to see, so if you don't know if the end user is malicious, I'd think hard about using a QueryString for anything but site-related information.

Be smart and encrypt any and all data you're moving around from page to page, especially if that information could be used maliciously. You may trust your users, but you still need that extra level of security that clear text GET/POST data doesn't provide.Imagine this scenario - you've been passing the customer's ID in the database around in a QueryString, in a URL that looks like this:

http://yoursite.com?cust_id=29

You know what a user is going to do? Switch that 29 to a 30 or 12 or some other number, and if you're not checking for invalid requests, you'll be dishing up some other customer's data.

Enter Encryption

What I was looking for was a quick way to encrypt and decrypt parts of a QueryString - it had to be on the fly, quick and dirty.

I chose Base64 because it wouldn't throw bizarre characters in my QueryString that I couldn't pass around… Little did I know that I'd hit a snag while passing around my encrypted QueryString - Apparently, the Request.QueryString object interprets the '+' sign as a space! So, with a quick Replace function slapped on my decrypt string, no harm, no foul.

Symmetric Key

The whole trick to this working is that the QueryString is encrypted and decrypted with the same private key. This is the secret key - if anyone gets a hold of your key, they can decrypt the data themselves, so keep it a secret!

We're going to use a hard-to-crack 8 byte key, !#$a54?3, to keep parts of our QueryString secret.

Let's Walk through the C# portion of the code:

Notice our two functions that abstract the dirty work that our Encryption64 class. The first, encryptQueryString, is used to encrypt the value of a QueryString. The second, decryptQueryString, is used to decrypt the value of an encrypted QueryString.

public string encryptQueryString(string strQueryString) {
ExtractAndSerialize.Encryption64 oES =

new ExtractAndSerialize.Encryption64();
return oES.Encrypt(strQueryString,"!#$a54?3");

}

public string decryptQueryString(string strQueryString) {
ExtractAndSerialize.Encryption64 oES =

new ExtractAndSerialize.Encryption64();
return oES.Decrypt(strQueryString,"!#$a54?3");

}

If we wanted to encrypt our QueryString on our first page, we could do something like this:

string strValues = "search term";

string strURL = "http://yoursite.com?search="
+ encryptQueryString(strValues);
Response.Redirect(strURL);

Inside our code-behind in our second page, we pass the contents our QueryString to a variable named strScramble. After that, we replace the '+' signs that our wonderful Request.QueryString has replaced with a space. We pass that string into our function, decryptQueryString, and retrieve the decrypted string.

string strScramble =  Request.QueryString["search"];

string strdeCrypt = decryptQueryString(
strScramble.Replace(" ", "+"));

Now we've decrypted the value of the QueryString, 'search', and we can do whatever we want with it. The end user is going to see a URL that looks like:

http://yoursite.com?search=da00992Lo39+343dw

They'll never be able guess what's going on in your QueryString, and if they try to fool around with it, there's no way to crack the code without knowing the Symmetric key.

VB.NET

Imports System
Imports System.IO
Imports System.Xml
Imports System.Text
Imports System.Security.Cryptography

Public Class Encryption64

Private key() As Byte = {}
Private IV() As Byte = {&H12, &H34, &H56, &H78, &H90, &HAB, &HCD, &HEF}

Public Function Decrypt(ByVal stringToDecrypt As String, _
ByVal sEncryptionKey As String) As String

Dim inputByteArray(stringToDecrypt.Length) As Byte
Try
key = System.Text.Encoding.UTF8.GetBytes(Left(sEncryptionKey, 8))

Dim des As New DESCryptoServiceProvider()
inputByteArray = Convert.FromBase64String(stringToDecrypt)
Dim ms As New MemoryStream()

Dim cs As New CryptoStream(ms, des.CreateDecryptor(key, IV), _

CryptoStreamMode.Write)
cs.Write(inputByteArray, 0, inputByteArray.Length)

cs.FlushFinalBlock()
Dim encoding As System.Text.Encoding = System.Text.Encoding.UTF8

Return encoding.GetString(ms.ToArray())
Catch e As Exception
Return e.Message

End Try
End Function

Public Function Encrypt(ByVal stringToEncrypt As String, _

ByVal SEncryptionKey As String) As String
Try
key = System.Text.Encoding.UTF8.GetBytes(Left(SEncryptionKey, 8))

Dim des As New DESCryptoServiceProvider()
Dim inputByteArray() As Byte = Encoding.UTF8.GetBytes( _

stringToEncrypt)
Dim ms As New MemoryStream()
Dim cs As New CryptoStream(ms, des.CreateEncryptor(key, IV), _

CryptoStreamMode.Write)
cs.Write(inputByteArray, 0, inputByteArray.Length)

cs.FlushFinalBlock()
Return Convert.ToBase64String(ms.ToArray())
Catch e As Exception

Return e.Message
End Try
End Function

End Class

Thursday, April 9, 2009

aspnet_wp.exe could not be launched because the username and/or password supplied in the processModel section of the config file are invalid.

By default ASP.NET runs the ASP.NET worker process using a
non-adminitrative windows account called "ASPNET". This restricts what
an ASP.NET application can do on a machine -- and requires
administrators to explicitly grant security permissions. =20

However, on Windows Domain Controller machines (this includes the
Windows Small Business Server product) the ASPNET account cannot be used
-- since non-administrative local accounts cannot be created and used
(the security policy of a Windows Domain Controller machine prevents
this). =20

If you attempt to use the default ASPNET account when running an ASP.NET
page on a Windows Domain Controller, the worker process will fail to
start -- most likely with an error message similar to the one below:=20

"aspnet_wp.exe could not be launched because the username and/or
password supplied in the processModel section of the config file are
invalid"

To fix this, it is necessary to configure ASP.NET to instead use the
LocalSystem account after setup. This is done by modifying the
tag within the Machine.Config configuration file
installed in the below location:

c:\Windows\Microsoft.Net\Framework\V1.0.3705\Config\Machine.Config

By default you will find that the configuration tag has a
"userName" attribute set to the value: "MACHINE". Changing this value
to "SYSTEM" will cause ASP.NET to instead use the LocalSystem account
when executing. This account *does* have permission to run on Windows
Domain Controllers.

After making the change to the Machine.Config XML file, save it, and
then restart IIS (iisreset). ASP.NET will then be using the LocalSystem
account to run its worker process, and ASP.NET will function fine on
domain controllers.


you cann add also any other admin account

Monday, April 6, 2009

Records using a Stored Procedure Paging

CREATE PROCEDURE dbo.proc_Paging_CTE
(
@Page int,
@RecsPerPage int
)
AS
-- The number of rows affected by the different commands
-- does not interest the application, so turn NOCOUNT ON

SET NOCOUNT ON


-- Determine the first record and last record

DECLARE @FirstRec int, @LastRec int

SELECT @FirstRec = (@Page - 1) * @RecsPerPage
SELECT @LastRec = (@Page * @RecsPerPage + 1);

WITH TempResult as
(
SELECT ROW_NUMBER() OVER(ORDER BY Popularity DESC) as RowNum,
s.Title, m.Publisher, s.AuthorNames, l.LanguageName,
m.FirstLine, m.CreationDate, m.PublishingDate, m.Popularity
FROM dbo.Articles m
INNER JOIN dbo.Content s
ON s.ArticleID = m.ID
LEFT OUTER JOIN dbo.Languages l
ON l.ID = m.LanguageID
)
SELECT top (@LastRec-1) *
FROM TempResult
WHERE RowNum > @FirstRec
AND RowNum < @LastRec



-- Turn NOCOUNT back OFF
SET NOCOUNT OFF
GO

Convert Object Array to DataTable

using System;
using System.Reflection;
using System.Data;

namespace BusinessLogicLayer
{

/// <summary>
/// Business Logic to Convert Datatable
/// </summary>
public static class ConvertToDatatable
{

#region "Converting ObjectArray to Datatable"

/// <summary>
/// Returns datatable using supplied parameters.
/// </summary>
/// <param name="array">Object array for which data is to be converted into datatable.</param>
/// <returns>Datatable on the basis of supplied parameters.</returns>
public static DataTable ConvertToDataTable(Object[] array)
{

PropertyInfo[] properties = array.GetType().GetElementType().GetProperties();
DataTable dt = CreateDataTable(properties);
if (array.Length != 0)
{
foreach (object o in array)
FillData(properties, dt, o);
}
return dt;
}

/// <summary>
/// Returns datatable using supplied parameters.
/// </summary>
/// <param name="properties">Propertyinfo object for which data is to be converted into columns of datatable.</param>
/// <returns>Datatable on the basis of supplied parameters.</returns>
private static DataTable CreateDataTable(PropertyInfo[] properties)
{
DataTable dt = new DataTable();
DataColumn dc = null;
foreach (PropertyInfo pi in properties)
{
dc = new DataColumn();
dc.ColumnName = pi.Name;
//dc.DataType = pi.PropertyType;
dt.Columns.Add(dc);
}
return dt;
}

/// <summary>
/// Filling record/s to datatable using supplied parameters.
/// </summary>
/// <param name="properties">PropertyInfo Object for which data is to be fill.</param>
/// <param name="dt">Datatable object to fill record/s</param>
/// <param name="o">Object for which data is to be fill.</param>
private static void FillData(PropertyInfo[] properties, DataTable dt, Object o)
{
DataRow dr = dt.NewRow();
foreach (PropertyInfo pi in properties)
{
dr[pi.Name] = pi.GetValue(o, null);
}
dt.Rows.Add(dr);
}
#endregion
}
}

Resizing uploaded image

One of my readers asked for example about my image resizing routine. Here you can find example and also some notes about my code design solution.

Why I used streams?

First, the resizing method is thought for web applications. Second, using streams is more general solution that using file paths (you don’t want to save files to hard disc if you get them from file upload and save to database). Web application may get image files from following sources:

  • files located on web server hard disc,
  • file uploads,
  • web services,
  • BLOB field of database table.

For first two sources we can ask stream directly. For the other two we can create memory stream and write byte array with image bytes to it.

Streams are useful also for output. Output stream may be file, response output stream or memory stream by example. And you can use also other streams that you need. In the case of file stream the resized image is written to file. In the case of response output stream the resized image is written back to browser. If you use memory stream then you may convert it to byte array so you can send image to database or post to web service.

Example

Let’s see now simple example that resizes images and uses streams. We have Resize.aspx page that accepts file uploads. If image is uploaded then it resizes it to 50% and shows it to user. If error occurs then error message is printed out.


protected void Page_Load(object sender, EventArgs e)

{

    if (Request.Files.Count > 0)

    {

        ShowPreview();

        return;

    }

}

protected void ErrorMessage(string error)

{

    var outputBuilder = new StringBuilder();

    outputBuilder.Append("<html><head></head><body>");

    outputBuilder.Append("<span>");

    outputBuilder.Append(error);

    outputBuilder.Append("</span>");

    outputBuilder.Append("</body></html>");

 

    try

    {

        Response.Clear();

        Response.ContentType = "text/html";

        Response.Write(outputBuilder);

        Response.End();

    }

    catch { }

}

 

protected void ShowPreview()

{

    var file = Request.Files[0];           

    try

    {

        Response.Clear();

        Response.ContentType = file.ContentType;

        ResizeImage(0.5,file.InputStream, Response.OutputStream);

        Response.End();               

    }

    catch (ArgumentException)

    {

        ErrorMessage("Unknown image file!");

    }

    catch(ThreadAbortException)

    {

 

    }

    catch (Exception ex)

    {

        ErrorMessage("Unknown error: " + ex);

    }

}

 

private void ResizeImage(double scaleFactor, Stream fromStream, Stream toStream)

{

    var image = Image.FromStream(fromStream);

    var newWidth = (int)(image.Width * scaleFactor);

    var newHeight = (int)(image.Height * scaleFactor);

    var thumbnailBitmap = new Bitmap(newWidth, newHeight);

 

    var thumbnailGraph = Graphics.FromImage(thumbnailBitmap);

    thumbnailGraph.CompositingQuality = CompositingQuality.HighQuality;

    thumbnailGraph.SmoothingMode = SmoothingMode.HighQuality;

    thumbnailGraph.InterpolationMode = InterpolationMode.HighQualityBicubic;

 

    var imageRectangle = new Rectangle(0, 0, newWidth, newHeight);

    thumbnailGraph.DrawImage(image, imageRectangle);

 

    thumbnailBitmap.Save(toStream, image.RawFormat);

 

    thumbnailGraph.Dispose();

    thumbnailBitmap.Dispose();

    image.Dispose();

}


You can use this resizing method also in desktop applications and web services.

Using Session State in a Web Service

Usually, when you think of a Web Service, you think …make the call, get the response, and get on with the task at hand. These "one shot" calls are the norm in Web Services but there may be times when you need a little more. You may need the Web Service to remember states between calls.


As an example, I wrote a Web Service that had to perform a lengthy operation. I didn't want to lock up the client by making a synchronous call, so once the job was started, the call returned. Every few seconds, on a timer, the client would call a GetStatus function in the Web Service to get the status of the running job. When the status was retrieved, a progress bar on the client was updated. It worked well.


There is support for using Session State in Web Services but it doesn't work "out-of-the-box".


This article assumes you know how to create and call a Web Service.


First we need a Web Service. I created a basic Web Service and then modified the supplied HelloWorld function that is created by default:


using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Services;
 
namespace DemoWebService
{
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
 
    public class MyDemo : System.Web.Services.WebService
    {
        [WebMethod (EnableSession = true)]
        public string HelloWorld()
        {
            // get the Count out of Session State
            int? Count = (int?)Session["Count"];
 
            if (Count == null)
                Count = 0;
 
            // increment and store the count
            Count++;
            Session["Count"] = Count;
 
            return "Hello World - Call Number: " + Count.ToString();
        }
    }
}


Note: The key thing to do is add (EnableSession = True) to the WebMethod tag. The rest of the code simple keeps track of how many times each client has called the Web Service method.


Side Note: I am using a Nullable Type to simplify the retrieving of Count from the Session collection.


Here's the old school way: 





int Count;
 
if (Session["Count"] == null)
    Count = 0;
else
    Count = (int)Session["Count"];


Here's the new school way...Nullable Type…is better, yah? 



int? Count = (int?)Session["Count"];
 
if (Count == null)
    Count = 0;


Ok, now the client. You've built the Web Service. You've added the Web Service to the client project (right-click the project and select "Add Web Reference…"). A proxy class has been created.


In a button click event, we instantiate the proxy class, call our function and update a label. This is going to be great…it's going to be so easy…


protected void Button1_Click(object sender, EventArgs e)
{
    // instantiate the proxy and call our function
    localhost.MyDemo MyService = new localhost.MyDemo();
 
    Label1.Text = MyService.HelloWorld();
}
We click the button a few times, but instead counting, we get this: 


Hello World - Call Number: 1
Hello World - Call Number: 1
Hello World - Call Number: 1


Explanation: When an object is put into the Session collection, Asp.Net gives the caller an indentifying cookie behind the scenes…the SessionID. This is like when you check your coat at an expensive restaurant (I've heard) and you get a coat check ticket. When you go to get your coat back, you must have the ticket. So why isn't the proxy storing the SessionID as a cookie?


Key Point: The proxy generated doesn't have a CookieContainer.


Solution: Create a CookieContainer in the proxy (it already has a reference for it)


Here's the modified code:

protected void Button1_Click(object sender, EventArgs e)
{
    // instantiate the proxy 
    localhost.MyDemo MyService = new localhost.MyDemo();
 
    // create a container for the SessionID cookie
    MyService.CookieContainer = new CookieContainer();
 
    // call the Web Service function
    Label1.Text += MyService.HelloWorld() + "<br />";
}


All right, problem solved. This is great…it's going to be so easy… Fire up the web page, click the button a few times, and…

Hello World - Call Number: 1
Hello World - Call Number: 1
Hello World - Call Number: 1


@#%* Why does life have to be so hard?

Explanation: When the proxy went out of scope, it was uninstantiated and ceased to exist. The CookieContainer also ceased to exist. And our cookie, the SessionID…a.k.a. coat check ticket…was lost.


Key Point: The proxy has to remain in existence between calls to the Web Service.


Solution: Keep the proxy around. In a Windows Forms application this is easy. Make the proxy global or static…just don't put it on the stack. For a Web Application it's a bit trickier, we put the proxy into the Session collection.



protected void Button1_Click(object sender, EventArgs e)
{
    localhost.MyDemo MyService;
 
    // try to get the proxy from Session state
    MyService = Session["MyService"] as localhost.MyDemo;
 
    if (MyService == null)
    {
        // create the proxy
        MyService = new localhost.MyDemo();
 
        // create a container for the SessionID cookie
        MyService.CookieContainer = new CookieContainer();
 
        // store it in Session for next usage
        Session["MyService"] = MyService;
    }
 
    // call the Web Service function
    Label1.Text += MyService.HelloWorld() + "<br />";
}  


All right, we hope the problem is solved because this is getting tiring. Fire up the web page, click the button a few times and…


Hello World - Call Number: 1
Hello World - Call Number: 2
Hello World - Call Number: 3


Ah, the sweet bliss of working code.

C Sharp goto statement for breaking the nested loop

Two days back, while discussing
with a friend came a small interesting (programming) situation where he wanted
to stop (break) a loop which was inside another loop.



You can think of the situation as
he was first looping through all the rows in a grid view and then in the entire
column in the grid view. Now he was trying to look into the text of each cell,
and if the text matched a given value, he needed to break from both the loop and
execute the statement after the loop.



His first idea was to use a flag
which will be checked in the outer loop every time to see if the value has been
found in the inner loop. The code would be something like below.



bool flag = false;


for(int i =
0;i<grd.Rows.count;i++)
{
if(flag==true)
{ break; }

for(int j= 0;j<grd.Columns.count;j++)
{

if(grd.Rows[i][j].ToString() == “someValue”;
flag = true;

Break;
}
}


// Statement to executed after
loop.



I am sure most of us have faced
some or other situation where we had some requirement like this and the solution
provided was also similar.



The code does the work that we
want it to do, but if you look deeply it has a problem. I have to check the
value of the flag for each time there is a loop for the row and also to maintain
a tedious flag for a just breaking the loop.



The same work can be easily done
without using a flag, by using a goto statement like this.



for(int i =
0;i<grd.Rows.count;i++)
{
for(int j=
0;j<grd.Columns.count;j++)
{
if(grd.Rows[i][j].ToString()
== “someValue”;
{
goto foundcell;

}
}
foundcell:


// Statement to executed after
loop.



This way, I could break from both
(if required even more than 2 loops) the loops easily without maintaining any
flag with the help of a goto statement.



Remember the goto statement
should only be used when we have nested loops. If you have only one loop than
its best to use the break keyword to stop, break the loop.

Thursday, April 2, 2009

Four Pillars of Asp.Net

Not that long ago, there was just ASP.NET. But ASP.NET has expanded to include different approaches to development. Recently, I was chatting with Microsoft’s Scott Hunter and Steve Walther over drinks at DevConnections Orlando and Steve mentioned “the four pillars of ASP.NET.” The four pillars are the four ways you can build web sites with ASP.NET, both today and in the future. The four pillars are:

1. ASP.NET Web Forms. Until recently, this was the only pillar of ASP.NET. Everything was done using the familiar rich server-side controls that many have grown to love (and some have learned to despise which is the seed for the other three pillars).

So what’s wrong with Web Forms? Well, many developers believe that ASP.NET Web Forms are too much of a black box with a healthy-dose of black magic. There’s a price you pay for the Web Form event model and lifecycle and that price is control over the exchange of data between server and browser. Some say the Web Form model with its incessant ViewState is a pig. The Web Form model also makes it difficult to create testable applications and practice test-driven development (TDD). On the other hand, ASP.NET AJAX and ASP.NET MVC (pillars 2 and 3, respectively) come with a steep learning curve, and for many developers will take longer to develop the equivalent application. Pillar 4 (Dynamic Data), on the other hand, has limited applicability, IMO.

My opinion is that with the possible exception of Dynamic Data for the creation of simpler intranet applications, nothing in my mind beats ASP.NET Web Forms (especially when paired with the ASP.NET AJAX UpdatePanel control) for creating good, solid, and responsive applications that, while not the leanest and meanest of applications nor very testable, are easy to grok and master for the novice through advanced developer. Web forms are also the best match for the developer looking to make the move to ASP.NET from Microsoft desktop (Win Forms or WPF) development. And with each new version, Microsoft is making it easier to tame the pig (ViewState) and reduce its size: ASP.NET 2.0 introduced ControlState and ASP.NET 4.0 changes the inheritance model of ViewState so it will be easier to turn off ViewState by default and only turn it on when needed.

2. ASP.NET AJAX. This pillar came to life with the ASP.NET AJAX Extensions for ASP.NET 2.0 / Visual Studio 2005. ASP.NET AJAX is now integrated into ASP.NET and Visual Studio 2008 and consists of both a set of server-side controls as well as the AJAX client-side libraries. In regards to its existence as a “pillar,” I would argue that Microsoft is really only talking about the client-side of ASP.NET AJAX. The reason I say this is that the Upgrade Panel and other server-side AJAX controls merely extend the Web Form pillar, giving Web Form controls the ability to do asynchronous postbacks.

There are many in the hard-core ASP.NET AJAX community that believe that a true AJAX application needs to be built from the ground up without the use of Web Forms and the server-side controls. Using this approach, ASP.NET merely becomes a way to emit HTML with embedded JavaScript (and references to the Microsoft ASP.NET AJAX and JQuery libraries) that calls back to ASP.NET (or WCF) web services. When the HTML and JavaScript hit the browser, that’s when the action begins.

The promise of this approach is a much snappier user interface and a much more scalable web site. On the downside, this requires programming in a looselytyped language with a weird inheritance model, spotty support for IntelliSense, and, while improved, lousy debugger support. Another downside, the lack of smart client-side controls is likely to be remedied in the ASP.NET 4.0 timeframe. Microsoft is busy improving the client-side story, complete with client-side controls, for ASP.NET 4.0 (if you are curious, check out
http://asp.net/ajax and click on the “ASP.NET AJAX Preview on CodePlex” link for a peek at what’s coming). Regardless, I believe this will pillar will always be for a subset of ASP.NET developers who don’t shun the client-side.

3. ASP.NET MVC. This pillar is the newest to emerge from Microsoft. In fact, as of this writing, it’s only a week old, having been released at Mix09. Some ASP.NET curmudgeons would call this a throwback to the days of ASP “classic” spaghetti code, but for many others--especially the alt.net crowd and transplants from Ruby and Java--this represents the cat’s pajamas on the Microsoft web stack. (Of course, it’s amazing how quickly developers find problems in the latest programmer’s paradise--usually before its release--and I’m sure the MVC aficionados are already looking to the next release.)

The basic idea behind ASP.NET MVC is to separate out the three concerns of the MVC pattern: the model, view, and controller. The model represents the data model, the view is the user interface that presents the data and interacts with the user, and the controller is the command center that takes inputs from the view, pushes and pulls data into/from the model, and decides what to do next. By separating out these concerns (as purely as possible), you improve the ability to create unit tests for your applications and, at least on some level, improve application maintainability. If you are into test driven development, then this is the pillar to hook your horse to.

4. Dynamic Data. IMO, Dynamic Data is a misnomer. From its name, one would tend to think this is yet another data access technology from Microsoft. It is not. I would have preferred Microsoft to use the name Dynamic Application or Dynamic Application Builder. MSDN Help says, “ASP.NET Dynamic Data is a framework that lets you create data-driven ASP.NET Web applications easily.

You start with Dynamic Data by creating a database and then using either LINQ to SQL or the Entity Framework to create a model over your data. Next, create a new project or web site in Visual Studio 2008 (with SP1) using one of the Dynamic Data Web Application templates, make a fairly simple change to the web site’s Global.asax, and Visual Studio builds a dynamic ASP.NET application over your data model. The resulting site support the creation, retrieval, updating, and deletion (commonly referred to as the CRUD operations) of rows in the underlying database.

Dynamic Data uses what is termed dynamic scaffolding to construct your application. This means if you change your data model, the application will be instantly updated: there’s no code that needs to be re-generated.

Dynamic Data is customizable. Thus, if you don’t like how Dynamic Data presents a datatype or a particular field, or want to change how it performs validation of a field, you can change the templates behind these. You can also change the master page used as well as a number of other details.

Kudos to Microsoft for Dynamic Data--even though I hate the name. Just realize that this pillar, unlike the other three, is only applicable to a subset of ASP.NET applications that fit in well with the Dynamic Data approach to applications: applications, which are primarily data-centric, intranet-based applications. That said I could see many places where I might use Dynamic Data, though I am still trying to work through the security implications of opening up the database for pretty much unrestricted reading and writing of database tables.

(For those who would like to see an MVC version of Dynamic Data: I’d expect to see such a beast come down the pike at some point from Microsoft.)

Conclusion
So what does this mean to the developer? I have both good and bad news.

The good news is that you now have a choice in how you develop your ASP.NET applications. If you love the responsiveness and coolness of AJAX or you need to scale your applications big-time, then you’ll love ASP.NET AJAX. If, OTOH, you are into unit tests or TDD, you will love ASP.NET MVC. Finally, if you were looking for an easier way to build you basic CRUD web application, you’ll want to take a look at Dynamic Data. Don’t need any of the above? There’s no need to despair--ASP.NET Web Forms are here for the long haul!

The bad news is that you now have a choice in how you develop your ASP.NET applications. (Wait a second, wasn’t that also the good news?)This means you have more things to learn. It also means that in trying to support all four pillars, Microsoft may be taking some of its focus off Web Forms. After all, there’s only so many PMs and devs at Microsoft on the ASP.NET team. Furthermore, this means that if you are a manager like me worried about maintainability of applications and hiring developers, your job just got more difficult because one person’s idea of ASP.NET development is not necessarily someone else’s. Still, I think the good news here, outweighs the bad.

Microsoft used to present ASP.NET Web Forms vs. MVC as a choice between a car and a motorcycle. Both will get you to your job , but some (the majority of the population, I might add) prefer driving a car, while a sizable minority love their motorcycles which give you better gas mileage and independence, but don’t protect you in the rain. To stretch this analogy to its breaking point, let me suggest that ASP.NET AJAX is like riding a bicycle to work (lean and mean, best gas mileage, but it requires you to exercise for your commute and exposes you to the elements like the motorcycle) while Dynamic Data is like taking the bus to work (let metro do the driving for you.)

What about Silverlight?
Silverlight is really just the next generation of a one-click desktop application, that is hosted in the browser and runs on a multi-platform .NET virtual machine. Not to take anything away from Silverlight, but it’s not ASP.NET.

Does this mean that ASP.NET Web Forms is going away?
Although some people “in the know” have stated in the past couple of years that either ASP.NET AJAX or ASP.NET MVC was the future of ASP.NET, this is not the official position of Microsoft. Think about it, since 98%--yes, this is a total educated guess--of ASP.NET development is still done using ASP.NET Web Forms, and this percentage is unlikely to change significantly over the next several years, Microsoft would be stupid to kill off Web Forms. It doesn’t make any economic sense, and since Microsoft is a for-profit entity, I think Web Forms will be a major thrust of ASP.NET for many years to come.

In my opinion, Microsoft has added the three new pillars for the following reasons:

· Microsoft is always trying to follow innovation and buzz in the industry. Three years ago, that buzz was in AJAX. Today, MVC, separation of concerns, and TDD is all the rage so Microsoft has countered with ASP.NET MVC.

· Microsoft is always trying to broaden the appeal of ASP.NET. Microsoft has been trying to woo the open source community for years (after initially discounting it). And in order to do this, it needs to embrace many of the ideals of this community, which tends to live on the bleeding edge and is into AJAX, testability, and TDD, amongst other things.

· Microsoft truly wants to improve the productivity of its customers. After all, if you improve the ability of your customers, in our case corporate and independent developers, to get their jobs done, you’ve gone a long way to attracting and retaining customers. In Microsoft’s eyes (and many of its customers), this is a win, win situation.

I, for one, would like to thank Microsoft for the four pillars of ASP.NET. In producing the four pillars, Microsoft has given ASP.NET developers the choices they both want and need.