The requirements for perfect web application framework

I was asked to write an article about application framework which we composed last months for buildign the web applications and I’d like to share my ideas, vision with you. I wrote “composed” because we didnt developed it from scrach but we tried to find possible solutions, connect and extedn them. It’ll be series of articles which will be published next days, so let’s start.

I work on the web applications last 10 years (I came from JSP world to ASP.NET) and my view how to build web apps changed quite much.  I added more and more requirements to the bag what the perfect web application framework should offer. 

  1. easy to use: it should be quite easy to learn and use the framework in order to build simple web apps. It should be also robust to build also enterprise web apps. This group of the apps will require deeper understanding of the framework which is quite normal and understandable.
  2. easy to extend: it should be possible to add there new features, it should be quite open and prepared for the future extensions, enhancements. 
  3. it should have large community of the developers behind the scene. This community of developers should create new versions, enhancements, support for the frameworkt, etc.
  4. comprehensive documentation source: I think the framework without good documentation is dead framework. 
  5. supporting testing mechanisms: to be developed with a focus on testing in order to support test driven development (TDD).

Btw, the requirements like clean architecture, offering scalability, etc. are must.

There are quite many frameworks on the market now. Some of theme are also opensource frameworks, others are developed as in-house frameworks. When you work on the business driven projects, you are still under the presure to deliver the functionality asap. There is no time to think about any frameworks quite often – just work, deliver the project. In such cases you use the standard ASP.NET like MS teach us. I met quite many developers who are in such situation – at least in our company. When I talk to them about MVP, TDD, O/R mappers and other “patterns” they are quite surprised that it exists, that there are also different views on the bulding web applications.

This inspired me to find a solution which we could use which fullfils the above mentioned requirements.

In the next posts I’d like to compare the frameworks like standard ASP.NET, ASP.NET MVC, Spring.NET for web, WCSF.

Then I’ll try to explain our solution with focus on the patterns like MVP, IoC, Factory; Behavior driven development, etc. 

To be continued …

Crystal Reports hell…

I’m working on the project where we should do some reporting. We choosed Crystal Reports as the reporting technology.

Everything worked fine until the testers started to test the reports on the testers’ DB. We use the testers for testing purposes ;o) We tought that it’ll be enough to change the connection string via CrystalReports DB connection API and it will work. But there were quite big problems and we found quite many people have the same problem how to set the connection in the runtime.

So how to solve the problems:

  1. use the data reader as custom data access object
  2. use ODBC connection and use CrystalReports API to do the weird crystal repotrs settings

 We choosed option 2 as it was for us more suitable.  So what we did:

  1. setup ODBC connection named i.e. coras with integrated windows security and default DB – coras_dev.
  2. create report with the input parameters i.e. via Visual Studio and use ODBC DSN name ‘coras’ (previously created) as the connection. Set the integrated security as is depicted on the picture.
  3.  

  4. Our reports have several parameters and when the user wants to generate the report he is asked for the parameters via autogenerated web page.
  5. execute the report in the code. I dont want to write whole code as we use a wrapper around standard crystal reports but the core setuping code is:

TableLogOnInfo crystalTableLogOnInfo = new TableLogOnInfo();
ConnectionInfo crConnectionInfo = new ConnectionInfo();
crystalDatabase =
this.Report.Database;
crystalTables = crystalDatabase.Tables;
foreach (Table crTable in crystalTables)
{
  crystalTableLogOnInfo = crTable.LogOnInfo;
 
if (!string.IsNullOrEmpty(this.ConnectionSettings.Server))
    crystalTableLogOnInfo.ConnectionInfo.ServerName =
this.ConnectionSettings.Server;
 
if (!string.IsNullOrEmpty(this.ConnectionSettings.Catalog))
    crystalTableLogOnInfo.ConnectionInfo.DatabaseName =
this.ConnectionSettings.Catalog;
  if (!string.IsNullOrEmpty(this.ConnectionSettings.UserID))
    crystalTableLogOnInfo.ConnectionInfo.UserID =
this.ConnectionSettings.UserID;
  if (!string.IsNullOrEmpty(this.ConnectionSettings.Password))
    crystalTableLogOnInfo.ConnectionInfo.Password =
this.ConnectionSettings.Password;
  crystalTableLogOnInfo.TableName = crTable.Name;
  crTable.ApplyLogOnInfo(crystalTableLogOnInfo);
  crTable.Location = crTable.Name;
}
this.Report.VerifyDatabase();

How the code works? It’s general code for ADO.NET conected Crystal Reports. Anyway the most important thing is that it’s necessary to iterate over the tables (in our case it’s stored procedure) and resets the table’s  logon info,  table name, apply the logon info and set the location! The setter causes the connection to the DB and recheck that the table exists (in our case stored procedure) – output from SQL Profiler:

exec [sys].sp_stored_procedures N'usp_GetAllocationsOfMyResources',N'%',NULL,@fUsePattern=1
exec [CORAS_DEV].[sys].sp_sproc_columns_90 N'usp_getAllocationsOfMyResources;1',N'dbo',N'CORAS_DEV',NULL,@ODBCVer=3,@fUsePattern=1
exec [CORAS_DEV].[sys].sp_stored_procedures N'usp_getAllocationsOfMyResources',N'dbo',N'CORAS_DEV',@fUsePattern=1

 It worked fine until I have the parameters. The output from SQL profiler:

exec CORAS_DEV.dbo.usp_getAllocationsOfMyResources;1 null,null,null

I found that the parameters (which I set in the other code) are not sent to the stored procedure execution as parameters! I found that there are sent to the report but not to DB access layer. The problem is that there is mapping between parameters passed to Crystal and parameters for stored procedure. When I change the connection in runtime, then the stored procedure has new parameters (their are specified via full name – [server].[schema].[sp]) So it’s necessary to recreate also crystal parameters and remap them to the current stored procedure params. That’s the reason why I had to call VerifyDatabase(). The output from SQL profiler:

exec CORAS_DEV.dbo.usp_getAllocationsOfMyResources;1 ''2008-05-23 18:00:18:000'',''2008-05-23 18:00:18:000'',1720

After this call I set the parameters and the report works fine.

We spent with elaboring Crystal Reports quite much time and I’m now gray haired developer but it works now!!!

Any comments, feedback, etc. ?  

Peace!