Friday, August 10, 2007

Can not retrieve values from grid view

Working with grid view, I faced an issue!

I had a gridview in which I had to hide few columns and use them later on for some conditional checks. The hiding part was quite easy and straight-forward but the conditional check was tricky. When I tried to get the values of the hidden column using
row.Cells[0].Text
where the hidden column index is 0, null was being returned. This looked strange to me as I was setting the values properly i.e. a datatable was being bound to the gridview and the datatable was properly constructed.

It turned out that ability to retrieve values from hidden columns has been chopped off in the new gridview. The logic that I found out (after a bit of gooling) was that, since most of the users hide primary key columns in the datatable, it is not safe to allow the column values to be retrieved. I guess the first part of the logic is very much right, that primary key columns are the best prospects to hiding. The second part may also be correct, that it is unsafe to expose them. But these two parts together, cause more harm than good!

First of all, inconvenience to devs as the regular functionality is changed. Second, how are the devs expected to identify the rows that the user is operating on? Often, the data in the gridview has a mapping table and if the dev can't retrieve its primary key, what operations are possible on it? And what use is the grid off?

Solution
Anyways, there is an easy workaround for this though. If you are in hurry, don't worry about all the blabber above. Just do the hiding of columns after you finish the binding of data. This works!

Monday, July 16, 2007

State-Machine Workflow Part II

We have the following on the host app:
  1. A service class that implements communication-service interface
  2. The workflow runtime and its services which are instantiated and added respectively in the host app.
Service Class
The service class basically implements the communication-service interface, promising the interface that it understands which events the workflow would support and that it will raise them. For each of the events that is supported the service class just raises them. That's it!

Workflow Runtime
We come to the centre of the pizza! Workflow runtime is the actual component that hosts the workflow. In effect, it's the translator between the workflow and the rest of the world.

Many services can be registered while instantiating the runtime. Services for External Data Exchange, tracking etc (the list of services can be easily googled) are provided to add extra functionality to the bare-bone runtime. But it's very important to choose the services judiciously as a service without purpose brings down the performance.

Friday, July 13, 2007

State-Machine Workflow Part I

State-machine WorkflowThis dia helps me very nicely in understanding how to implement a state-machine workflow (which relies on external events). Let me see if I understand each of the components in the dia :)

Let us start with the workflow part and then move to the host application part (prob in the next post if this one becomes too long):

The workflow part has only a couple of things:
  1. The workflow itself, and
  2. An interface
The Interface
The interface, also sometimes called as communication-service interface, is used to tell the outer world as to what events the workflow would respond to. To elaborate on this, the workflow is expected to handle events that are generated from the host application. Hence the host app needs to know which events the workflow is prepared to handle or, in other words, what functionality is the workflow capable of handling. The same is exposed through a set of events. Essentially, it (the interface) is nothing more than a communication contract, which helps the host app to understand what events it can raise. The interface, at the minimum, is supposed to do two things:
  • Is marked with ExternalDataExchange attribute: This attribute tells the WF that this interface should be used as a contract. A simple example would be:
[ExternalDataExchange]
public interface IAnalyzeNameService
{
event EventHandler AnalyzeName;
}
  • Give a list of all the events that the workflow would respond to.
That's it on the interface end! Quite simple!

The Workflow
On the workflow end, in addition to the actual workflow that it would contain, it should also define the custom EventArgs that has been used while defining the event in the service interface. (One can consider this activity to be outside of workflow also. ) But there are few things that should be taken care of:
  • It should inherit from ExternalDataEventArgs: Unless this is done the custom event args is not accepted. The obvious reason is that this pre-defined type has some information, like the instaced id, that needs to be propogated to the WF infrastructure to raise the event on the appropriate workflow instance.
  • This class should be marked as serilizable: If this is not done, an EventDeliveryFailedException is thrown.
  • InstanceID of the workflow instance should be passed (in addition to any custom info that would be required to be passed), for reasons mentioned already.
That does the job on the workflow side. There are a couple of things that should be done on the host app side and we are ready with a state-machine workflow running with the host app and the workflow communication in full flow.

Thursday, July 12, 2007

Error loading workflow: Runtime capabilities are not available with this type

I just started-off with coding on workflows and the first error that I see:

I did quite a bit of googling but couldn't find any answer. Usually in these kind of errors, the error (written in blue) is given with link which would take the dev to the error line. But here the link doesn't work i.e. you don't go anywhere :)

So the resolution?
Well, just rebuild the whole application. And it works like magic. Now, what's going on here: The scenario was that we were two guys working on same code using TFS. He had checked-in code which was not properly building (he was infact in the middle of making some changes). Once he checked-in properly building code things started working properly.

Wednesday, July 4, 2007

Going Forward...

Long time that I've updated my blog. I was actually busy with a personal work and couldn't concentrate on this.

Well, as Shakespeare said, All is well that ends well, I'm now going to resume my blog. But going forward the posts would be relating to Windows Workflow Foundation (WF), Windows Communication Foudnation (WCF) and Windows Presentation Foundation (WPF) rather than just C#. Though the theme of the posts would be same, "Not So Obvious..."

Monday, March 26, 2007

Every Type is derived from...

A simple question...

Which is the type from which every other type is derived? Think before you look forward!
If you are answer is System.Object, then it's partially correct. The actual answer is System.Object if it's a reference type. If it is a value type then it derives from System.ValueType.

Saturday, March 24, 2007

Multiple Entry Points

A dot net program has a single point of entry (which is generally the Main function).
public static void Main(int args[])

A well-known fact:The execution of the program starts from here. If we look at the sig of the function we see that the Main function is publi. But ever wondered what happens if the sig is: private static void Main(int args[])?

The Main method is invoked from outside of the program. So it is, obviously, essential that the method be public. But would the program compile if it was private? The answer is: YES. It would compile. For some reason, not so obvious to me, the compiler/runtime doesn't see difference between a public and a private Main method. All it needs is a Main method.

So what if, in a program, we have two Main methods, either private or public or both? The compiler/runtime is confused. It doesn't know which is the actual point of entry. So, ambiguity! Hence, errors!

But what if for some reason you want to have two main methods? Can you make things work or is it the end of the road? It's definitely not the end. You can still make it work, with as many Main methods you want. Only condition being, the fully qualified name of the method (or the type containing it) should be different from each of the other Main methods.
namespace MainNamespace
{
class FirstMain
{
public static void Main(int args[]) {}
}

class SecondMain
{
public static void Main(int args[]) {}
}
}

To build this program use:
csc.exe Program.cs /main:MainNamespace.FirstMain

This will do the trick for you.
The next obvious question is how would we compile it using VS 2005? I would take this in my next post.