Visual Basic support

Mar 12, 2008 at 3:38 AM
Does anyone know the number of files (templates) that would have to be converted to VB.Net in order to use the WSSF to generate VB based web services (not just say convert for your needs)? Requirements change, so it all should be converted and VB code generated for all scenarios.

There is a thread that says one of the .tt files to use as a VB sample for conversion exist, this file is in a VB directory, but it is still C#. Is there anyone who has completed the conversion or would like to help with the conversion?

Why do the VB developers have to do conversion on a PnP factory in order to use it anyway? I thought the VB versus C# war was over, but apparently one got left behind. This is causing developers that would like to use the WSSF extra work and in many cases, not being able to use the factory for lack of time to do the conversion. Microsoft, please provide solutions for VB (the original RAD environment) with equal PnP solutions.

Since C# and VB.Net are the most commonly used, why not provide both? Especially if it is so easy to convert the templates.
Mar 12, 2008 at 12:23 PM
There are 6 tt files for WCF and 7 for ASMX including Service Contracts and Data Contracts. THen you can also convert the VS templates in order to generate VB projects instead of C# projects.
Regarding the included VB text template file, you will notice that the generated code is in VB but you can have the rest of the support script in C# (or convert it as well to VB if you wish but that won't be viswible to the consumer of the factory).
On the other hand, my guess is that the reason why it was not included the VB templates is only for time constrain reasons and has nothing to do with a preference of one language over the other.
Mar 12, 2008 at 1:55 PM
charlyfriend,

The problem is, many of us have only just discovered service factories and don't have the domain knowledge to even know where to begin to do MS's grunt work.

Can you please specify exactly which files need to be converted in order to generate vb projects and contracts?



Finally, allow me to ask the question of if MS and it's teams have no intentions of supporting both languages, why do they bother releasing products with more than one? It becomes a huge pain when you encounter clients/employers who insist that you have to write in one syntax when you can't find support for it. MS should have scrapped either C# or VB.net years ago because all it does it cause problems.
Mar 13, 2008 at 4:23 AM
charlyfriend

I've been lamenting the lack of out-of-the-box VB code generation for months now. The WCSF team managed to ship with recipes for both languages. I really don't see why WSSF team couldn't have done the same. I find it hard to believe that it was left out only due to time constraints - if it is really only those 13 template files in total that need to be modified and if that process is as simple as you make it out to be then what's the hold up?
Mar 13, 2008 at 2:09 PM
I can't speak for the team regarding the rationale for this but I will post here the detailed steps to do this conversion with code samples as well in order to hopefully aleviate your pain.

Regards,
CF
Mar 13, 2008 at 8:52 PM
Charlyfriend,

I would greatly appreciate this as I am eager to make use of Service factories for the work I'm doing with WCF. Hopefully the conversion will be relatively quick?

Thanks
Mar 14, 2008 at 6:40 PM
Edited Mar 18, 2008 at 1:31 PM
It shouldn't take so long since it's not rocket science but there some steps to follow for each template you want to translate.
You can use the source code of the WSSF:ME and execute the steps below.
Here are the steps to translate the DataContract.tt text template to VB:

1) Create a new text template file (a simple text file with .tt extension) and add it to a folder like (i.e a DataContract.tt) "\Data Contract DSL\Dsl\TextTemplates\WCF\VB\DataContract.tt"
2) Check its property values are these: Build Action: None, Copy to Output Directory: Copy if newer, Custom Tool: <empty value>
3) Copy the content of DataContractr.tt file located under the same folder tree of CS (in this case, "\Data Contract DSL\Dsl\TextTemplates\WCF\CS\DataContract.tt").
4) Translate to VB all the code that is outside the <# and #> and parts of the support private implemetnation code (see complete file translation at the bottom)
5) Go to Utility class in "Microsoft.Practices.Modeling.CodeGeneration" project and change the code provider to VB (notice that this is just a quick solution in order to avoid creating all the VB methods overloads in that class).
private static CodeDomProvider csProvider = new VBCodeProvider(); //CSharpCodeProvider();
6) Open file "DataContractLink.cs located in project "Microsoft.Practices.ServiceFactory.Extenders.DataContract.Wcf" and insert the following attribute under the same attribute for CSharp (notice that you can also do the same in the "FaultContractLink.cs" because it uses the same tt file):
[TextTemplate("TextTemplates\\WCF\\VB\\DataContract.tt", TextTemplateTargetLanguage.VB)]
7) Rebuild Solution all and test it.

