Wednesday, April 30, 2008

How to create a Web Server Control in ASP.Net with Delphi 2007

We were presented with the challenge of creating our own server controls. After some research on the web, we found very few examples regarding how to do this, even less if they are specifically targeted to Delphi.Net 2007.

So, in order to help the next fellow Delphi developer that is presented with similar situations, it is our objective to publish small articles on every new item that we face in our development process as a contribution to the new Spirit of Delphi that is growing in the community.

Special thanks to Feryal Badili for putting this article together. :)

Here is the step-by-step instruction on how to create a simple server control in Delphi 2007.

Well, there are two ways to create web components in Delphi:
1) You can go to 'File-New-Other-Delphi for .NET Projects' and choose 'Web Control Library'.
2) OR, you can go to 'File-New-Other-Delphi for .NET Projects' and choose 'Package'. Then in project manager panel, right click on 'Contains' folder and select 'Add new-Other-Delphi for .NET Projects-New ASP.NET Files' and select 'Web Custom Control'. You may want to use this approach if you would like to have multiple controls in the same package.

The general recommendation is to use the first method to create a web custom control for the first time, it is a lot easier in the long run, believe me.

Delphi will generate the source code for a very simple web control. Let's just try to understand it:

The default name for the file is 'WebControl1.pas' . It is a Delphi unit file and the unit name is really your namespace. You need to remember that because you're going to need it later when you are using the control in your web page!

Under 'Type' section of the code, you will see the following lines:

[DefaultProperty('Text'), ToolboxData('<{0}:MyWebControl1 runat=server>')] MyWebControl1 = class(System.Web.UI.WebControls.WebControl)

Well, what does it mean?
Your class MyWebControl1 is derived from System.Web.UI.WebControls.WebControl.

If your control renders a user interface (UI) element or any other visible element on the client, you should derive your control from System.Web.UI.WebControls.WebControl (or a derived class).

If your control renders an element that is not visible in the client browser, such as a hidden element or a meta element, derive your control from System.Web.UI.Control. The WebControl class derives from Control and adds style-related properties such as Font, Forecolor, and BackColor.

In addition, a control that derives from WebControl participates in the themes features of ASP.NET without any extra work on your part. If your control extends the functionality of an existing control, such as the Button, Label, or Image controls, you can derive from that control.
If you are going to have multiple visual controls in your server component and you wish to inherit the basic functionality of the parent controls, you need to derive your class from CompositeControl class:
MyWebControl1 = class(System.Web.UI.WebControls.CompositeControl)
To learn more about composite controls, see:
http://msdn2.microsoft.com/en-us/library/3257x3ea(VS.80).aspx

The code inside brackets that is generated on top of your class definition is attributes that apply to your class. To learn more about these attributes, see the following link:
http://msdn2.microsoft.com/en-us/library/ms178658(VS.80).aspx

The code generated by Delphi adds a property called 'Text' to your component . Since this property is published, you will be able to see it in the "IntelliSense" or "Code Completion" and object inspector when you use this component in a web page.

As you can see, this property also has some attributes:
Bindable: set it to true if your property can be data bound.
Category: In object inspector, this property will appear under the category(group) that you define.
DefaultValue: Obviously, this is the default value of your property.

You need to define these attributes for each and every property that you want to publish for your component. Also pay attention to the field definition for your property.

Next step is to add your own child controls and render the server control. In order to do that, you need to implement the following procedures:

procedure CreateChildControls(); override; procedure RenderContents(Output: HtmlTextWriter); override;

Here is an example of simple server control that includes only one control (TextBox) and adds one property named 'ShowTime' to the control.

You can use this component in both Visual studio or Delphi .NET.

unit WebControl1;
// To create a more advanced Web Control that supports live data at
// design time, see instructions in the readme file located in the
// 'BDS\5.0\Source\DotNet\dbwebcontrols' directory
//

interface

uses
system.web,
System.Web.UI,
System.Web.UI.WebControls,
System.ComponentModel,
system.Drawing,
System.Data,
system.security.Permissions;

type
///
/// Summary description for the component
///


[
AspNetHostingPermission(SecurityAction.Demand,
Level = AspNetHostingPermissionLevel.Minimal),
AspNetHostingPermission(SecurityAction.InheritanceDemand,
Level=AspNetHostingPermissionLevel.Minimal),
DefaultProperty('ShowTime'),
ToolboxData('<{0}:OpenItems runat=server>')
]
OpenItems = class(System.Web.UI.WebControls.CompositeControl)
strict private
IsError : boolean;

