The Problem Solver

Tell me and I will forget
Show me and I will remember
Involve me and I will understand
- Confucius -

Google Ads

This Blog

Syndication

Search

Tags

News





  • View Maurice De Beijer's profile on LinkedIn

Community

Email Notifications

Explore

Archives

October 2006 - Posts

By default the web service wrapper generated around a workflow use the "tempuri.org" namespace. Not very pretty and certainly not something you want to use in a deployed application. So people started complaining and Microsoft listens (sort of).
 
Paul Andrew published the solution on this blog at http://blogs.msdn.com/pandrew/archive/2006/10/25/extending-the-wf-publish-as-web-service-or-get-rid-of-tempura-org.aspx. Now I don’t like it as it means searching for temp files with vague names, copying them and changing the generated code and ASMX page. Not exactly a pretty solution by any standards.
 
Unfortunately this is all we are going to get for now. Lets just hope a service pack to address this behavior doesn't take too long (yea right).
 
And while I am going on about it, how come there is only an ASMX web servide wrapper and no WCF wrapper? Really sounds like that is what we are supposed to have in the first place.
 
Posted by Maurice | 1 comment(s)
Filed under: , ,
How often can you meet a software legend in the Netherlands? Not very often, I tried to get him to the Netherlands earlier this year for an SDE event but unfortunately scheduling conflicts prevented this :-(
 
Well VBCentral and André Obelink has been more successful and will host an event with Jackie as speaker on November 22nd. You can register for this event at http://www.vbcentral.nl/tabid/166/Default.aspx.

Highly recommended!
 
Posted by Maurice | with no comments
Its almost time, less than two weeks to go to the start of Tech-Ed Developers in Barcelona. I am really looking forward to it :-) Just hope my back isn't going to trouble me too much as recovery is going a bit slower than I originally expected :-(
 
If you are going come by an the Ask The Experts stand and say hello or ask any question you might have about Windows Workflow, LINQ, VSTO or .NET 3.0 in general.
 
See you there :-)
 
Posted by Maurice | with no comments
Filed under: , , , ,
So you are going to add WF to your application, great but now you are faced with some decisions like:
  • Use state versus sequential workflows.
  • How much to put in a single workflow.
  • Where to leave all the information used by the workflow.
 
Well a while ago I wrote a blog entry on the choice of state versus workflows, see http://msmvps.com/blogs/theproblemsolver/archive/2006/10/11/Sequential-versus-State-workflows.aspx for the details. Next time I will write about where to leave all the information/data required by the workflow.
 
So the next question is how much to put in a single workflow. This is basically a question of creating bit catch all workflows versus smaller granular workflows.
 
My take on this is to create uses cases and turn each use case into a workflow. So let’s look at an example. A customer goes to a online shop, picks a few items, orders them and ask form them to be shipped. This is the basic use case but we can think of a number of additional use cases that may apply. For example:
  • The customer might prefer to pick the goods up in person instead of having them shipped.
  • The customer returns some of the goods as defective.
  • The customer returns some of the goods as unwanted. In the Netherlands this could easily happen because a consumer is permitted by law to return any item within 7 days of the purchase in which case he or she should get a complete refund.
  • A customer might not pay the bill and legal action should be started.
  • Etc…
 
Now all of these actions are valid variations of the basic sale but would it be smart to design them all into the same workflow? No certainly not! The workflow would become excessively large and complex with lots of actions that never execute during normal operations.
 
So I suggest you create a basic workflow consisting of a normal sales action. This consists of:
  1. Pick items.
  2. Choose delivery method.
  3. Choose a payment method.
  4. Spawn a new delivery workflow depending on the delivery method.
  5. Spawn a new payment workflow depending on the payment method.
  6. Wait for the delivery workflow to notify the sales workflow that the delivery is made or canceled.
  7. Wait for the payment workflow to notify the sales workflow that the payment is finished.
 
Now the payment and delivery are separated out of the main workflow. This way it becomes easier to support alternatives or reuse them in other places. For example if the customer returns a defective item we will have to ship him a new one. Shipping is no different but the whole process of handling defects is vastly different from selling the original item.
 
An alternative to spawning new workflows would be to modify the workflow at runtime adding the required steps. The main benefit would be that everything stays nice and contained in a single workflow making it easier to track but the drawback is that part of the workflow is designed in code removing the a major benefit of WF in that a picture is worth a thousand words.
 
Conclusion
Model your workflows after the real processes in your organization. If one process activates another take a good look if it is really part of the first process of more the result of it. Often it will turn out to be just a new resultant process that really should be a different depended workflow.
 
 
Posted by Maurice | with no comments
Filed under: , ,
Google has only just released its possibility to create a custom search engine and already people are putting it to good use.
 