The final template for DataContract.tt file will be this:

<#@ Template Debug="true" Language="C#" Inherits="Microsoft.Practices.Modeling.CodeGeneration.Strategies.TextTemplating.ModelingTextTransformation" #>
<#@ Import Namespace="System" #>
<#@ Import Namespace="System.Collections.Generic" #>
<#@ Import Namespace="System.Collections.ObjectModel" #>
<#@ Import Namespace="System.Xml.Serialization" #>
<#@ Import Namespace="System.Runtime.Serialization" #>
<#@ Import Namespace="Microsoft.Practices.ServiceFactory.DataContracts" #>
<#@ Import Namespace="Microsoft.Practices.ServiceFactory.Extenders.DataContract.Wcf" #>
<#@ Import Namespace="Microsoft.VisualStudio.Modeling" #>
<#@ ModelInjector processor="ModelInjectorDirectiveProcessor" #>
'------------------------------------------------------------------------------
' <auto-generated>
'     This code was generated by a tool.
'
'     Changes to this file may cause incorrect behavior and will be lost if
'     the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------
 
Imports System*
Imports WcfSerialization = System.Runtime.Serialization*
 
Namespace <#=CurrentExtender.ArtifactLink.Namespace#>
	''' <summary>
	''' Data Contract Class - <#= CurrentElement.Name #>
	''' </summary>
	<WcfSerialization.DataContract(Namespace := "<#= CurrentElement.Namespace #>", Name := "<#= CurrentElement.Name #>")> _ <#= BuildKnownTypeAttributes() #>
	Partial Public Class <#= CurrentElement.Name #> 
<# 
	foreach(DataMember member in CurrentElement.DataMembers)
	{ 	
		PopulateMemberVars(member);
		if( memberType != null )
		{				
	#>		Private <#= memberPrivateName #> As <#= memberType #>
<#
		} // closes if  
	} // closes foreach
 
	foreach(DataMember member in CurrentElement.DataMembers)
	{ 	
		PopulateMemberVars(member);
		if( memberType != null )
		{
#>
		<#= memberAttribute #>
		Public Property <#= memberName #>() As <#= memberType #>
			Get
				Return <#= memberPrivateName #>
			End Get
			Set(ByVal value As <#= memberType #>)
				<#= memberPrivateName #> = value
			End Set
		End Property
<#
		} // closes if
    } // closes foreach
#>
	End Class
End Namespace
 
<#+
private	string memberType = null;
private	string memberName = null; 
private	string memberPrivateName = null; 
private string memberAttribute = null;
 
private void PopulateMemberVars(DataMember member)
{
	string dataElementAttrInfo = "";
	
	if (member is PrimitiveDataType)
	{
		PrimitiveDataType pde = (PrimitiveDataType)member;
		
		if(pde.CollectionType == null)
		{
			memberType = Utility.GetCSharpTypeOutput(pde.Type, pde.IsNullable);
		}
		else
		{
			if(pde.IsNullable && Utility.CanBeNullable(pde.Type))
			{
				memberType = Utility.GetCSharpTypeDeclaration(pde.CollectionType, Utility.GetCSharpTypeOutput(pde.Type, pde.IsNullable));
			}
			else
			{
				memberType = Utility.GetCSharpTypeDeclaration(pde.CollectionType, pde.Type);
			}
		}
	}
	else if (member is ModelElementReference)
	{
		ModelElementReference dcde = (ModelElementReference)member;		
		memberType = Utility.GetCSharpTypeDeclaration(dcde.CollectionType, dcde.Type);
	}									
 
    WCFDataElement dateElementInfo = GetObjectExtender<WCFDataElement>(member);
    if(dateElementInfo != null && member.IsDataMember)
    {
		dataElementAttrInfo = ", IsRequired := " + dateElementInfo.IsRequired.ToString().ToLowerInvariant() + ", Order := " + dateElementInfo.Order.ToString();
    }
 
	memberName = member.Name;
	memberPrivateName = Utility.ToCamelCase(memberName.ToLowerInvariant());  
	memberAttribute = member.IsDataMember ? "\r\n\t\t<WcfSerialization.DataMember(Name := \"" + memberName + "\"" + dataElementAttrInfo + ")> _" : String.Empty;								
}
 
private string BuildKnownTypeAttributes()
{	
	string attribute = String.Empty;
	
	foreach(DataMember member in CurrentElement.DataMembers)
	{
		ModelElementReference reference = member as ModelElementReference;
		if (reference != null &&
			reference.IsDataMember)
		{
			Contract found = CurrentElement.DataContractModel.Contracts.Find(delegate(Contract contract)
			{
				return contract.Name == reference.Type;
			});
			if (found != null && found is DataContractEnum)
			{
				attribute += string.Format("{0}	<WcfSerialization.KnownType(GetType({1}))> _", Environment.NewLine, reference.Type);
			}
		}
	}
	
	return attribute;
}
#>

Following these steps you can do the same for the service contract templates.
NOTE: These steps show how to update the text templates for code generation. If you want to update also the solution templates for WCF/ASMX projects, you will find some hints in Exercise #2 of the Extensibility Hands-on lab and ideas regarding text templates in Exercise #4.
Mar 17, 2008 at 3:21 PM
@charlyfriend

Thanks for that. I'd like to take it a step further and create a C# Model project template (basically just rename the existing one) and a VB Model project template, each using the corresponding language's code generation. How do I go about doing that?
Mar 18, 2008 at 11:36 AM
Hi all,
My aim is to modify the WSSF to allow both C# and VB code generation. In this light, I'd like to provide the user the option of choosing which language to generate code in, similar to the WCSF. Thus I was thinking of have too Model Project templates - one called Model Project (C#) and the other Model Project (Visual Basic). Is there an easier way to do this? Providing a drop down in the model project properties, for instance, allowing the user to choose a code-gen language? I need to get this up and running pretty urgently, so I'd appreciate help from any sources.

On a related issue, following the guidelines provided by charlyfriend above, I've create vb templates for the datacontracts, service contracts, message contracts and faultcontracts (wcf and asmx). The DatacontractDSL project builds ok, but when I try to rebuild the whole solution, I get the following error in the DataContract.tt (WCF, VB) file which is basically a copy and paste of charlyfriend's code above:

Error 1 A processor named 'ModelInjectorDirectiveProcessor' could not be found for the directive named 'ModelInjector'. The transformation will not be run. The following Exception was thrown:
System.IO.FileNotFoundException: Failed to resolve type for directive processor ModelInjectorDirectiveProcessor.
at Microsoft.VisualStudio.TextTemplating.VSHost.TextTemplatingService.ResolveDirectiveProcessor(String processorName)
at Microsoft.VisualStudio.TextTemplating.Engine.ProcessCustomDirectives(ITextTemplatingEngineHost host, TemplateProcessingSession session, List`1 directivesToBeProcessed) C:\WssfSrc\Data Contract DSL\Dsl\TextTemplates\WCF\VB\DataContract.tt 10 4 DataContractDsl

It's been driving me nuts. None of the other template files generates this error and yet they all refer to the ModelInjectorDirectiveProcessor in exactly the same manner. Furthermore, the error only comes up when I rebuild the solution - it doesn't occur when I'm building the DataContractDsl project in isolation. Ideas anyone?
Thanks,


Mar 18, 2008 at 12:14 PM
I'd just like to add to that last post wherein i described the error I'm getting. Following the debug output, it seems the error occurs due to this command:

C:\Program Files\Microsoft Visual Studio 2008 SDK\VisualStudioIntegration\Tools\bin\ctc.exe "CtcComponents\Commands.ctc" "obj\Debug\Commands.cto" /I"C:\Program Files\Microsoft Visual Studio 2008 SDK\VisualStudioIntegration\Common\Inc" /I"C:\Program Files\Microsoft Visual Studio 2008 SDK\VisualStudioIntegration\Common\inc" /I"C:\Program Files\Microsoft Visual Studio 2008 SDK\VisualStudioIntegration\Common\inc\office10"
CTC : fatal error CTC2013: Can't start preprocessor (2)
CTC : fatal error CTC2013: Can't start preprocessor (2)
Done building project "DataContractDslPackage.csproj" -- FAILED.

I noticed that obj\Debug\Commands.cto does not exist and is not created anywhere during the build process. Other than that, I'm clueless.
Mar 18, 2008 at 1:45 PM
Check that you set the Custom Tool property in the DataContract.tt file to an empty value (not the defautl value of "TextTemplatingFileGenerator"). like described in step #2 of my last post above.
Regardin your question about creating a new project template for VB, you may get that information from Exercise #1 and #2 of the Extensibility Hands-on lab. As you will notice, these samples are based on C# projects but you can easily update them to VB and your own template structure.
Mar 18, 2008 at 4:02 PM

charlyfriend wrote:
Check that you set the Custom Tool property in the DataContract.tt file to an empty value (not the defautl value of "TextTemplatingFileGenerator"). like described in step #2 of my last post above.
Regardin your question about creating a new project template for VB, you may get that information from Exercise #1 and #2 of the Extensibility Hands-on lab. As you will notice, these samples are based on C# projects but you can easily update them to VB and your own template structure.


The Custom Tool property is empty (i.e "").
Mar 19, 2008 at 9:11 AM
In this case, then it should be the Known issue in DSL Tool so try installing VC++ and that should fix this issue.
May 28, 2008 at 1:13 AM
@charlyfriend, thanks for those very helpful tips.
I've started the conversion but I am starting to realise that there are other details that affect the conversion that you have not mentioned.
For example the XsdMessageContract.tt and MessageContract.tt are utilising methods from CommonTextTransformation.tt that output code that would only work in C# (for example the PrintAttributeArguments method)
I was wondering if anyone that's gone through a successful conversion could provide additional tips/source code on what they found was affected.

TIA!
May 28, 2008 at 11:56 AM
I know that some people are finishing working on VB code gen for WSSF (all templates and any other details) and they will publish the code any time soon in codeplex and of course we will publish this information in this wiki.
Stay tunned!

PS: PrintAttributeArguments will return C# formatted code but is should not be hard to update it for VB.
May 29, 2008 at 11:35 PM
Correct me if I am wrong, but going through the source of WSSF it becomes apparent that the Template (*.tt) file to use is determined by examining the type of target project. This means that in order for me to get code to be generated in VB, I must update the solution templates to use VB projects.
May 30, 2008 at 12:11 AM
You are right if you want to use (update) the buil-in templates for WCF and ASMX. Otherwise you may just update the ".tt" files and add your own VB projects to the sln.
Jun 13, 2008 at 1:16 AM

I've made great headway in the conversion, but I've run into one problem that I think is very interesting. The crux of the problem stems from the fact that VB doesnt support use of the "partial" keyword with interfaces.
This appears within the ServiceImplementation.tt template file and is generated into the ServiceImplementation project.
I am not a VB expert and I am not sure how to create a generic work around to this issue.

Inheriting from and extending the generated interface does not seem to properly solve this. Namely, the declarations for both the abstract "Base" class that implements the generated interface and the concrete class that inherits from the base are also generated.  As such there isnt too much room for extension here, given this particular architecture without the ability to directly extend the interface.

Jun 19, 2008 at 11:58 AM
I am facing the same issue.How to convert ServiceContract.tt file or what is a other way to achieve partial Interface functionality in VB.Net.
Please help us on the same its really urgent !!!