Sunday, November 22, 2009

The Template Persistent Cache initialization & IIS Application Pool

A quite funny monday morning. Our network police, Mr.Pais rushed to the desk with his lappy and wooed, finding a strange issue with IIS application pool. Obvious, he wont stay cool until and unless finds a solution. The brainstomer had given a glimspe of the error message the Event Viewer had been throwing for the last whole week. He observed the issue was registering in the log every morning before the office hour starts. Here is the event viewr log.

Event Type: Error
Event Source: Active Server Pages
Event Category: None
Event ID: 5
Date: 14/05/2004
Time: 4:32:55 AM
User: N/A
Computer: 001DC001
Description:

Error: The Template Persistent Cache initialization failed for Application Pool 'DefaultAppPool' because of the following error: Could not create a Disk Cache Sub-directory for the Application Pool. The data may have additional error codes..

Googleoscoped the solution, suggested him the workaround.
A. Add the NT AUTHORITY\NETWORK SERVICE account to
C:\WINDOWS\Help\iisHelp\common with "Read and Execute," "List Folder Contents" and "Read".

B. Add the NT AUTHORITY\NETWORK SERVICE account to
C:\WINDOWS\system32\inetsrv\ASP Compiled Templates with Full Control.

C. Add the NT AUTHORITY\NETWORK SERVICE account to
C:\WINDOWS\IIS Temporary Compressed Files with Full Control.
Do an IIS Reset.
You know what, he never turned up saying the same. Issue must be solved. ;)

Tuesday, November 17, 2009

Using Temporary Table, SQL Server 2005

ALTER PROCEDURE dbo.BUDGET_COMMITMENT_QTY_REPORT
(
@BudgetYear NVARCHAR(50) = null,
@BudgetVersion NVARCHAR(50) = null,
@Company NVARCHAR(50) = null,
@Division NVARCHAR(50) = null,
@CostCenter NVARCHAR(50) = null,
@SubAccount NVARCHAR(50) = null,
@SalesDivision NVARCHAR(50) = null,
@AsOnDate DATETIME = null
)
AS
SET NOCOUNT ON
BEGIN

DECLARE @Select NVARCHAR(4000)
DECLARE @Param NVARCHAR(4000)

SET @Param = ' @BudgetYear NVARCHAR(50) = null,
@BudgetVersion NVARCHAR(50) = null,
@Company NVARCHAR(50) = null,
@Division NVARCHAR(50) = null,
@CostCenter NVARCHAR(50) = null,
@SubAccount NVARCHAR(50) = null,
@SalesDivision NVARCHAR(50) = null,
@AsOnDate DATETIME = null '
CREATE TABLE #TEMPTABLE
(
BudgetType NVARCHAR(50), BudgetYear NVARCHAR(50), Company NVARCHAR(50), Division NVARCHAR(50), SalesDivision NVARCHAR(50), Costcenter NVARCHAR(50), SubAccount NVARCHAR(50), Display NVARCHAR(50), Amount DECIMAL(29,2), Quantity DECIMAL(29,2), RQDate DateTime
)

INSERT INTO #TEMPTABLE

SELECT BUDGET_TYPE AS BudgetType, BUDGET_YEAR AS year, COMPANY_CODE AS Company, DIVISION_CODE AS Division,
SALES_DIVISION AS SalesDivision, COST_CENTER AS costCenter, SUB_ACCOUNT_CODE AS subAccount, 'Precommitment' AS Display, SUM(AMOUNT)
AS TotalValue, SUM(QUANTITY) AS Quantity, PR_REQ_DATE AS RQDate
FROM ECMS_PR_BUDGET_CHECK
GROUP BY BUDGET_TYPE, BUDGET_YEAR, COMPANY_CODE, SALES_DIVISION, COST_CENTER, SUB_ACCOUNT_CODE, QUANTITY, DIVISION_CODE,
PR_REQ_DATE

UNION ALL