Dan Appleman decided to create a search site targeted at .NET developers. Now I have always said that Google is my friend when it comes to finding information but sometimes it just servers up a bit to much for my own good. Well Dan's site will be a welcome first filter, only searching through selected sites and thus filtering out a lot of the garbage.
 
See his announcement at http://www.danappleman.com/?p=49 or the search engine at http://www.searchdotnet.com/
 
I already bookmarked the search page :-)
 
Enjoy!
 
Posted by Maurice | with no comments
Filed under:
Brian Jones has released a few videos about working with the new XML based document structure in Office 2007. They make for some interesting watching if you are new to the Office 2007 XML format.
 
 
Using the content controls in Word 2007:
Recommended!
 
Posted by Maurice | 2 comment(s)
Filed under: , ,
I just found two interesting blog post about dynamically updating workflows by Bart de Smet.
 
WF - How to make a workflow dynamic?
 
Recommended!
 
Maurice de Beijer
 
Posted by Maurice | with no comments
Filed under: , ,
I recently gave Microsoft Expression Web a spin while working on a new web site. I must say I was pleasantly surprised. Now I didn't do a full test of review but did use it to create a template for the new web site using the build in templates as start. Renaming a few files and a few small tweakes where enough to have it working in VS2005 as a regular ASP.NET web site.
 
One thing I noticed was that quite a few features where very Frontpage like. Well I guess that should not be a surprise :-)
 
Certainly a product to keep an eye on.
Maurice de Beijer
 
Posted by Maurice | 1 comment(s)
Filed under: ,
For example adding child Activities to a another.
A WhileActivity can only contain a single child activity, the same is true for a ReplicatorActivity. However a IfElseActivity and a ListenActivity can contain multiple child activities. Now the difference doesn't matter much as the single activity in the WhileActivity or ReplicatorActivity can be a SequenceActivity which in turn can contain multiple children but still it's confusing.
 
When a ConditionedActivityGroup is used you drop whatever activities you want in and these activities gain an extra property, the WhenCondition. On the other hand with the FaultHandlers you drop a FaultHandlerActivity in the top, set its FaultType and drop the activities you want to execute below. By the way the same difference as above applies, the ConditionedActivityGroup accepts a single child activity for each branch while the FaultHandlers accept multiple children for every FaultHandlerActivity.
 
Now this isn't much of a problem but the behavior seems inconsistent. If there is some good reason I am missing I would appreciate the info.
 
Enjoy!
 
Maurice de Beijer
 
Posted by Maurice | 2 comment(s)
Filed under: , ,
Scott Guthrie just posted the news that ASP.NET AJAX Beta 1 is released. No not the final product but Beta 1! It is kind of hard to believe that the product is just at the Beta 1 stage. After all it has been talked about so much that it almost sounds like its been around for years and version 5 is about to be released. But no it is all hype so far. But that said I think it’s a very exciting product that will help ASP.NET developers create much more dynamic sites. But like anything else out there with a lot of power it also opens the door to a lot of misuse, lets hope this doesn’t happen to much and give a very useful product a bad name.
 
 
Enjoy!
 
Maurice de Beijer
 
Posted by Maurice | with no comments
Filed under: ,
The PolicyActivity is rather cool but with more than a few rules in the RuleSet and full chaining enabled it can become a bit hard to see what is going on. Now it would be nice if we could step through the rules with the debugger but if there is a way I haven't found it yet. Of course you could add Console.WriteLine statements to the actions, after all they can be multiple statements. There is however an easier way that will show exactly what the runtime engine is doing and that is tracing.
 
Add the following to the app.config:
  <system.diagnostics>
    <switches>
      <add name="System.Workflow.Activities.Rules" value="Verbose" />
    </switches>
  </system.diagnostics>
