Wednesday, July 22, 2009

Bad code alert =)

Haha, today a collegue of mine found a very funny piece of code unfortunatly located in on of our products, behold the 100 repeater-item killer:

The asp.net code-behind code is:

List list = null;
foreach (RepeaterItem item in repOngoing.Items)
{
HtmlInputCheckBox c = (HtmlInputCheckBox)item.FindControl("chkMark");

if (c.Checked)
{
HiddenField hfId = (HiddenField)item.FindControl("hfErrandId");

ITP1ErrandVO evo = getITP1Errand(new Guid(hfId.Value));
if (evo.ErrandTypeId == IKConstants.ERRANDTYPE_ITP1_OTHER)
{
uncheckErrands();
lblError.Text = "'Övrigt Ärende' kan ej sättas klar för batch.";
}
else
{
list = getCheckedErrands();
}
}
}

The page dislaying a repeater which is feed a list of ITP1ErrandVO:s to produce a list which users can edit and then save. This method is invoked when hitting the "save".
First of all it iterates over all repeateritems finding each checkbox and each id. Then a db-query fetches the errand and populates an object with the rows data. If its type is of type ITP_OTHER then it calls the uncheckErrands method:


private void uncheckErrands()
{
foreach (RepeaterItem item in repOngoing.Items)
{
HtmlInputCheckBox c = (HtmlInputCheckBox)item.FindControl("chkMark");
c.Checked = false;
}
}

This method also iterate over all items in the repeater finding the checkboxes and unchecking all of them! So in the rest of the iterations the c.Checked is never true. Hence it will call getCheckedErrands() for all else items. Take a look at getCheckedErrands method



private List getCheckedErrands()
{
List list = new List();
foreach (RepeaterItem item in repOngoing.Items)
{
HtmlInputCheckBox c = (HtmlInputCheckBox)item.FindControl("chkMark");

if (c.Checked)
{
HiddenField hfId = (HiddenField)item.FindControl("hfErrandId");
list.Add(new Guid(hfId.Value));
}
}
return list;
}

So for every unchecked checkbox find all checkboxes that is checked and add them to a list and return.

According to my colleague the errand is very seldom of type ERRANDTYPE_ITP1_OTHER so the list returned from the main-loop will be populated over and over again

Thank god I dont code like this =)

Tuesday, July 21, 2009

Workflow persistence and FaultHandler


I´m currently working an a quite big project, atm all alone. The purpose of the system im developing is to safely transfer/fetch/push data from business to business (B2B) with web services according to a securityspecification used by many well known insurencebusinesses in Sweden.

The problem I´ve stumbled into generates no matches on google search. My setup is as follows:
I got a workflow runtime running workflows that each represent a transaction of message between companies. Each workflow has a bunch of SendActivity/ReceiveActivities used to communicate to the other company but also to local so interests (the system takes no interest in what it send/receive).

Of of the many bugs I´ve found is when using a SendActivity or a CodeActivity which throws an MessageSecurityException (the bug is not likely to be restricted to that exception though) and having a FaultHandlerActivity catching the FaultException from the WCF call.



The first problem is that the Fault property of the FaultHandler is null making it totaly useless (mind FaultType is not null).. the second problem is when trying to presist the workflow after received exception. The latter generates the following exception:



Inner exception: System.Workflow.Runtime.Hosting.PersistenceException: Type 'System.ServiceModel.Channels.ReceivedFault' in Assembly 'System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable. ---> System.Runtime.Serialization.SerializationException: Type 'System.ServiceModel.Channels.ReceivedFault' in Assembly 'System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.
at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)
at System.Workflow.ComponentModel.Activity.Save(Stream stream, IFormatter formatter)
at System.Workflow.ComponentModel.Activity.Save(Stream stream)
at System.Workflow.Runtime.Hosting.WorkflowPersistenceService.GetDefaultSerializedForm(Activity activity)
at System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService.SaveWorkflowInstanceState(Activity rootActivity, Boolean unlock)
at System.Workflow.Runtime.WorkflowExecutor.Persist(Activity dynamicActivity, Boolean unlock, Boolean needsCompensation)
--- End of inner exception stack trace ---
at System.Workflow.Runtime.WorkflowExecutor.Persist(Activity dynamicActivity, Boolean unlock, Boolean needsCompensation)
at System.Workflow.Runtime.WorkflowExecutor.ProtectedPersist(Boolean unlock)