SELECT BUDGET_TYPE AS BudgetType, BUDGET_YEAR AS BudgetYear, COMPANY_CODE AS Company, DIVISION_CODE AS Division,
SALES_DIVISION AS SalesDivision, COST_CENTER AS CostCenter, SUB_ACCOUNT_CODE AS SubAccount, 'Commitment' AS Display, SUM(AMOUNT)
AS TotalValue, SUM(QUANTITY) AS Quantity, PO_REQ_DATE AS RQDate
FROM ECMS_PO_BUDGET_CHECK
GROUP BY BUDGET_TYPE, BUDGET_YEAR, COMPANY_CODE, SALES_DIVISION, COST_CENTER, SUB_ACCOUNT_CODE, DIVISION_CODE, PO_REQ_DATE

--SELECT * FROM #TEMPTABLE

SET @Select = 'SELECT #TEMPTABLE.BudgetYear, #TEMPTABLE.Display, #TEMPTABLE.Amount,
#TEMPTABLE.Quantity, ECMS_MST_COMPANY.Company_Name, ECMS_MST_COST_CENTER.Cost_center_desc,
ECMS_MST_SUB_ACCOUNT.SUB_AC_NAME, ECMS_MST_SALES_DIVISION.SALES_DIVISION_NAME , ECMS_MST_DIVISION.DIVISION_NAME
FROM #TEMPTABLE
INNER JOIN
ECMS_MST_BUDGET_TYPE ON #TEMPTABLE.BudgetType = ECMS_MST_BUDGET_TYPE.BUDGET_CODE INNER JOIN
ECMS_MST_COMPANY ON #TEMPTABLE.Company = ECMS_MST_COMPANY.Company_Code INNER JOIN
ECMS_MST_COST_CENTER ON #TEMPTABLE.Costcenter = ECMS_MST_COST_CENTER.Cost_center_code INNER JOIN
ECMS_MST_SUB_ACCOUNT ON #TEMPTABLE.SubAccount = ECMS_MST_SUB_ACCOUNT.SUB_AC_CODE INNER JOIN
ECMS_MST_SALES_DIVISION ON #TEMPTABLE.SalesDivision = ECMS_MST_SALES_DIVISION.SALES_DIVISION_CODE INNER JOIN
ECMS_MST_DIVISION ON #TEMPTABLE.Division = ECMS_MST_DIVISION.DIVISION_CODE '


IF @BudgetYear<>0 AND @BudgetYear IS NOT NULL
SET @Select = @Select+ ' AND (BudgetYear=@BudgetYear) '

IF @BudgetYear IS NOT NULL
SET @Select = @Select+ ' AND (BudgetType=@BudgetVersion) '
IF @Company<>0 AND @Company IS NOT NULL
SET @Select = @Select+ ' AND (Company=@Company) '
IF @Division<>0 AND @Division IS NOT NULL
SET @Select = @Select+ ' AND (Division=@Division) '

IF @SalesDivision<>0 AND @SalesDivision IS NOT NULL
SET @Select = @Select+ ' AND (SalesDivision=@SalesDivision) '
IF @Costcenter<>0 AND @Costcenter IS NOT NULL
SET @Select = @Select+ ' AND (Costcenter=@Costcenter) '
IF @SubAccount<>0 AND @SubAccount IS NOT NULL
SET @Select = @Select+ ' AND (SubAccount=@SubAccount) '
IF @AsOnDate<>0 AND @AsOnDate IS NOT NULL
SET @Select = @Select+ ' AND (RQDate<=@AsOnDate) '

--print @Select

Execute sp_Executesql @Select, @Param , @BudgetYear, @BudgetVersion, @Company, @Division, @CostCenter, @SubAccount, @SalesDivision, @AsOnDate

END
SET NOCOUNT OFF
RETURN

Friday, October 9, 2009

Generating thumbnail of an image on the fly and saving it to the server.

Yup, yet another scenario where I fumed my mind. I was with a product catalogue application, for a POC (Proof of concept) to Malaysian client, where the registered users would be able to add a product details under a chosen category. The uploaded products will be listed in the home page based up on the category. Requirement was of very low complexity.

File upload control is quite enough to upload a file in the server, which was serving the basic of my yesterday’s requirement. The product listing page, for sure, has to show the thumbnail view of the images. The product images which the client was supplied where of huge size. (1024X768 kind of stuff). No wonder, I was allowed to have only a single file upload control in the page. I just started bending the chair behind, how do I have a thumbnail image with the same name of the parent image, in a different folder.

Didn’t take much time to get out of the problem, ASP.Net System.Drawing namespace is what we need to have to get this done.