And run the workflow again. This time the Immediate Window will contain a trace with all rules being loaded and their dependencies. After that the trace will contain all evaluations of conditions and results thereof. The following is an example of a small RuleSet I created:
 
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "+5%" Condition dependency: "this/amount/"
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "+5%" THEN side-effect: "this/rate/"
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "10%" Condition dependency: "this/age/"
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "10%" THEN side-effect: "this/rate/"
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "50%" Condition dependency: "this/age/"
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "50%" THEN side-effect: "this/rate/"
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "Calc" Condition dependency: "this/"
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "Calc" Condition dependency: "this/amount/"
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "Calc" Condition dependency: "this/rate/"
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "Calc" Condition dependency: "this/discount/"
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "Calc" THEN side-effect: "this/discount/"
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "+5%" THEN actions trigger rule "Calc"
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "10%" THEN actions trigger rule "Calc"
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "50%" THEN actions trigger rule "Calc"
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "Calc" THEN actions trigger rule "Calc"
System.Workflow.Activities.Rules Information: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Executing
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Evaluating condition on rule "+5%".
System.Workflow.Activities.Rules Information: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "+5%" condition evaluated to True.
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Evaluating THEN actions for rule "+5%".
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Evaluating condition on rule "10%".
System.Workflow.Activities.Rules Information: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "10%" condition evaluated to True.
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Evaluating THEN actions for rule "10%".
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Evaluating condition on rule "50%".
System.Workflow.Activities.Rules Information: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "50%" condition evaluated to True.
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Evaluating THEN actions for rule "50%".
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Evaluating condition on rule "Calc".
System.Workflow.Activities.Rules Information: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "Calc" condition evaluated to True.
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Evaluating THEN actions for rule "Calc".
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "Calc" side effects enable rule "Calc" reevaluation.
System.Workflow.Activities.Rules Verbose: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Evaluating condition on rule "Calc".
System.Workflow.Activities.Rules Information: 0 : Rule Set "Rule Set1": InstanceId 4c453688-cb02-41e9-a641-39921711d2a0: Rule "Calc" condition evaluated to False.

Rather nice as you can see exactly what is going on. Just make sure you name your rules well otherwise it will still be somewhat hard to follow.
Enjoy!
Maurice de Beijer
 
Posted by Maurice | with no comments
Filed under: , ,
Some time ago I installed the Google Desktop Search utility so I could quickly search my hard drive for all sorts of stuff I know is on there but can’t remember where. Well some time ago I discovered that hitting Windows+G was a fast way of searching my desktop as it started a new browser window and brought me to the Google Desktop search window.
 
Well this morning I hit the Ctrl key twice by accident and discovered that was an even faster way to search :-) Doing so activates a small popup window allowing you to search the local disk and the Internet. It even lets you start programs, just hit Ctrl twice and type notepad and start it, next time just typing an N is enough to have it at the top of the list. Now I have no clue how log I have had this feature but it sure is useful :-)
 
Enjoy!
 
Maurice de Beijer
 
Posted by Maurice | with no comments
Sometimes mailing lists about Visual Basic can take an unexpected side turn and uncover some unexpected behavior. This time its about Google Image search.
 
Google Image search itself it quite cool and useful when searching for an image. Of course you won’t always find what you are looking for but sometimes it just doesn’t exist or isn't indexed. Or at least that was my take on things. Turns out there is more to it though.
 
A fellow MVP was searching for an image with the Cup<T> logo. So she thought lets use Google Image search, I would have done the same. Now she can’t find it so ask on the mailing list of someone has a copy. Someone else uses Google Image search and it turns up as the first hit WTF! So a number of us try and as far as we can tell you get either 1 of two different result sets. One set starts with the required Cup<T>.
 
 
The second group don’t get to see this picture but get a result set starting with some Manchester United soccer.
 
We all use exactly the same search criteria "Cup<T> Generics" or http://images.google.com/images?hl=en&q=Cup%3CT%3E%20Generics&btnG=Google+Search&sa=N&tab=wi
 
Neither location nor previous soccer searches seem to be the cause of this either.
 
So if anyone knows what the reason is I am more than a little curious so let us know.
 
BTW. A search using live.com seems to work for everyone.
 
Maurice de Beijer
 
