Wednesday, November 18, 2009

Download all images from a Webpage using C#

In this article I am going to explain how we can use the power of .Net framework class library for downloading the images imposed on a web page. There is a class called WebBrowser. Check here for msdn documentation.

WebBrowser browser = new WebBrowser();
browser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(browser_DocumentCompleted);
browser.Navigate(“http://www.msn.com”);

In the above code snippet, I am creating a new WebBrowser object. After that registering DocumentCompleted event. Now the most important statement, WebBrowser.Navigate, this method will accept a url and will load the webpage. Once the entire webpage is loaded, DocumentCompleted event will get fired. In this method we will do as follow

void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser browser = sender as WebBrowser;
HtmlElementCollection imgCollection = browser.Document.GetElementsByTagName("img");
WebClient webClient = new WebClient();

foreach (HtmlElement img in imgCollection)
{
string url = img.FirstChild.GetAttribute("src");
webClient.DownloadFile(url, url.Substring(url.LastIndexOf('/')));
}
}
First we will convert the sender object to a WebBrowser. Then we will get all the img tag’s in the loaded webpage. For each img tag we will use the WebClient object to download the image. We will be downloading the file to the current working directory.

Sunday, November 15, 2009

Image slide show using JQuery

In this article I am going to explain, how we can use JQuery for preparing a slid show using various images. You can download JQuery from the following link.

Download JQuery

Below is the aspx page content

<html xmlns="http://www.w3.org/1999/xhtml">
<
head runat="server">
<
title>Image slide show</title>
<
script type='text/javascript'
src="JQuery/jquery-1.3.2.min.js">
</
script>

<
script type="text/javascript">
$(function() {
var img = $("img.imgclass");
$(img).hide().eq(0).show();
var cnt = img.length;

setInterval(imgRotate, 5000);

function imgRotate() {
$(img).eq((img.length++) % cnt).fadeOut("slow", function() {
$(img).eq((img.length) % cnt)
.fadeIn("slow");
});
}
});
</script>
</
head>
<
body>
<
form id="form1" runat="server">
<
img src="Images/1.jpg" class="imgclass" alt="Image1"/>
<
img src="Images/10.jpg" class="imgclass" alt="Image2"/>
<
img src="Images/11.jpg" class="imgclass" alt="Image3"/>
</
form>
</
body>
</
html>

In the code what I am doing is straight forward. Get all img tags with class “imgclass”. Hide them initially. Every 5 second, call the method “imgRotate”. This method will fadeout the previous image and fade in the current image. Inside the form tag, you can add as many images you needed.

Hope this was helpful thumbs_up

Friday, November 13, 2009

Enabling IIS and ASP.Net 32 bit on 64 bit Windows OS

Assuming .Net framework is not installed. In that case follow the below step to enable IIS to run 32 bit ASP.Net applications.

Navigate to %WINDIR%\Inetpub\AdminScripts directory and run the adsutil.vbs script using the following command line

cscript.exe adsutil.vbs set W3SVC/AppPools/Enable32BitAppOnWin64 "true"

If you have .Net framework pre installed. Then after following the above step. Run the following command on the command line from the directory %WINDIR%\Mircosoft.Net\Framework\v2.0.50727

aspnet_regiis -i

Now you can install 32 bit ASP.Net applications.

The above solution is for IIS 6.0 on Windows Server 2003 64 Bit.

Now I am going to explain how to achieve the same on IIS 7.0

As compared to all Microsoft products IIS 7.0 is also backward compatible. This is achieved through IIS 6.0 metabase compatibility and IIS 6.0 WMI compatibility. Installing this will make IIS 6.0 Default Application Pool on IIS 7.0. For installing these options, if IIS 7.0 is already installed, configure it using the Add Roles option under Server Manager.

From Server Manager, Select Web Server(IIS). Now from left pane click on "Add Rol Services". In the new windows, scroll down, to check "IIS 6 Metabase Compatibility" and "IIS 6 WMI Compatibility".

