Wednesday, August 12, 2009

Generic Handlers to display images from database in a gridview from database.

Generic Handler ; A ‘Generic’ way to find the solution.

Was fuming my head to fetch the logo image from SQL Server database (Not the URL, Image stored as the type image, in binary format). Plenty of try outs could lead me in to the solution.

ASP.Net 2.0 does not allow images(binary format) from the database and directly databind to a control in the page. There are some tricky things to get it done, Take a sneak peak.

Here is my Company Master Table

Allow null I used as this field was an addition to the master table which has got references to the transactions. Hope you understood the significance of allowed null. Well, leave that topic, it doesn’t make any sense in this topic.

I had to deal with two presentation layer files for this scenario. One is the .aspx page where my grid view sits with data bound with all the company information, except the logo, and the other, an ASHX file to custom handle the request. Try binding the logo entity to the server side image control, its not gonna work out.

So bind all other fields of Company master to the grid’s item templates and see how the image can be displayed. Here comes the role of Generic Handler.

Generic Handlers are equivalent to custom handlers and they contain classes that fully implement IHttpHandler. All you need is to simply surf the Generic Handler (ASHX) files and they're compiled automatically just as ASPX file works.

Advantages of Generic Handlers

The advantage of using the generic handler is twofold. First, it's usually much more convenient to generate a simple handler than it is to create a whole new assembly to handle the request. Second, you don't need to run interference with either Web.Config or with IIS. That is, Web.Config and IIS already understand what to do about files with the extension of .ashx. Installing ASP.NET places those when mapping into IIS.

Limitations

However, ASHX files have the same limitations as ASPX and ASCX files in terms of their place in an ASP.NET project. Simple generic handlers go with the project. That is, for the handler to work, it must accompany the whole project. Alternatively, custom handlers deployed as separate assemblies may be deployed and shared among the enterprise as Global Assembly assemblies (that is, strongly named assemblies placed in the Global Assembly Cache).


Back to our problem; added an image control in the template field of the grid view where I had to load the Company Logo.Hope you know the way of creating a Generic Handler. If not follow these steps.
Right click on the Website Project and Add New item in the Solution Explorer of Visual Studio IDE.
My Stored Procedure fetches the image field from Company Master for a particular Company ID. This ID had to be provided from the Grid View’s Item template as a Query String to the Generic Handler.





No big deal, accepted the query string and passed it to Stored Procedure and fetch the data as byte[]. Did a binary write of the fetched data. From the ASPX page, ie, my Master Dot Net Page,

public void ProcessRequest (HttpContext context) {

SqlConnection con = new SqlConnection();
con.ConnectionString = ConfigurationManager.ConnectionStrings["MyConnString"].ConnectionString;
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "select CH_CMP_LOGO from CH_CMP_INFO where CH_CMP_ID = @ID";
cmd.CommandType = System.Data.CommandType.Text;
cmd.Connection = con;

SqlParameter ImageID = new SqlParameter("@ID", System.Data.SqlDbType.Int);
ImageID.Value = context.Request.QueryString["ID"];
cmd.Parameters.Add(ImageID);
con.Open();
SqlDataReader dReader = cmd.ExecuteReader();
dReader.Read();
context.Response.BinaryWrite((byte[])dReader["CH_CMP_LOGO"]);
dReader.Close();
con.Close();
}

I could browse and view the company listing.

Happy!





sorry, i forgot to tell about the data access layer specialty to fetch the image.

int logoImageIndex = reader.GetOrdinal("CH_CMP_LOGO");
if (!reader.IsDBNull(logoImageIndex))
{
companyListingEntity.LogoImage = new Byte[(reader.GetBytes(logoImageIndex, 0, null, 0, int.MaxValue))];
reader.GetBytes(logoImageIndex, 0, companyListingEntity.LogoImage, 0, companyListingEntity.LogoImage.Length);
}

Monday, August 10, 2009

Service Unavailable error message when you browse a MOSS / WSS site or Central Admin.

IIS must be the reason for this. Do an IIS reset and see. If the problem persists, Just check the farm administrators password which has been set on the Application Pool.
To see this, go to Application Pool of both your site and the Central Administration site and right click to see the properties. Go to Identity tab and see the account name.

Make sure that the password is latest. If your network policy is defined some password expiration policy, you must have changed the password of the farm admin's domain password. Some times this to be reset in the Application Pool also. Do it for all the application pools of the sites which are not running and saying 'Service Unavailable'.
Give the new password in the identity tab and reset the iis.
run>cmd> iisreset
Hope it works fine now.

Wednesday, August 5, 2009

What next? Yeah, I got JQuery in hand !

What next, if the server side controls are rendered in to pure html? Has developer all done with coding? Not at all, jQuery can do a million at the front end.

Quite surprisingly, the client manager asked us to display the details of an internal order in a new table right after the selected row of the grid view by adding a new row in the grid view. What to do when the server side code has lost the control after the code has been rendered in to the browser? We went Google to come out of the trouble.

jQuery was the answer we found to relax a bit. The code snippets we found during our search made us wonder line by line. Hours of R&D brought us delight, could present it pretty decently up to the expectation.

Have a sneak peek here, this is the way we done it.
Added a button control in the item template of the Grid view. Attached a VB.Net Function in the Client Click event of the button, passing the Internal Order Number (PK) to it.


This VB Function triggers the Javascript Function defined in an external file. Passing Internal Order number and the current object Id. This Javascript method gets the parent object of the button, which is a element with help of jQuery and the object with the help of TD object.

Checking the value of the button control for + ( ie in collapsed mode ) and if collapsed, calling a Web service which returns the Result set for a particular Internal Order Number.

Just see how handy jQuery is