Upload an image in to server with the file upload control. (Say a 1024X768 sized image)

Generate random number generated from C# to give a unique name for the file which is going to be saved in the server. Generate the thumbnail image by specifying the width and height.

private void UploadImage()
{
if (UploadImage.HasFile) {
try {
Random random = new Random();
int randumNumber = random.Next(1000);
string FolderPath = Server.MapPath("~") + "\\ProductImages\\";
string FileName = randumNumber.ToString() + "-" + UploadImage.FileName;
System.Drawing.Image myImage = System.Drawing.Image.FromStream(UploadImage.PostedFile.InputStream);

System.Drawing.Image thumbnailImage = myImage.GetThumbnailImage(64, 64, new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback), IntPtr.Zero);

thumbnailImage.Save(FolderPath + "/thumbnails/" + FileName, System.Drawing.Imaging.ImageFormat.Gif); //thumbnails in different folder

UploadImage.SaveAs(FolderPath + "/" + FileName);
}
catch
{
MessageLabel.Text = "Unable to save the file";
}

public bool ThumbnailCallback()
{
return false;
}

Thinks are simple once you have a try, until then it would be complex. Now my concern is to have a water mark of the company logo on the main image on the fly. Come down,

Genrating Watermark on the fly

private void MakeWatermark()

{

string sProduct = Server.MapPath("ProductImage.jpg”);
string sLogo = Server.MapPath("logo.gif");

System.Drawing.Image oImage= Bitmap.FromFile(sProduct);
Graphics oGraphics = Graphics.FromImage(sLogo);
Bitmap oLogo = new Bitmap(s2);
oGraphics.DrawImage(oLogo, new Point(70, 70));

Response.ContentType = "image/JPEG";
oImage.Save(Response.OutputStream, ImageFormat.Jpeg);

}

Monday, September 21, 2009

Ajax Modal Popup Extender and ASP.Net Grid View Control

Had gone through a couple of blogs about having the modal popup extender of ASP.Net AJAX invoked from the button click of Grid view rows.

Posts were not many serving this requirement, though there were some where the Modal Popup Extender had been used in the Item Template of the grid view controls and the requirement is getting met. I could see the appreciations flowing to the blog poster. Well, I too appreciate those who took initiative to put forth a solution for the problem which ASP.Net developers have been facing.Now listen what I have to say you. Do you think keeping a control in an item template is a good and wise idea? How many modal popup extender instances get created while rendering the grid view control if there are one hundred records, and hence one hundred rows? Am I making sense?
Come on. keeping the modal popup extender inside the gridview’s item tempate is an absolute ridicule in this scenario. because, it is an overhead for the page. There are some other ways to get it done. Yup, here is the alternative.

Here we go, add a grid view in the page. Data bind the primary set of data where the result set primary key is, say RequestId in my scenario. Remove auto generate fields property of the columns of the grid view and add template fields to bind the result set. Keep an empty item template where we will later add the button, on click of this the popup to be invoked)

Let the Model Popup Extender be out side the grid, in the page itself. Do the settings of the properties as it is required to have for the modal popup. I guess, I don’t have to go through the settings required for it in detail. (If not, take a sneak peak here in the ASP.Net AJAX site. It is quite explanatory.)

Keep a Button, in the page (Not in the Grid view control), which has to be referred as the Target Control for the modal popup.
asp:Button ID="BtnPopUp" runat="server" Text="BtnPopUp" Width="0px"
Notice the width of the button, it is set to zero, won’t be visible at all when page is rendered. Surprising?, come on, this is a tricky way of doing it!

Insert a panel to the page from the Visual Studio toolbox; Keep a table in the panel where you can arrange your controls quite decently. Type “Click and Drag Popup Here” in the first row of the table where the id of the element should be Id=”DragIt” and set the property runat=”server” for the TD element. This is to enhance the drag facility of the pop up throughout the page.

Keep your Controls (Another grid view control to show the details of each rows? Well, add it then), which have to be popped up on click of the buttons rendered in the grid view, in the table, inside the panel (Control id = PnlResponse), give fixed width for the panel, say 350px.. BtnCancel refers the ID of the button in the panel, on click of which the pop up disappears.


--cc1:ModalPopupExtender ID="MpeSendResponse" runat="server"
TargetControlID="BtnPopUp"PopupControlID="PnlResponse"
BackgroundCssClass="modalBackground"
DropShadow="true"
OkControlID="BtnCancel"
CancelControlID="BtnCancel"PopupDragHandleControlID="DragIt">
cc1:ModalPopupExtender

Well, now we need to add a button control in the Item Template of the Grid view control.(Button control id=”GridsButton”) This Button has no settings for Model Popup extender.

Keep it as it is and Edit Data Bindings of this button control and data bind the required PrimaryKey of the particular row. Ie, Set the command argument as Eval(“RequestId”).

Add a Command Event for this button and in the command event,

You can get


protected void GridsButton_Command(object sender, CommandEventArgs e)
{
Int64 RequestId = Convert.ToInt64(e.CommandArgument);
CallAnotherMethodToShowMoreDetails(RequestId);
MpeViewResponse.Show();
}
All you need to do is to just invoke the Show() method of modal popup extender.

protected void CallAnotherMethodToShowMoreDetails(string RequestId)
{
//Do whatever you want with the RequestId.
}
You can fetch another set of records from the database by passing RequestId as the input parameter and display the result set in another grid view control kept in the pannel control (PnlResponse). Yup your pop up shows the details of the records when you click on the buttons in the parent grid view control.

Doesn’t it make sense?

Tuesday, September 1, 2009

MDX and SQL, the kissing cousins!

Quite interesting, yeah! Here we go,

If SQL is meant for create manage and query Relational Databases in OLTP(Online Transaction Processing) Systems, MDX, The Multi Dimensional Extension, is to perform calculations in OLAP(Online Analytical Processing) Databases.

Why MDX, and how important it is in Business Intelligence?

It is to query, navigate, and perform calculations in OLAP databases. OLAP databases are usually called as CUBES. Cubes are so called as the OLAP Databases comprises of multi Dimensional data. Though the cubes can have dozens of dimensions but rarely goes more than 15 to 20 to make them easier/understandable to work with. Cube consists of dimensions, hierarchies, levels, attributes and measures. MDX has been the strength of reporting and analysis in Business Intelligence (BI) as it supported virtually by many of the BI Server giants like Microsoft, IBM, Hyperion and SAP.

OLAP cubes are multidimensional database model which consists of measures and dimensions joined though a central fact table. As the arrangement of dimensions with a central fact table resembles a ‘star’, multidimensional database are called as ‘Star schemas’. At the same time we can compare OLTP database with ‘Spider Web’ as plenty of tables joined together through a complex set of primary and foreign key relationships.

Although you can theoretically query an OLAP cube using SQL, SQL has no inherent knowledge of dimension hierarchies and cannot easily navigate to the parent or children of a particular dimension member. Here comes the advantage of MDX over SQL. It can be used to navigate, query and perform calculations against multidimensional structures. Examples of Multidimensional structures are OLAP Cubes, dimensions, hierarchies, levels, attributes, members and measures.

MDX can recognize all kind of dimension relationship from ancestors to descendants f, from members to siblings, from root to leaf with very little coding. PeriodsToDate, LastPeriods, ParallelPeriod, YTD, QTD are few of the interesting 200 functions MDX have. (Interestingly, ParallelPeriod picks the data from a current period to the same period a year ago.) The queries for bringing these results in SQL would consume huge time and lines of code.

MDX was born on top of SQL to provide code consumption in dealing OLAP Server. OLAP Server was the invention of a third party called Panorama, and lately it was acquired by Microsoft.

Tuesday, August 18, 2009

Back button / Previous Page button in ASP.Net C#

Enabling Back Button in ASP.Net
There are different ways of doing it. I will just take you through two simple solutions.
First way is quite simple. A straight forward approach.
Declare a string variable public
static string goBackUrl = String.Empty;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
goBackUrl = Request.UrlReferrer.ToString();
}
}
protected void BackButton_Click(object sender, EventArgs e)
{
Response.Redirect(goBackUrl);
}
Second one is with View State.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GoBackURL = Request.UrlReferrer.ToString();
ViewState.Add("GoBackURL", GoBackURL);
}
else
{
GoBackURL = ViewState["GoBackURL"].ToString();
}
protected void BackButton_Click(object sender, EventArgs e)
{
Response.Redirect(BackPath, false);
}

