Friday, March 30, 2007

Using AJAX

Continuing from the previous post, I'll first post a small tutorial on using ajax note that AJAX is a browser technology, so far I have tested in firefox and IE, ive read somewhere that SAFARI has partial implementation for it, but I didnt check which version was being discussed. first u'll need to create a factory method in your JS file, this method will , depending on the browser, call the correct library and get the ajax object.
it should look something like this:

function GetXmlHttpObject()
{
var objXMLHttp=null
if (window.XMLHttpRequest)
{
objXMLHttp=new XMLHttpRequest()
}
else if (window.ActiveXObject)
{
objXMLHttp=new ActiveXObject("Microsoft.XMLHTTP")
}
return objXMLHttp
}


You can call the function and get the object that will be sending the actual request

var url = “http://www.sample.comm/sample.asp”;
var xmlObj = GetXmlHttpObject(); //get the object from factory method
xmlObj.onreadystatechange = stateChanged;
xmlObj.open("GET",url,false);
xmlObj.send(null);


a line by line explanation of the code

xmlObj.onreadystatechange = stateChanged;

this line assigns the method to an event, whenever the state of the object changes the method you assign here will be called

xmlObj.open("GET",url,false);

here you are setting the options for opening the connection

arg1 = this can be either “GET” or “POST”, “POST” should be used whenever sending data more than 512kb
arg2 = the url of the server page to hit
arg3 = this parameter specifies whether the call should be sync or async

there are two additional arguments that can be passed, I havnt used them but I think they can be used for HTTP basic authentication

arg4 = username
arg5 = password


xmlObj.send(null);

This is the actual call, note that instead of passing null, you can send xml data in the argument.

Now, whenever the state of the object changes the method that you assigned will be called,

xmlObj.onreadystatechange = stateChanged;

lets look at how we can use this event

function stateChanged(){
if (xmlObj.readyState==4 xmlObj.readyState=="complete") {
alert("success");
}
else{
alert("error");
}
}


The readyState can be any one of the following:

0 = uninitialized
1 = loading
2 = loaded
3 = interactive
4 = complete

In this example I have only used the completed state, note that it might be returning its string counterparts depending on the browser

There are other properties which can be used for testing the state of the xml call object
These are:

responseText : get the response as a stirng
responseXML : get the XML DOM object which can then be parsed

status : status number for http such as 200 ok status or 404 error
statusText : get the status as string like “Not Found” or “OK”

from the server side, you can write anything from the page that you have specified in the callback url in Response.Write(“”) , which will become available in the responseText property of the xml obj once the callis complete

similiary , whole forms can be called and retrieved from response.Text, but its not generally a good idea as discussed in the previous post

head over to w3school.com for more tutorials on calling ajax., but this is pretty much there is to it

Thursday, March 29, 2007

Parent child forms in ASP

A month ago, I had to modify an ASP form with some functionality.

this functionality existed in another form, so I decided instead of developing or copy pasting the functionality , i would just call that form as a child in a DIV of the parent form using AJAX.

boy was that a bad decision! believe me it works, the whole form can be called in a div using ajax response.

but i ran into a weird problem that the javascript coming in the AJAX call from the child page didnt run, no matter what. even though the js was there in the AJAX response, I could see it in the debugger

I had to write whole of form validation scripting on the parent page, the elements in the child form were available by using

document.getElementById


in js. I warned another of my colleague who got a similar assignment , he wanted to do it with IFRAME element, and get calls at runtime by changing the form action for the form in the IFRAME element

eventually he ended with similar problems that I was having.

there was another problem with browser caching when using AJAX, when the user updates some values in the child form and submits it and refreshes the parent form, although the changes were reflected in database but the browser (specifically internet explorer) kept showing old values which I believe it keeps picking up from the cache.

theres a browser setting that can be set to check for the new instance of the page on every request, but that didnt seem to work either. We deployed the application with this so called "bug".

I'll post some examples related to this issue later on

Wednesday, March 28, 2007

Using COM interop services

The past few days have been quite interesting.

Recently I've had a chance to work with XSL and XSLT, the experience was just amazing considering the simplicity and ease of use, i'll probably publish a post on using those later...