Now open IIS Manger. From left pane select "Set Application Pool Defaults...". Now under General, select "Enable 32-Bit Applications" as true.

Paging and Sorting Optimized with ASP.Net GridView

Lets start by creating an Employee table

CREATE TABLE [dbo].[Employee](
[EmpID] [int] NOT NULL,
[Name] [varchar](50) NULL,
[Department] [varchar](50) NULL,
[Salary] [decimal](18, 0) NULL
)
ON [PRIMARY]

GO

For optimization, we need a stored procedure at database level, which will return one page of data. The following stored procedure is the bottom line of optimization

Create PROCEDURE spGetAllEmployee
(
@startIndex int,
@pageSize int,
@sortBy nvarchar(30),
@totalEmployees int OUTPUT
)
AS
SET NOCOUNT ON
DECLARE
@sqlStatement nvarchar(max)
DECLARE @upperBound int
IF
@startIndex < 1
SET @startIndex = 1
IF @pageSize < 1
SET @pageSize = 1
SET @upperBound = @startIndex + @pageSize
Select @totalEmployees=Count(*) From Employee
SET @sqlStatement =
'SELECT E.EmployeeID, E.EmployeeCode, E.Name, E.Department, E.Salary
FROM (
SELECT ROW_NUMBER() OVER(ORDER BY '
+ @sortBy + ')
AS rowNumber, * FROM Employee
) AS E
WHERE rowNumber >= '
+ CONVERT(varchar(9), @startIndex) + ' AND
rowNumber < '
+ CONVERT(varchar(9), @upperBound)

exec (@sqlStatement)

The stored procedure accepts page index, page size and sort expression. It returns the sorted data for that page index. The procedure contains two SELECT statements. The first one will find out the total employee count while the second statement is dynamic, which will return the sorted records of one page according to the provided page index and page size. If you look into the second SELECT statement you can see the use of ROW_NUMBER() function, which is an addition to SQL Server 2005 and above. What it will do is, it will add an additional column to the record set and places a record number for each row. In the outer query we will filter the result rows by using lower bound and upper bound indexes so that we return only the rows between lower and upper bounds.

Now take a look at the aspx page

<asp:GridView ID="GridView1" DataKeyNames="EmpID" runat="server" 
AllowPaging
="True" AutoGenerateColumns="False"
CellPadding="4" DataSourceID="ObjectDataSource1" ForeColor="#333333"
GridLines
="None" AllowSorting="True" PageSize="5" >
<
RowStyle BackColor="#EFF3FB" />
<
Columns>
<
asp:BoundField DataField="EmpID" HeaderText="EmpID"
ReadOnly
="true" SortExpression="EmpID" />
<
asp:BoundField DataField="Name" HeaderText="Name"
SortExpression
="Name" />
<
asp:BoundField DataField="Department" HeaderText="Department"
SortExpression
="Department" />
<
asp:BoundField DataField="Salary" HeaderText="Salary"
SortExpression="Salary" />
</
Columns>
<
FooterStyle BackColor="#507CD1" Font-Bold="True"
ForeColor
="White" />
<
PagerStyle BackColor="#2461BF" ForeColor="White"
HorizontalAlign
="Center" />
<
SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True"
ForeColor
="#333333" />
<
HeaderStyle BackColor="#507CD1" Font-Bold="True"
ForeColor
="White" />
<
EditRowStyle BackColor="#2461BF" />
<
AlternatingRowStyle BackColor="White" />
</
asp:GridView>

<
asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
SelectMethod
="GetAllEmployees" EnablePaging="true"
TypeName="WebApplication1.EmployeeData"
StartRowIndexParameterName
="startIndex" MaximumRowsParameterName="pageSize"
SortParameterName="sortBy" SelectCountMethod="GetTotalEmployeesCount" >
</
asp:ObjectDataSource>

We will be using the ObjectDataSource, which allow Virtual Paging. For achieving this we will be using the following property of ObjectDataSource

StartRowIndexParameterName - Specifies the parameter name of the Select method of ObjectDataSource’s bounded Type. ObjectDataSource will pass the value to this parameter when the user changes the page index. For example, if Grid View page size is 10 and the user clicks page number 3 to view the 3rd page, then the ObjectDataSource will calculate the value of StartRowIndexParameter by using the (page Size * page Index) formula. In this case it will be 10 * 3= 30. Default value of this property is startRowIndex, which means that if we don't mention any value for this property then the Select method should have the startRowIndex parameter.

MaximumRowsParameterName - Specifies the parameter name of the Select method of ObjectDataSurce’s bounded Type. ObjectDataSource will pass the value to this parameter when the user changes the page Index. ObjectDataSource source gets its value from GridView's PageSize property. Default value of this property is maximumRow, which means that if we don't set any value for this property then the Select method should have the maximumRow parameter.

SelectCountMethod - Specifies the method name of ObjectDataSource’s Type. This method will be called by ObjectDataSource to get the total number of records in the database. This count will help ObjectDataSource to create virtual paging in the Grid. For example, if GridView page size is 10, and SelectCountMethod returns 100 as total number of employees in the database then ObjectDataSource will display 10 page indexes in the GridView's pager area, even if we didn't get all the 100 records from the database.

SortParameterName - Specifies the parameter name of the Select method of ObjectDataSource’s bounded Type. ObjectDataSource will pass the value to this parameter when the user clicks on any column header to sort the data according to that column. ObjectDataSource fetches the value from the SortExpression property of the particular GridView column.

public class EmployeeData
{
private static int employeesCount;

public EmployeeData()
{
//
// TODO: Add constructor logic here
//
}

[DataObjectMethod(DataObjectMethodType.Select)]
public static List<Employee> GetAllEmployees(int startIndex,
int pageSize, string sortBy)
{
List<Employee> result;
int totalEmployees = 0;
if (string.IsNullOrEmpty(sortBy))
sortBy = "EmpID";
result = GetAllEmployee(startIndex, pageSize, sortBy,
ref
totalEmployees);
employeesCount = totalEmployees;
return result;
}

public static int GetTotalEmployeesCount()
{
return employeesCount;
}

public static List<Employee> GetAllEmployee(int startIndex,
int
pageSize, string sortBy, ref int totalEmployees)
{
System.Data.SqlClient.SqlConnection connection;
System.Data.SqlClient.SqlCommand selectCommand = null;
List<Employee> employeeList = new List<Employee>();

try
{
using (connection = new
System.Data.SqlClient.SqlConnection(
"Data Source=.;Initial Catalog=deptStore;Integrated Security=SSPI;"
))
{
if (connection.State != ConnectionState.Open)
connection.Open();

using (selectCommand = new System.Data.SqlClient.SqlCommand())
{
selectCommand.CommandText = "dbo.spGetAllEmployee";
selectCommand.Connection = connection;
selectCommand.CommandType = CommandType.StoredProcedure;

selectCommand.Parameters.Add(new
SqlParameter("@startIndex", SqlDbType.Int));
selectCommand.Parameters[0].Value = startIndex;
selectCommand.Parameters.Add(new
SqlParameter("@pageSize", SqlDbType.Int));
selectCommand.Parameters[1].Value = pageSize;
selectCommand.Parameters.Add(new
SqlParameter("@sortBy", SqlDbType.VarChar, 30));
selectCommand.Parameters[2].Value = sortBy;
selectCommand.Parameters.Add(new
SqlParameter("@totalEmployees", SqlDbType.Int));
selectCommand.Parameters[3].Value = totalEmployees;
((System.Data.SqlClient.SqlParameter)
selectCommand.Parameters["@totalEmployees"]).Direction = ParameterDirection.Output;
SqlDataAdapter adapter = new SqlDataAdapter(selectCommand);
DataSet empDS = new DataSet();
adapter.Fill(empDS);
totalEmployees = Convert.ToInt32(((
System.Data.SqlClient.SqlParameter)
selectCommand.Parameters["@totalEmployees"]).Value);

for (int index = 0; index < empDS.Tables[0].Rows.Count;
index++)
{
Employee emp = new Employee()
{
EmpID = Convert.ToInt32(
empDS.Tables[0].Rows[index][0].ToString()),
Name = empDS.Tables[0].Rows[index][1].ToString(),
Department =
empDS.Tables[0].Rows[index][2].ToString(),
Salary = Convert.ToInt32(
empDS.Tables[0].Rows[index][3].ToString())
};

employeeList.Add(emp);
}
}
}
}
catch (System.Data.SqlClient.SqlException ex)
{
throw ex;
}
return employeeList;
}
}

public class Employee
{
public int EmpID { get; set; }
public string Name { get; set; }
public string Department { get; set; }
public int Salary { get; set; }
}

Thursday, November 12, 2009

ASP.Net to Check whether request is coming from mobile device

For checking this use the following code

protected void Page_Load(object sender, EventArgs e)
{
if (Request.Browser.IsMobileDevice == true ||
Request.UserAgent.ToLower().Contains("iphone"))
{
Response.Redirect("DefaultIPhone.aspx");
}
}

The UserAgent property contains the data which tells from which device the request is coming. On problem with this approach is that there are lot of mobile devices and browsers which runs on mobile. One solution I found for this problem is by using a library called 51degrees.mobi.

Basic usage of LINQ

We can use LINQ in any scenario where we want to iterate through a list of items. For example how about listing all types in the current application domain?

var asm = from a in AppDomain.CurrentDomain.GetAssemblies()
from type in a.GetExportedTypes()
select type;

foreach (var val in asm)
{
Console.WriteLine(val.Name);
}

How about listing all 3.5 assemblies order by length

var alist = asm.Where(x => x.Assembly.FullName.Contains("3.5.0.0")).
OrderByDescending(x => x.Name.Length);

foreach (var val in alist)
{
Console.WriteLine(val.Name);
}

Lets find the total count of types for each version

var vers = asm.Select(
x => x.Assembly.FullName.Split(",".ToCharArray())[1])
.GroupBy(y => y)
.Select(z => new { VerName = z.Key, Count = z.Count() });

foreach (var ver in vers)
{
Console.WriteLine(".NET {0} has {1} types\n", ver.VerName, ver.Count);
}
Interesting right?

Highest value in each group using LINQ

First of all, let me thank Suportim for explaining how to achieve this. For demonstrating I have created an employee class as shown below.

public class Employee
{
public string Name { get; set; }
public string Department { get; set; }
public int Salary { get; set; }
}
Our aim is to find those employee from each department who earns the most. Here I am manually creating some employee as shown below
List<Employee> employeeList = new List<Employee>();
employeeList.Add(new Employee() { Name = "John", Department = "Web", Salary = 1000 });
employeeList.Add(new Employee() { Name = "Frank", Department = "Web", Salary = 2000 });
employeeList.Add(new Employee() { Name = "Loyd", Department = "Web", Salary = 3000 });
employeeList.Add(new Employee() { Name = "Peter", Department = "IT", Salary = 1500 });
employeeList.Add(new Employee() { Name = "Tevez", Department = "IT", Salary = 2500 });
employeeList.Add(new Employee() { Name = "James", Department = "IT", Salary = 3500 });
employeeList.Add(new Employee() { Name = "Peter", Department = "Finance", Salary = 500 });
employeeList.Add(new Employee() { Name = "Tevez", Department = "Finance", Salary = 1500 });
employeeList.Add(new Employee() { Name = "Cameron", Department = "Finance", Salary = 3250 });
Now check the LINQ statement for finding the most earning employees for each department.
var employees = from e in employeeList
group e by e.Department into egrp
let max = egrp.Max(sal => sal.Salary)
select new
{
Department = egrp.Key,
Name = egrp.First(val=>val.Salary == max).Name,
Salary = egrp.First(val=>val.Salary == max).Salary
};
For demonstrating lets print the values to screen
foreach (var emp in employees)
{
Console.WriteLine("In Department {0}, Employee {1} has the highest salary {2}",
emp.Department, emp.Name, emp.Salary);
}
Hope this helps.