Wednesday, August 12, 2009

A Comparison of Traditional FTP Upload & WebDAV Feature of IIS

FTP (File Transfer Protocol) & IIS WebDAV

Why WebDEV and whats wrong with FTP?

The traditional method for uploading content to a web server is File Transfer Protocol (FTP), but using this approach has its disadvantages:
• Using FTP requires that you open additional ports on your perimeter firewall, and this can increase the attack surface of your network and make it more susceptible to penetration by attackers. This is obviously undesirable from the perspective of keeping your network secure.

• FTP has no file locking mechanism, so it’s possible for two users to upload different versions of the same file simultaneously causing one to be overwritten. This can mean lost time troubleshooting why an uploaded file is different from what you expect.

• The FTP approach means you have to edit your content locally on the client. In other words, to edit a page already on the web server you would have to download it to the client, edit it there, and then upload it again to the web server. This is a time-consuming and inefficient approach to managing content.
WebDAV offers the solution for all the above problem scenarios, It’s a protocol used for publishing and managing content to web servers. WebDAV is an extension of the HTTP/1.1 protocol described in RFCs 2518 and 3253. WebDAV overcomes the three issues described above as follows:
• WebDAV uses port 80, the same port used by HTTP for web access. So using WebDAV means you don’t have to open any extra ports on your firewall.

