Posts RSS Comments RSS 133 Posts and 258 Comments till now

EnableEventValidation Error

Invalid postback or callback argument. Event validation is enabled using <pages enableEventValidation=”true”/> in configuration or <%@ Page EnableEventValidation=”true” %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.

Event validation is a security measure by ASP.NET to prevent Injection-Attack (i.e. other page post their result to your ASPX page). Turning this option off through the web.config or inside the <%@ Page .. %> tag will guarantee you will never receive above error, but your security might be compromised.

But if your page still producing above error, say when you click a button, or select the value of a server dropdownlist control, these conditions might be applicable to your ASPX page:

  1. You have another <form /> tag inside your main Form tag
  2. Your AJAX/Javascript code changed the value of a server control
  3. You type tags that resemble HTML tags inside a textbox/text-area

What I have today was number 1. I found a <form /> tag inside a < asp:Content .. /> tag. The error came out when I convert my ASP.NET Website project into .NET Web Application Project. So its quite surprising that page never throw any Event validation error during its tenure as Website project. Another possibility is the <form /> was generated by Visual Studio when i convert the project. I’ll do some trial and error more tomorrow…

 

How To Kill MS Excel Process Started by ASP.NET

It was a quiet Tuesday afternoon in Singapore. The sky was greyish with clouds. The air was cool with slow wind. I sat in front of my computer mindlessly seriously reading blog posts in the neighbouring blogs.

The suddenly out of the darkness his room, Buddie approached me complaining about his Web Application. His ASP.NET web application is using Interop.Excel to read data stored in XLS file. The problem is that those Excel processes are refusing to be closed, resulting tens mega bytes of memory hogged.

Just to illustrate how the Excel process is started, please take a look of the following code which shamelessly proudly copied from MSDN:

//-----------------------------------------------------------------------
//  This file is part of the Microsoft .NET Framework SDK Code Samples.
//
//  Copyright (C) Microsoft Corporation.  All rights reserved.
//
//This source code is intended only as a supplement to Microsoft
//Development Tools and/or on-line documentation.  See these other
//materials for detailed information regarding Microsoft code samples.
//
//THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
//KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//PARTICULAR PURPOSE.
//-----------------------------------------------------------------------
using System;
using System.Reflection; // For Missing.Value and BindingFlags
using System.Runtime.InteropServices; // For COMException
using Microsoft.Office.Interop.Excel;