function LoadSummaryDetails(internalOderno,btnID, myObj)
{
btn=$('#'+btnID);
var btnVal=$(btn).attr('value');
td=$('#'+btnID).parent();
tr=$(td).parent();

if(btnVal == '+')
{
InternalOrder.InternalOrderXmlData.GenerateChildSummaryDetails(internalOderno,GridSucceedCallback);
}
else
{
$(btn).attr('value','+');
$(btn).attr('class','Expand');
var nextRow= $(tr).next();
$(nextRow).remove();
}
return false
}
Web Service method returns a result set as a string object with the help of a string builder object.
The Callback function associated with the web service call does the following steps

1. Assigns the value ‘-‘ to the grid’s button ( To ‘Expanded’ mode)
2. Setting the CSS class for the button.
3. Creating a newRow object and adding the result set returned by the Web service to it.
4. Adding the row after the current row.

function GridSucceedCallback(result,eventAgrs)
{
$(btn).attr('value','-');
$(btn).attr('class','Collapse');

var newRow = $("");
$(newRow).append(" "+result+"");
$(tr).after(newRow);
}

See the else block of the LoadSummaryDetails() function.
$(btn).attr('value','+');
$(btn).attr('class','Expand');
var nextRow= $(tr).next();
$(nextRow).remove();
On Click of ‘Collapse‘ button,
1. Set the value back to ‘+’ ( to ‘Collapsed’ mode)
2. Changing the css style
3. Getting the next row of the current row object where the Detials have been added.
4. Removing the row.

How to know the version of the SharePoint you are using

Go to Control Panel -> Add and Remove Programs.
OR, Go to (Windows) Start>Run>
Type appwiz.cpl


Select the product (sharepoint server) and then click: Click here for support.

Or: Under Tasks, Click "View Installed Updates"
Doesn't it answer your querry? :) Window must have popped up and said about your current SharePoint version.

Saturday, July 11, 2009

It is an error to use a section registered as allowDefinition='MachineToApplication' beyond application level, More than one Web.config

You may get this error when trying to browse an asp.net application.

The debug information shows that "This error can be caused by a virtual directory not being configured as an application in IIS."

However, this error occurs primarily out of 2 scenarios.

1. When you create an new web application using visual studio.net, it automatically creates the virtual directory and configures it as an application.
However, if you manually create the virtual directory and it is not configured as an application, then you will not be able to browse the application and
may get the above error. The debug information you get as mentioned above, is applicable to this scenario.

To resolve it, Right Click on the virtual directory - select properties and then click on "Create" next to the "Application" Label and the textbox. It will
automatically create the "application" using the virtual directory's name. Now the application can be accessed.

2. When you have sub-directories in your application, you can have web.config file for the sub-directory. However, there are certain properties which cannot
be set in the web.config of the sub-directory such as authentication, session state (you may see that the error message shows the line number where the
authentication or sessionstate is declared in the web.config of the sub-directory). The reason is, these settings cannot be overridden at the sub-directory level
unless the sub-directory is also configured as an application (as mentioned in the above point).

Mostly we have the practice of adding web.config in the sub-directory if we want to protect access to the sub-directory files (say, the directory is admin and we
wish to protect the admin pages from unathorized users).

But actually, this can be achieved in the web.config at the application's root level itself, by specifing the location path tags and authorization, as follows:-

However, if you wish to have a web.config at the sub-directory level and protect the sub-directory, you can just specify the Authorization mode as follows:-

Thus you can protect the sub-directory from unauthorized access.

Thursday, June 18, 2009

Menu control (Asp.net 2.0) is not displaying properly in Google chrome and IE8 (Beta).

Though the Asp.net 2.0 menu control was displaying fine in IE 6 and Mozilla, There were issues with mouse hover styles and alignment in Google Chrome and IE 8. I was scratching my head over and over for long.

Could find a solution to tackle this issue. This is really interesting.

The C# version of the solution is as follows:

( If you got a master page for the application / website, write this snippet in it's PreInit event )

protected void Page_PreInit(object sender, EventArgs e)
{
if (!IsPostBack)
{
if ((Request.UserAgent.IndexOf("AppleWebKit") > 0 ) || (Request.UserAgent.IndexOf("Unknown") > 0 ) || ( Request.UserAgent.IndexOf("Chrome") > 0 ))
{
Request.Browser.Adapters.Clear();
}
}
}

Happy hours ! It works for Chrome. Im trying for IE 8. Let me know if some one can give some ideas.

Tuesday, June 9, 2009

Export Excel Data to SQL Server Database

Stored procedure for Exporting data from Excel Sheet to SQL Server Table.

CREATE TABLE [dbo].[MyAddressTable] (
[FirstName] VARCHAR(20),
[LastName] VARCHAR(20),
[ZIP] VARCHAR(10)
)
GO

SELECT * FROM [MyTestDB].[dbo].[MyAddressTable]

INSERT INTO [MyTestDB].[dbo].[MyAddressTable] ( [FirstName], [LastName], [ZIP] )
SELECT [FirstName], [LastName], [ZIP]
FROM OPENROWSET('Microsoft.Jet.OLEDB.4.0',
'Excel 8.0;Database=E:\sabin\Try.xls;IMEX=1',
'SELECT * FROM [Sheet1$]')

It does not need to have excel to be installed in the Server machine where SQL Server is installed. All you need to have is a file of .xls in the server.

OPENROWSET featire to be enabled through SQL Server Surface Area Configuration.
Start > SQL Server 2005 > Configuration Tools > Surface Area Configuration

Click Surface Area Configuration for Features
Click on Database Engine and Check the Enable OPENROWSET and OPENDATA..

Done !