msgBox : textBox;
FShowTime: boolean;

strict protected
procedure RecreateChildControls(); override;
protected
procedure RenderContents(Output: HtmlTextWriter); override;
procedure CreateChildControls(); override;
public
constructor Create;
published
[Bindable(false),
Category('Behavior'),
DefaultValue(false),
Description('Show the Date and Time')
]
property ShowTime : boolean read FShowTime write FShowTime;
end;

implementation
uses SysUtils;

///
/// Define a public parameterless constructor needed by web controls.
///

constructor OpenItems.Create;
begin
inherited;
isError := false;
end;

procedure OpenItems.RecreateChildControls();
begin
try
EnsureChildControls();
except
IsError := false;
end;
end;

procedure OpenItems.CreateChildControls();

begin
try

Controls.Clear();

// Create a text box
msgBox := TextBox.Create;

if ShowTime then
msgBox.Text := DateTimeToStr(Now)
else
msgBox.Text := DateToStr(Now);

msgBox.BorderStyle := System.Web.UI.WebControls.BorderStyle(1); // Sets border style to 'None'
msgBox.ForeColor := System.Drawing.Color.get_Red;
msgBox.Style.Item['position'] := 'reletive';
self.Controls.Add(msgBox);
except
IsError := false;
end;

end;

///
/// Render this control to the output parameter specified, preserving
/// cosmetic attribute output generation inherited from standard
/// WebControl.
///

///


{$REGION 'Render override'}
procedure OpenItems.RenderContents(Output: HtmlTextWriter);
begin

if not IsError then
begin
// There was no error so far, render all components
try
AddAttributesToRender(output);

Output.AddAttribute(HtmlTextWriterAttribute.Cellpadding,'1', false);

Output.RenderBeginTag(HtmlTextWriterTag.Table);
// The table will be very useful when you have multiple visual controls
// included in your component

Output.RenderBeginTag(HtmlTextWriterTag.Tr);
Output.RenderBeginTag(HtmlTextWriterTag.Td);
msgBox.RenderControl(output);
Output.RenderEndTag(); // end td
Output.RenderEndTag(); // end tr

Output.RenderEndTag();

except
// An error happened, just show a message
Output.Write(' '+ 'Unable to create the components');
end;

end else begin
// An error happened, just show a message
Output.Write(' '+ 'Unable to create the components');
end;

end;

{$ENDREGION}

end.


Tuesday, April 22, 2008

Creating extended stored procedures on Delphi.

Well, originally we were going to implement a sexy Delphi.Net CLR Based Stored procedure now that we are using MSSQL 2005 and hearing all the good things about this highly publicized feature. Sadly, we hit the wall after initial testings showed us the big amount of limitations on the assemblies that we could use and all the exceptions we must made to make it work on MSSQL 2005. For example:

* First, you need to enable CLR on the database. (Thats ok.)
* Classes must be public and static. (Makes it harder, but we can manage it)
* Avoid namespaces with anything that is not the list of "safe" name spaces approved by Microsoft. (mmm)
* "Safe" assembly is simply a way of saying "non-microsoft built" assembly. You have a couple more "modes" on how to install your assembly on MSSQL, but as you can read below (MSSQL Online help), it gets touchy, and probably complicated. (yeah, I tried it, got ugly)

To create an EXTERNAL_ACCESS or UNSAFE assembly in SQL Server, one of the following two conditions must be met:
The assembly is strong name signed or Authenticode signed with a certificate. This strong name (or certificate) is created inside SQL Server as an asymmetric key (or certificate), and has a corresponding login with EXTERNAL ACCESS ASSEMBLY permission (for external access assemblies) or UNSAFE ASSEMBLY permission (for unsafe assemblies).
The database owner (DBO) has EXTERNAL ACCESS ASSEMBLY (for EXTERNAL ACCESS assemblies) or UNSAFE ASSEMBLY (for UNSAFE assemblies) permission, and the database has the TRUSTWORTHY Database Property set to ON. “

* MSSQL will complaing about the CodeGear assemblies being unsafe, some tweaking is necessary.

* Third party assemblies are not welcome on MSSQL. i.e. RemObjects.

Well, in summary, after playing with it, adding our assemblies required a lot of code trimming and removing any namespace that has any reference to anything visual (makes sense) even if it is not being used at all. Finally, the detail that just finish helping us to dropped the idea was that we don't have the source code for those "extra" assemblies (RemObjects) that we required and the amount of trimming just got out of control.

