WCSF: Add View (with Presenter) fix
March 13th, 2007
WARNING: This post is obsolete. Please visit the definite fix post here
If you are using Web Client Software factory in your projects, you probably got an annoying exception that randomly occurs when using the Add View (with Presenter) recipe. The exception is shown below:
Microsoft.Practices.RecipeFramework.ValueProviderException: An exception occurred during the binding of reference or execution of recipe CreateView. Error was: An error happened while calling the value provider or evaluating the default value of argument ModuleInfos..
You can remove the reference to this recipe through the Guidance Package Manager. —> System.ArgumentException: Value Microsoft.Practices.CompositeWeb.Configuration.DependantModuleInfo[] specified for argument ModuleInfos can’t be converted to the argument type Microsoft.Practices.CompositeWeb.Configuration.DependantModuleInfo[].
at Microsoft.Practices.RecipeFramework.Services.DictionaryService.SetValue(Object key, Object value)
After spending a lot of time debugging to find out what the problem was, we (thanks to Matias Woloski for helping me) found a weird behavior. When the Add View (with Presenter) recipe is being executed, .NET is sort of mixing the loaded assemblies available for the guidance package, with those available to the destination solution; in particular Microsoft.Practices.CompositeWeb.dll is being referenced two times during the recipe runtime: one without a public token, because it’s linked directly to the WebClientFactoryPackage in the solution, and one with a public token, which is the one that comes with the Library, and the one that the destination solution references.
Then, depending of the destination solution, it was randomly (well, not random, but without a visible way to know exactly when) trying to receive an argument of a class type that belongs to either of those assemblies (for us it appear to be the same class, but this obviously not the case for .NET). Because this configuration is in XML, and read at runtime, it uses reflection to create an instance of this class).
<Argument Name=”ModuleInfos” Type=”Microsoft.Practices.CompositeWeb.Configuration.DependantModuleInfo[], Microsoft.Practices.CompositeWeb”> <!– some configuration –></Argument>
What we should do to avoid this conflict, is remove the chance to let .NET randomly decide which assembly to use, and instead pin it to the assembly we know it’s there from the point of view of the Guidance Package: the one with a null public token.
All the technical stuff said, the way to solve this problem is:
Open the CreateWebClientFactoryView.xml file located at “%INSTALL_DIR%\WCSF Guidance Package\Recipes”.
Where it says:
Type=“Microsoft.Practices.CompositeWeb.Configuration.DependantModuleInfo[], Microsoft.Practices.CompositeWeb”
Replace it with:
Type=“Microsoft.Practices.CompositeWeb.Configuration.DependantModuleInfo[], Microsoft.Practices.CompositeWeb, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”
And where it says:
Type=“Microsoft.Practices.CompositeWeb.Configuration.DependantModuleInfo, Microsoft.Practices.CompositeWeb”
Replace it with:
Type=“Microsoft.Practices.CompositeWeb.Configuration.DependantModuleInfo, Microsoft.Practices.CompositeWeb, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”
Now (re)open Visual Studio, and you should now be able to work with this annoying bug.
Here is a modifed version of the file for your convenience: CreateWebClientFactoryView.xml
SCSF: Add Smart Web Reference and still access the Web Service’s authorization credentials
March 6th, 2007
When using the Add Smart Web Reference recipe from the Smart Client Software Factory, it generates a proxy that wraps the original VS generated proxy.
Let’s assume we have a web service named MyService. When you add a Smart Web Reference, Visual Studio will automatically add a Web Reference to the service (a class named MyService that inherits from SoapHttpClientProtocol), and a class named MyServiceProxy, which is the class that wraps the previous one. It will also generate a bunch of other classes and interfaces to support the command queue infrastructure.
We, as SCSF users/developers, are used to add the services to WorkItem.Services collection to be consumed later in this or other modules, in the following way:
As you already know by now, you could get a reference to IMyServiceProxy, or even MyServiceProxy, but this wrapper does not expose any properties the original proxy had, so you can’t access the credentials for a service that do requiere some, if you don’t have a reference to the original web service proxy instance. MyServiceProxy does not inherit from SoapHttpClientProtocol so you don’t have access to any member of the original Visual Studio generated proxy class for the web service.
What the previous example does is call the default constructor on MyServiceProxy, which creates a new instance of MyService to wrap. Luckily, the wrapper has an overloaded constructor that receives an instance of the service it wraps, but the problem is we cannot specify the ObjectBuilder which instance we want to use with the previous code.
What we should do instead is the following:
Makes perfect sense, right? Sometimes we are so used to add web services to a workitem the other way, that when we add authentication to them we don’t see the solution at first sight.
Side comment: As many of you’d probably know, the p&p team is working on something called Disconnected Service Agent that will replace the Add Smart Web Reference recipe in the next release of SCSF, with lots of added functionality as it also uses the Offline Application Block.