The microsoft developers community is slowly migrating towards newer and newer development technologies, but there still a lot of legacy applications out there which require some new development. Here is where COM interop. comes in , it provides the ease of development in .NET while still using the class library as COM in legacy enterprise services such as ASP 3.0

I had a chance to work on a component which was developed in c# .net 2.0 as a class library and called in ASP 3.0

using COM interop is pretty straight forward

when developing a class library for COM interop in .NET its important to keep in mind that
all classes and methods to be accessed from legacy app should be public.

in .net 2.0 and VS 2005 the methods and classes are not visible to COM by default,

one way is to make the whole assembly accessible to COM , goto the project properties, under the application tab click assembly information and check the make com visible checkbox near the bottom



the other method involves using System.Runtime.InteropServices library and declaring [ComVisible(true)] attributes at class and method level for each of the method and class


Registering the Assembly as COM :

after compiling the assembly needs to be registered as COM using the command regasm.exe

a typical example of what I used was something like : regasm /codebase / tlb

the /codebase switch sets the code base in the registry and the /tlb creates a type library and registers it as well

there is another option available in visual studio 2005 in project properties build tab, theres a checkbox option to register for com interoperatibility, but i havnt personally tried using that option.

after registering the component it should be ready for use. I will consider usage from an ASP 3.0 application as an example

from ASP 3.0, the instance can be created by using

Server.CreateObject("namespace.classname") command

note that you have to provide the namespace and class name to create the object, the namespace is not required if creating the component in VB 6, instead you can call the class using the assemblyname.classname insted

after creating the object you should be able to call any of the exposed methods for the class. As for the arguments, I passed and returned the primary data types (including string) from my methods in object


Weird Errors :

Tracing COM errors is a difficult job, I suggest including some built in mechanism for logging events in the class library so it becomes easier to trace if the object breaks.

another problem I faced during development was non-relevant error messages thrown by ASP 3.0 this really gave me a headache. I spent almost the whole day trying to figure it out when calling one of my methods i kept getting an error that the instance was not set for my object.

The weird thing was that if I wrote Response.Write with the object name, it showed that the instance was created by printing the namespace and name of the class. At first I couldnt really understand that if the instance is created, but as soon as i call a method i got the error that the object wasnt set to an instance

Eventually i figured out that this error was caused when my COM object was breaking when i called the method and it gave this weird error about instance not being set.

Permissions :

we had to deploy on win3k server, I faced a number of issues there regarding security

Inn my class library i had to access registry. while testing the classes in .net test application it worked fine but asp 3.0 pages failed to compile giving the error that access was denied to registry keys.

this problem occurs because by default in IIS 6.0 IUSR_ account does not have enough rights to access the registry,
IUSR_is the machine account under which ASP 3.0 apps run

this can be resolved by giving administrative rights to the IUSR account on the machine, but this solution is not feasible for a lot of production environments.

the alternative is to register the .net COM with component services, open the run window type DCOMCNFG in win3k which will open the component services snap-in
follow these steps:
  1. add a new COM+ application
  2. create a blank server application
  3. provide the identity to be used by this com which has enough access rights (such as accessing the registry in my case)
the new COM+ app should have been created now add you component to this application by adding new component, and selecting from the library thats already registered you should see your namespace.classname in the registered components list (you would have to register using regasm.exe before this activity), select the component and add.

I encountered a problem here that one of the classes i created later was not appearing in the registered list. I traced the problem back to visual studio, it seems that even though make COM visible option was selected, the class still wasnt visible.

I had to manually include include the attribute [ComVisible(true)] in the class, recompile it and re-register using regasm (although first you would unregister the previously registered dll using regasm /unregister)

this solved my probem with having not enough access rights to the registry, becuase now i can specify the COM+ application under which identity to run


Win3k Error : could not create object, access denied :

you might get this error while trying to create your com object, to resolve this goto the COM+ application you created in component services, right click and go to the properties window. Under the Security tab there should be an option to enforce security checks/access, uncheck that option



it should now work.


happy COM interoperting!