With one option out we went back to the drawing board with the plan to extend and update an old implementation of "Old School" extended stored procedures, as soon as I open that old project I realized why I never liked working with it, parsing the parameters, checking their types, defining data columns to return a proper record set was simply a big painful and slow process.

Thankfully, I was able to find in the vault of memories a great presentation by Berend de Boer made in Inprise DevCon '99 where he explains the general steps to implement them and even included a great piece of source code of the mighty "TSQLXProc" object that simply takes over the painful implementation and takes it to the Delphi way. After that finding Berend's website was easy.

For anyone needing this, check this link.

My Kudos to Berend,

Monday, April 21, 2008

EVERY DAY TIPS: Manually deleting a windows service

There I was playing with setting up subversion server running as a Windows Service until I made a tragic mistake and I get to the point of needing to remove the service that I just recently installed.

Ok, fine, as a good Delphi guy, I went looking for that sexy graphic console (Service Manager) that will give me the all mighty power to delete the service, but, I hit a wall after realizing that such an option was disabled for me.

So, after googling a bit I found two nice options.

1. If you remember the exact name of the service (not the description), you can use the sc command:
C:\>sc delete "service name"

If you don't know it, then you can go straight to the registry, find your guy and delete it.

HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services

You indeed will need to restart the computer to see these changes fully reflected.

Monday, April 14, 2008

Delphi for PHP 2 en EspaƱol

Well, great news for my mother language! We have now Delphi for PHP in Spanish!.

Yup, just after the official release we are now getting the news of a translation on the Cervantes language.

Tuesday, January 01, 2008

Truncating your transaction log.

First, HAPPY NEW YEAR GUYS!!

Now, some actual blogging...

Here I was, trying to restore our metadata only database into a production server, getting constantly an error messaging saying that it was waaay to big for the available space. Well, my concern was that the entire back up of the database was only 6MB, and the database itself only contains tables with very basic data.

What is worst, the space available on that production drive was 14GB, so gosh, it simply didn't make any sense. Well, after reviewing the original metadata-only database I realized that our constant adding, updating and deleting of structures made our transaction log simply huge. (40gb)

So, after some reading I found this nice recipe to cut down the fat of your log database:

First, backup your existing log file by running
BACKUP LOG  TO DISK = ''

Now, shrink the transaction log, executing this
DBCC SHRINKFILE (, ) WITH NO_INFOMSGS

File name is the transaction log filename and target size you wanted to be, don't be too demanding on the shrinking, but as a hint, I ended up making mine only 1MB cause we don't need a log on our metadata db. :)


Update:
My apologies, the database in question is MSSQL 2005. Thanks for the feedback.

Thursday, November 15, 2007

Help Update 1 for Delphi 2007 available.

Another great sign of constant improvement of my favorite IDE.

If you have not get an information dialog from your installation just go to Programs\Code Gear RAD Studio\Check for updates.

You can go here to read the install and Release notes, straight from CodeGear.

Tuesday, October 23, 2007

Migrating from ADO to dbExpress...

I finally started.

After holding the migration for a long time I am doing it, the reason? well, CodeGear has a renew effort on working on dbExpress, and its latest version dbExpress 4 is a great example of it, with good performance, great connectivity with WIN32 and .Net, support for BlackFish SQL, code included and completely rewritten in Delphi, and lots of improvements on D2007 to work with it like a new SQL Query Editor.

My initial testings always showed a better performance with dbExpress than ADO, now add the fact that ADO is being discontinued by MS in benefit of ADO.Net, the choice was a lot easier.

But, what I did to migrate thousands and thousands of components? Well it wasn't easy, there was no way I could do it in the form designer, it will simply take years.

So just go, open your Data Module, switch to code view, and Find/Replace the following:

1. Replace Connection with SQLConnection.
2. Replace TADOQuery for TSQLQuery.
3. Replace TADOStoredProc for TSQLStoredProc.
4. Replace TADODataSet for TSQLDataSet.
5. Parameters for Params.
6. CmdStoredProc for ctStoredProc.
7. Direction for ParamType.
8. pdOutput for ptOutput.
9. pdInput for ptInput.
10. Add under every dataset that uses SQLConnection, Schema = "dbo" or whatever your schema is.
11. Remove every parameter item called "@RETURN_VALUE".
12. Replace TDateTimeField for TSQLTimeStampField.


Geesh, thats what I remember, I will add more to the list if I hit more rocks on the road.

Thursday, September 27, 2007

Consolas fonts.