class AutoExcel {
	public static int Main() {
		Console.WriteLine ("Creating new Excel.Application");
		Application app = new Application();
		if (app == null) {
			Console.WriteLine("ERROR: EXCEL couldn't be started!");
			return 0;
		}

		Console.WriteLine ("Making application visible");
		app.Visible = true;

		Console.WriteLine ("Getting the workbooks collection");
		Workbooks workbooks = app.Workbooks;

		Console.WriteLine ("Adding a new workbook");

		_Workbook workbook = workbooks.Add(XlWBATemplate.xlWBATWorksheet);

		Console.WriteLine ("Getting the worksheets collection");
		Sheets sheets = workbook.Worksheets;

		_Worksheet worksheet = (_Worksheet) sheets.get_Item(1);
		if (worksheet == null) {
			Console.WriteLine ("ERROR: worksheet == null");
		}

		Console.WriteLine ("Setting the value for cell");

		// This paragraph puts the value 5 to the cell G1
	    Range range1 = worksheet.get_Range("G1", Missing.Value);
		if (range1 == null) {
			Console.WriteLine ("ERROR: range == null");
		}
		const int nCells = 5;
		range1.Value2 = nCells;

		// This paragraph sends single dimension array to Excel
	    Range range2 = worksheet.get_Range("A1", "E1");
		int[] array2 = new int [nCells];
		for (int i=0; i < array2.GetLength(0); i++) {
			array2[i] = i+1;
		}
		range2.Value2 = array2;

		// This paragraph sends two dimension array to Excel
	    Range range3 = worksheet.get_Range("A2", "E3");
		int[,] array3 = new int [2, nCells];
		for (int i=0; i < array3.GetLength(0); i++) {
			for (int j=0; j < array3.GetLength(1); j++) {
				array3[i, j] = i*10 + j;
			}
		}
		range3.Value2 = array3;

		// This paragraph reads two dimension array from Excel
	    Range range4 = worksheet.get_Range("A2", "E3");
		Object[,] array4;
		array4 = (Object[,])range4.Value2;

		for (int i=array4.GetLowerBound(0); i <= array4.GetUpperBound(0); i++) {
			for (int j=array4.GetLowerBound(1); j <= array4.GetUpperBound(1); j++) {
				if ((double)array4[i, j] != array3[i-1, j-1]) {
					Console.WriteLine ("ERROR: Comparison FAILED!");
					return 0;
				}
			}
		}

	    // This paragraph fills two dimension array with points for two curves and sends it to Excel
	    Range range5 = worksheet.get_Range("A5", "J6");
		double[,] array5 = new double[2, 10];
		for (int j=0; j < array5.GetLength(1); j++) {
			double arg = Math.PI/array5.GetLength(1) * j;
			array5[0, j] = Math.Sin(arg);
			array5[1, j] = Math.Cos(arg);
		}
		range5.Value2 = array5;

		// The following code draws the chart
		range5.Select();
		ChartObjects chartobjects = (ChartObjects) worksheet.ChartObjects(Missing.Value);

		ChartObject chartobject = (ChartObject) chartobjects.Add(10 /*Left*/, 100 /*Top*/, 450 /*Width*/, 250 /*Height*/);
		_Chart chart = (_Chart) chartobject.Chart;

		// Call to chart.ChartWizard() is shown using late binding technique solely for the demonstration purposes
		Object[] args7 = new Object[11];
		args7[0] = range5; // Source
		args7[1] = XlChartType.xl3DColumn; // Gallery
		args7[2] = Missing.Value; // Format
		args7[3] = XlRowCol.xlRows; // PlotBy
		args7[4] = 0; // CategoryLabels
		args7[5] = 0; // SeriesLabels
		args7[6] = true; // HasLegend
		args7[7] = "Sample Chart"; // Title
		args7[8] = "Sample Category Type"; // CategoryTitle
		args7[9] = "Sample Value Type"; // ValueTitle
		args7[10] = Missing.Value; // ExtraTitle
		chart.GetType().InvokeMember("ChartWizard", BindingFlags.InvokeMethod, null, chart, args7);

		Console.WriteLine ("Press ENTER to finish the sample:");
		Console.ReadLine();		

		try {
			// If user interacted with Excel it will not close when the app object is destroyed, so we close it explicitely
			workbook.Saved = true;
			app.UserControl = false;
			app.Quit();
		} catch (COMException) {
			Console.WriteLine ("User closed Excel manually, so we don't have to do that");
		}

		Console.WriteLine ("Sample successfully finished!");
		return 100;
	}
}

 

I don’t know how the exact code in his ASPX file, but it should be similar to the example detailed above. Actually, Buddie inherited the code from previous programmer which use the following brutal method to terminate the Excel Process:

Process[] procs = Process.GetProcessesByName("EXCEL");
foreach (Process p in procs)
{
   p.Kill();
}

 

When I was consulted about the code before, I said that this method might pose a problem with many concurrent accesses to the ASPX page. He then decided to comment the portion of code described above. :-D Which of course, resulting the memory hogged by many unclosed Excel processes. :-D

After fooling around with the code (huhu.. I thought fooling around only used by a person to the opposite sex :-D), I came up with a solution:

Process[] procs = Process.GetProcessesByName("EXCEL");
foreach (Process p in procs)
{
    int baseAdd = p.MainModule.BaseAddress.ToInt32();
    //oXL is Excel.ApplicationClass object
    if (baseAdd == oXL.Hinstance)
        p.Kill();
}

Basically the idea is to compare the lowest memory address of the Excel Application and the Process obtained by GetProcessesByName(). This way, the ASPX page will terminate exclusively the Excel Application that started by it.

Comments?

UPDATE: Please check the track back on the comments below.

DotNetNuke: Error Installing Module

Just solved a simple problem but took me hours to figure out the solution. So I will just share it here hopefully it will help you avoid the same mistake.

 

I have few DotNetNuke modules to be improved/debugged. So I managed to install the first module and improved it. When I tried to install the second module, DotNetNuke prompted me this:

error

So my immediate response was re-edit the manifest (.dnn) file. After validated it using DotNetNuke’s Manifest Validator (apparently it’s only an XML validator ^^!), I reinstall the module. Still the same error.

 

Strangely when I check the Module Definition Page, the module is actually installed. The DNN Manifest declared 4 Module Definition, but apparently only 3 added. When I tried to add the fourth Module Definition manually, it prompted me, “Module Definition is already exist”. EUREKA!!! (unlike Archimedes, I was not in the bathtub and then running around the village naked. I just running around in my house, fully clothed, of course :-))

 