Posted by Maurice | 3 comment(s)
If you are doing any sort of database updates you are more than likely using transactions. If you are not either your application is very simple or it’s a problem waiting to happen :-(
 
In .NET 2.0 the new System.Transactions and in particular the TransactionScope type make working with transactions a lot easier than before. In fact so easy that there really is no excuse not to use them. John Papa just published an interesting article in the MSDN magazine showing how and when to use the TransactionScope. Read the article at http://msdn.microsoft.com/msdnmag/issues/06/11/DataPoints/default.aspx.
 
And just in case you where thinking I don’t do databases so I don't need TransactionScope it works with all sorts of resource managers. For example reading messages from a transactional MSMQ message queue can be wrapped in TransactionScope just fine.
 
Enjoy!
 
Maurice de Beijer
 
Posted by Maurice | with no comments
Filed under:
As you may be aware, after all I have given some presentations about it, I like SQL Everywhere and its capabilities for both partially connected client and utilities that just need a small local database. The main problem with SQL Everywhere is syncing the local database with its counterpart on the server. The existing possibilities, RDA and Merge Replication, have their uses but leave something to be desired for partially connected smart applications.
 
Well Steve Lasker is working on the Offline Data Synchronization and Caching library for SQL Server Everywhere. While it doesn’t quite work the way I advise people to do it the library seems like a well though out system and seems to do the job very well. Now personally I like to use MSMQ to push the changes back to the server, the main advantage is that as soon as the PC is back in the network the changes will be pushed up and be applied, no need to first start your application. Of course the same effect could be achieved by running the sync framework from a service but that way you lose the advantages of click once deployment. Still it look like an impressive and useful library.
 
 
Enjoy!
 
Maurice de Beijer
 
Posted by Maurice | with no comments
Filed under:
Ron Jacobs interviewed Bill McCarthy recently about the eternal debate of C# versus VB. Bill is a respected Visual Basic MVP and has some interesting points to share.
 
 
Enjoy!
 
Maurice de Beijer
 
Posted by Maurice | 1 comment(s)
Filed under:
Technorati Profile
Posted by Maurice | with no comments
Office 2007 has a much nicer document format. The new format is XML based, no longer some proprietary binary format, and unlike the previous XML format introduced in Office 2003 this is the real deal not a format that only supports a subset of the functionality.
 
But the new format, DOCX for Word, itself is actually a ZIP file containing a whole range of other documents. These other documents are XML, actually there can be other file types as well but the XML files is what it is all about. So ZIP and XML means we should have an easy time of opening and reading these file from our .NET programs, after all both are pretty standard and have plenty of tools and libraries available. But life is even better than that. Microsoft has decided to add native support for reading and writing these files in .NET, in the System.IO.Packaging package to be exact. Take a look at the following code for an example:
 
Imports System.IO.Packaging
Imports System.Xml
 
Module Module1
    Sub Main()
        Using doc As Package = Package.Open("C:\Documents and Settings\Maurice\My Documents\Microsoft\Demos\1. XML File format\test.docx")
            Dim part As PackagePart
            Console.WriteLine("===== Document parts. =====")
 
            ForEach part In doc.GetParts()
                Console.WriteLine(part.Uri)
            Next
            Console.WriteLine("Press any key to continue and show the contents.")
            Console.ReadKey()
 
            Console.WriteLine("===== /word/document.xml contents. =====")
            part = doc.GetPart(New Uri("/word/document.xml", UriKind.RelativeOrAbsolute))
            Using reader As XmlReader = XmlReader.Create(part.GetStream())
                While reader.Read()
                    Console.WriteLine(reader.ReadString())
                EndWhile
 
            EndUsing
            Console.WriteLine("Press any key to end.")
            Console.ReadKey()
        EndUsing
    EndSub
EndModule
 
The only slightly confusing thing is trying to import the System.IO.Packaging namespace. You would tend to try to set a reference to a System.IO.Packaging.dll, either from the GAC or file system, but it just isn’t there. Instead you need to add a reference to WindowsBase.dll. It should be in the list of .NET assemblies but if not you can find it in the "C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0" folder.
 
Enjoy!
 
 
Maurice de Beijer
 
Posted by Maurice | 2 comment(s)
Filed under: , ,
A few weeks ago I mentioned the fact that I would like to see the Optimize Namespace References refactor sort the remaining namespaces. Well it turns out you can and Mark Miller just set me straight. All you need to do it go to the DevExpress/Options menu, select Editor/Refactoring and you actually have a choice of sort options to use. Great, switched that on right away. Guess that should be a hint to go through the DevExpress/Options menu and see what other gems they have hidden away there.
 
BTW Mark just became a C# MVP, congratulations and well deserved if you ask me!
 
Enjoy!
 
Maurice de Beijer
 
Posted by Maurice | with no comments
Filed under:
I have been receiving this error recently with a web site I was developing. Its rather weird because I am not using it nor had I any reference to System.EnterpriseServices or anything else that might have. In fact the web site was new so didn’t have much of a reference to anything except the default assemblies. Well a little searching turned up that the there was a reference to the System.EnterpriseServices assembly in the web.config located in the "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG" folder.
 
How it got there? I can only assume it’s the result of recently installing the Microsoft Enterprise Library. Now that was about a weeks ago but its quite possible that I didn’t do any other ASP.NET development since. Whatever the cause was, if you receive the same error that is one thing you might want to check.
 
Enjoy!
Maurice de Beijer
 
Posted by Maurice | 10 comment(s)
Filed under:
More Posts Next page »