Well, I was reading the CodeGear's non-technical newsgroups, and found an interesting conversation regarding what kind of font you use on your development IDE, among the recommendations there was the new Consolas Font from Microsoft. Well, I surrender to temptation, downloaded the font, set it up on my RAD Studio 2007 and expected to see something cool in front of me, but.... nothing happened, tried several times, and nothing happened, the IDE didn't recognize the font, nothing changed.

Luckily I did my googling and found out this nice tool, that avoided me the trouble to attempt to configure the font from the command prompt .

Well, I did it, restarted my sexy IDE and yahoooo!! I have a nice sexy font. I must admit I like it, it will take a while to feel fully comfortable with it, but i think is here to stay.

Try it! you may like it too.

Monday, August 13, 2007

Restarting your application.

We are creating a project to automatically update our different modules. That usually implies an application restart, lots of ideas went around, a service that does that, a batch file, or another program working as a proxy of the original one, but, hey, I found this G R E A T article from Zarko Gajic who is always giving amazing tips with Delphi on how to do it in a VERY easy way.


Enjoy!

Saturday, August 04, 2007

The overload directive.

Well, it is fairly common to use the Delphi's overload directive to create a method with different sets of parameters in an object.

What I wasn't aware is that it actually works on functions or procedures that are not part of an object. That is cool.

Thursday, August 02, 2007

RemObjects and DataSnap.

I'm using a mix of Delphi's RemObjects SDK and DataSnap on our middletier, and we have implemented session management on all the services and in all the DataSnap remote modules.

Thanks to RO, that can be easily done on the DataSnap modules by turning on the RequiresSession property of the RODataSnapModule. Now the only problem with this is during design time, once it is on you will not be allowed to connect to your DataSnap datasetproviders without first logging in. So, as you can read that is a problem.

The solution? We added a command line parameter to our application server that simply controls if we want to require a session or not in our services or datamodules. Once that flag is set, we just use it as an indication while we are creating the service/datamodule.

Soon, I will post the results of a LETHAL combination, KbmMW, RO and DataSnap in a single SUPER POWERFUL MIDDLETIER MILKSHAKE.

Tuesday, July 31, 2007

Developer Day en EspaƱol!!

Hi guys,

CodeGear is hosting "Developer Days en EspaƱol" a nice gathering of great developers with the spanish speaking Delphi community.

There is a wide variety of sessions including Delphi, Interbase, PHP and Java.

It is only for 2 days, today was the first session and it was great. An average of 300+ guys were listening online to the different sessions, in my opinion a great success.

So if you want to check it out, this is the website.

Enjoy!

Monday, July 30, 2007

A nice surprise on Delpih 2007...

I was creating a "Lost Connection" dialog box for our rich client applications and as a distraction I was browsing around through thousands of nice icons on the internet, when I finally selected the icon that i wanted, I realized that it was (as almost every nice icon now days) a .png file.

Big disappointment I said, cause my mighty Delphi doesn't support that in a native way, I need to use a open source component, (actually there are tons of them, but I don't have the time for that) so I will have to convert it to that ugly bitmap thing. Oh well, i did and when I was getting ready to upload the image, sweet surprise!

TImage supports now gifs, cur, pcx, ani, png, gif, jpg, jpeg, bmp, ico, emf, wmf. I don't know if that is something new, but for sure it wasn't on Delphi 7 :P.


Love my D2007.

Sunday, July 22, 2007

Visual Studio launch in 2008....

Latest news said that Visual Studio will see the light in a joint launch with MSSQL Server 2008 and Windows Server 2008 in Los Angeles on February 27th, 2008.

But, it will be released officially by the end of this year.

CodeGear Studio will be out around September.

Sunday, July 08, 2007

Database scalability with MSSQL 2005

Some news from the battlefront...

We are expecting at least a 75% increase of our internet traffic, db transactions, network and database activity in general so our entire company is working hard on getting ready to manage this incoming wave.

Regrettably, life is not always good and the core of the business is setup around a system using a typical client/server architecture where each workstation creates a connection to the database and to make it worst, establishes server side cursors to fetch all data they need.

Now on the other hand, the website is driven by old school ASP pages, using adHoc Queries or direct stored procedure calls to the already beat up database. Finally, it is important to mention that this is running on ODBC connections.

End result?, chaos, in high traffic moments the entire network slows down and all the applications switch to a slow silent death walk to a total IT crisis. There is no caching techniques, no business layer, basically no middle tier... all the opposite things to what I'm used to deal with, and that is why it is my mission to turn this around and take over the world. (moooooahahaha)

Well, the mission is simple, we can't change much in short time, so we need to make this system work as good as possible. So, my first task is to provide a list of recommendations towards the deployment of our new database servers running MSSQL 2005.