So I compared the both DNN Manifest files. Snippets from the first DNN Manifest:


    Statistics
    
        
            DesktopModules/FirstModuleName/FirstModuleControlName.ascx
            View
        
    

 

Snippet from the second DNN Manifest:


    Statistics
    
        
            DesktopModules/SecondModuleName/SecondModuleControlName.ascx
            View
        
    

 

CONCLUSION: DotNetNuke’s Module Definition Friendly Name Is Unique

 

How to Install DotNetNuke

Apparently installing DotNetNuke is quite tricky. I did make a few mistakes which wasted a few minutes. So hopefully this post will save you from hassle.

  1. Get your Internet Information Server (IIS) up and running
    IIS is by default available on Windows 2000 all version, Windows XP Professional, Windows Server 2003. If you have Windows XP Home Edition, don’t worry. This hack should help to get IIS installed on Windows XP Home Edition. To confirm your installation click this HERE.
  2. Install .NET Framework 2.0
    Get your .NET Framework 2.0 HERE. The trick is always to get .NET Framework installed after your IIS confirmed up and running. You can’t do it the other way round. For most Windows XP installation, usually .NET Framework is already installed by default. If you happen to have such condition, you need to uninstall your .NET Framework, confirm that your IIS is up and running and then you proceed to install .NET Framework.
  3. Download DotNetNuke
    Although I recommended .NET Framework 2.0 at step 2, DotNetNuke older version is running on .NET Framework 1.1. So if you haven’t upgrade your .NET Framework to 2.0 and you don’t have intention to do so, download the DotNetNuke version 3.x. Otherwise, download version 4.x. The download page is HERE.
  4. Setup the Folder
    Extract the archive you download in Step 3. In this example we will assume the installation folder is C:\DotNetNuke. Right-click on C:\DotNetNuke folder, click Properties. On the General tab, make sure the Read-Only checkbox is not ticked. On the Security tab, add user “ASPNET” and give it Full Control access rights. You might want to add user “IUSER_YOURCOMPUTERNAME” (the IIS guest account) and give it non-Write access rights.
  5. Setup the Virtual Directory

    Open the IIS Management Console. You could do it by Start-Run-type “C:\Windows\System32\inetserv\iis.msc“-OK, or by Start-Run-type “compmgmt.msc“-OK continued by browsing to the IIS section. Right-click on the Default Web Site, New -> Virtual Directory. A wizard window will show up, click Next. Put DotNetNuke in the Alias text box, click Next. Browse to “C:\DotNetNuke”, click Next. Tick Read and Run Scripts only, click Next. Click Finish.
  6. Install Database
    Although DotNetNuke supports not only MS SQL Database, I have yet to research them. In this opportunity, I will only discuss about MS SQL. Hopefully someday I will have time to test DotNetNuke installation with other type of Databases and report it there. Okay, first you need to download your copy of MS SQL Express Edition. You can downloaded it HERE.
  7. Setup Database

    Open your SQL Server Management Studio (Start -> All Programs -> Microsof SQL Server 2005 -> SQL Server Management Studio). Click Connect. Above Database, Right-click -> New Database. Give the database a name, in this case we will name it MyDNN and click OK.


    Go to Security -> Logins. Above Logins, Right-click -> New Login. Type the Login Name –we will call it myDNNuser and then change the radio-button into SQL Server Authentication, and then type the password and confirm it, and then select the Default Database (i.e. MyDNN), and finally click OK.


    Go back to the MyDNN Database -> Security -> MyDNNuser -> Right-click -> Properties. Make sure db_owner on the “Schemas owned by this user is ticked”

  8. Edit Configuration File
    On the folder “C:\DotNetNuke” you will find web.config, edit it. If you could not find web.config, rename release.config into web.config. Look for a tag called <connectionStrings>. Inside it, comment the first child tag and uncomment the second one. Make sure you put the correct value in that tag. (i.e. value=”Server=YOUR_ComputerName\SQLEXPRESS; Database=myDNN; uid=myDNNuser; pwd=the_password;”). Do the same on the other tag called <appSettings>

After this you need to point your browser to “http://localhost/DotNetNuke/Install/install.aspx”. The installation should be automatic. Problems? Critics? Suggestions? Just drop your opinion on the comments. :-)

Close
E-mail It
Socialized through Gregarious 42