• WebDAV lets only one user modify a file at a time, while allowing multiple users to read it. This allows files to be locked while they are being edited, preventing unexpected changes from occurring.

• WebDAV lets you edit files on the server instead of needing to download them first to the client. Editing files remotely using WebDAV is as easy as if they were locally present, and the whole process is transparent to the content producer.

How to Install and Use WebDEV on your Server?

When we use Windows Server 2003 machine to the role of Application Server, it installs various IIS 6 components but WebDAV isn’t one of these components installed. This is different from the earlier Windows 2000 Server platform where installing IIS 5 automatically installed WebDAV as well. To install WebDAV on the IIS 6 machine, use Add or Remove Programs in Control Panel and run the Windows Components Wizard. You can see WebDAV under Application Server > Internet Information Services > World Wide Web Service > WebDAV Publishing. Check it and Install.

You need to enable it for IIS after the installation. To verify if enabled, check the WebDAV option under the Web Service Extensions node in IIS Manager. Open IIS (Start>Run>inetmgr) See Web Service Extensions at the left pane. You will be able to se WebDEV at the right pane, if you select the Wen\b Service WExtension from the left pane. Make sure that it is Allowed. Be noticed, when WebDAV extension (httpext.dll) is Allowed, it would be applicable for all websites on your server. IIS unfortunately does not let you configure WebDAV for each and every website separately.

What to be set at Client side?

To create and manage content for your website , WebDAV to be enabled on the client machines. Windows XP has a built-in WebDAV client that doesn’t need to be installed, only enabled. To enable WebDAV on XP, open the Services console under Administrative Tools and find the WebClient service and double-click on this service to open its Properties. Change the Startup Type to Automatic, then click the Start button to run the service. Now you can publish the site content to your web server.

Settings on the Server for WebDAV

The physical directory where the Virtual directory points to be given read/write/directory listing permissions.
To publish content with WebDAV, the following web permissions on the directory to be enabled.
1. Read - lets users read what has been published to the server
2. Write - lets users upload new content to the server and edit existing content on the server
3. Directory listing - lets users view a list of published files on the server so they can select the one they want to view or edit.
If the Access is going to be given for a particular user group, It has to have Read, Read & Execute, and List Folder Contents permission. These are necessary for WebDAV users to be able to write and modify content on the web server. There are also two additional special permissions that the Users group has Create Files / Write Data, Create Folders / Append Data. These permissions too are necessary for WebDAV publishing, so don’t change them.

Publishing content with WebDEV

Go to Internet Explorer’s Menu, File>Open
Check the ‘Open as Web‘ check box. Window will be opened with 0 Object displayed.

Now, drag and drop your Local files in this window, it reaches at the root of your Virtual Directory’s root on the remote server!. You can browse it as http://162.61.39.8/Assetice/NewFile.aspx