Yup, we are migrating from MSSQL 2000 to MSSQL 2005, people will think that it is a simply straight import/export, but special considerations need to be made when dealing with the databases collation which has completly change from one version to the other one and to the famous "compatibility modes". Keeping an imported database in Compatibility mode 80 (MSSQL 2000) may save you headaches but will offer you little in terms of all the good new toys and performance tricks that you can apply on compatibility mode 90 (MSSQL 2005).

Bellow is a summary of my initial recommendations aimed to the physical database storage design aspect that you should follow when dealing with a situation like the described above:

  1. Server side cursors implies lots of memory usage on the database. So, increase memory on the database server, the more the better. Make sure your database is using it, by checking the database memory limit. (special attention to the 3gb limit on the non Enterprise versions of MSSQL)
  2. Multiple core machine? well, you will not use them if you don't separate that big nasty .mdf file into multiple .ndfs, what is the recipe? the number of data files within a single file group should equal the number of CPU cores.
  3. For optimized I/O parallelism, use 64 Kb or 25 Kb strip size when defining the RAID configuration.
  4. Use manual file growth database options. Automatic is only for development (ja! you didn't knowt that did ya?)
  5. Increased size of “tempdb” and monitor space usage, adjusting accordingly. The recommended level of available space is 20%. All your temp tables and indexes are created there so, keep that guy with enough space, if you are using the default size that is only 8MB, and that is basically 8 floppies, so be nice, put some more space there.
Alright, so that should buy us some time to concentrate on the next stage, database optimizations. Until the next post.

Wednesday, June 20, 2007

CodeGear drops C# Builder.

I was listening to one of the weekly community podcasts from CodeGear, and one of the topics that was mentioned was the announcement of C# Builder being dropped from the CodeGear Developer Studio 2007, to be released later this year.

Winforms seems to be a no no too. It seems they will be putting all their efforts on Delphi and C++ and Delphi.Net using the VCL.Net. They will convert their existing support for C# Builder to the same level of the VB personality, which means edit, syntax highlight, compile, and basic
debug functionality.

It looks like we will have the possibility to use any existing C# component and add it to your Delphi.Net project with no problem.

For people using ECO with Winforms, they will be ways to move into the direction of VCL.Net, which will be fully supported by ECO on the coming Delphi.Net release.

I certainly agree with their moves, there is no point on supporting a language that they cant controlled. They can use the .Net framework or the Win32/Win64 native APIs, but just like they did with Win32 by building the impressive VCL on top of it, expanding the VCL to support .net will also forced the VCL under native APIs to be extended to new cool functionalities.

Lots of news around CodeGear, which just reasures my thoughts towards the fact that these guys are doing the best they can to have things going the proper way.

Oh final comment, initially it was mentioned that Generics will be only supported from a consumption level, that seems not to be the case, production of Generics will be there too. But, only for .Net initially.

Thursday, June 14, 2007

ASP.Net not too scalable....

Scalability is a daily concern on my business. We managed thousands of requests, that startup lots of transactions that will make any online bank website simply jealous.

A couple of times, I worked with companies that use ASP.Net as their web framework of preference and it was not long when we start having scalability problems. It is a well known issue with ASP.Net, but there are solutions.

I found this interesting article that talks about the issue and gives a good solution.

Read it!

Wednesday, June 13, 2007

Using Visual Studio 05...

Yes, I know, but hey, I was programming on Java a couple of days ago, so for me it is just more stuff to learn and at least it is more visual than Java.

I'm in no way leaving behind my sexy Delphi, we just got a new update and a cool roadmap, but, I need to develop some web applications that connect to my Delphi middletier and the option I have right now is to do some ASPX on C#.

If I'm lucky enough, I should have the new Code Gear Developer Studio with support for .Net 2.0/3.0 by September, so I can use it.

Monday, June 04, 2007

The big reunion.

Hi guys,
I don't know if you were aware of this great reunion between the last two old schoolers of the software industry: Bill Gates and Steve Jobs, on an interesting chat together at D5!!.

The vision they had and have is simply outstanding, the advances we enjoy today on the software area can be easily blame to these two great minds.

Enjoy!

Friday, June 01, 2007

What will many cores mean to future window releases?

This is a good article about what is going on with Microsoft around the new trend on Multi Core devlopment.
You got to love AMD Opterons :)

A painless self-hosted Git service

Remember how a part of my NAS setup was to host my own Git server? Well that forced me to review options and I stumble into Gitea .  A extr...