The reason for this problem is according to the exception that serialization is unpossible but why in the world is the SqlPersistenceService trying to save the FaultHandlerActivity? And how can I avoid it?

  • the easiest workaround is not to idle (atm I have a DelayActivity and PersistOnIdle="true").
  • or just dont use FaultHandlerActivity for catching WCF faults - but then I cannot use the SendActivity and has to do all proxymanagement in "workflow behind"
I´ve also tried to get feedback from WCF Forum in this thread.

Updated!

Ok, I´ve now given up finding a solution to this problem. I now manually create proxys from each workflow and handle the exception in code - making it much much much slower than the proxymanagement available through the ChannelManagerService. Unfortunately one cannot fetch the opened channels from the manager because it only contains internal classes...

Monday, July 20, 2009

Blogg back online!

There! First input since ages. After a lot of struggle with the thesis I completed it last year and I can now name myself as an civilengineer. I got a job as an developer at a small company in Umeå Sweden.


I will continue on this blog to talk about my programming problems and how i solved them - for venting purposes and the possibility that someone might find the same problem as me.


Code will now be syntax highlighted as in:

public void main() {
int a = 2;
}




Thursday, March 6, 2008

Further achivements!

Now Im getting somewhere!

Had a problem today that might interest someone using either DataFormWebPart or SPSiteDataQuery creating querys towards Sharepoint. The problem was with Calendars and retrieving the RecurrentData XML that specified how the event was repeating. In my case when retrieving from the SPList the RecurrentData was empty all the time. I thought first my dataformwebpart xslt was the error but putting the generated XSLT into sharepoint designer revealed no errors. It had to do with the selectcommand of the SPdatasource!
I didnt have a clue but you had to specifiy the column as a if you actually wanted the RecurrentData to show. But I had a mistake in generating the query: I used
<View><ViewField><FieldRef Name="field1" /><FieldRef Name="field2" /></ViewField></View> while sharepoint designer used the very strange syntax:
<View><ViewField><FieldRef Name="field1" /><FieldRef Name="field2" /></ViewField><ViewFields><FieldRef Name="field1" /><FieldRef Name="field2" /></ViewFields></View> OBS ViewFields with the same columns as the ViewField... Microsoft...plz

Thursday, February 21, 2008

Toolbar complete

I've just completed the toolbar for the generic list with some fancy buttons presenting the user with delete buttons for each item in the list or with a form for creating a new item to the list.

The toolbar was a big pain, it took me probably two-three weeks(!!) to figure out how sharepoint developers are creating their menus! Thats pritty insane, but my only source of information has been blogs and SharePoints insane pile of code.. come on M$ produce some documentation to your API please. Probably they havn't heard that an API without documentation is useless. I've could have completed a menu of my own in half that time or less...

Friday, February 8, 2008

Advancement!

Hi! Now I have finaly accomplished something, I was able to create a custom sharepoint menu for my application page using FeatureMenuTemplate containing MenuItemTemplate:s. To display them I used a control named toolbar residing in the 12-hive under controltemplates. Then I used SharePoint:Menu as template-buttons reffering to the menutemplates i created earlier.

Though now i have a problem when trying to inject some javascript into the web part. Its not recognizing it!

Monday, February 4, 2008

hmm more problems

Crap, today i read on a web page regarding the DataFormWebPartthat:
For security reasons, you cannot create Microsoft JScript code in your XSLT code using msxsl:script. All extension code available in your XSLT must either come from standard XSLT code, or from the functions described in this article.


That fucks me up quite a bit, because now i cant insert any javascript.

Hm, nevermind. I'll just insert my javascript in another way using one of these techniques. I only cant used external javascript files, which would be preferred.

Anyway I today realized that I will have further problems: The SPDataSource used for populating the DataFormWebPart cannot be used for Create, Delete and Update...Because it will only be rendered to a string and passed along through web services to another web-server, and there being inserted as a widget. But I can create all the forms in the web-part and then only handle receiving from forms and performing an javascript asynchronous web service-request to the list service when for example a list is being edited.