3

Although I love the idea of F# type providers my first serious attempt to use them crashed hard.

I was going to connect to a service (WCF) with WsdlService<"http://someurl/some.svc?wsdl">

It fails epicly with:

The type provider 'Microsoft.FSharp.Data.TypeProviders.DesignTime.DataProviders' reported an error: tmp6E6C.cs(9409,26): error CS0644: 'System.ComponentModel.PropertyChangedEventHandler' cannot derive from special class 'System.MulticastDelegate' c:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll: (Location of symbol related to previous error)

and a lot of other warnings which probably are not relevant:

tmp6E6C.cs(290,28): warning CS0436: The type 'System.Data.DataRowState' in 'c:\Users\someuser\AppData\Local\Temp\tmp6E6C.cs' conflicts with the imported type 'System.Data.DataRowState' in 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dll'. Using the type defined in 'c:\Users\someuser\AppData\Local\Temp\tmp6E6C.cs'. tmp6E6C.cs(9427,17): (Location of symbol related to previous warning)

Is this a known feature ;-) or am I using it wrong?

I unfortunately cannot post the WSDL, and its rather large with a lot of types in it so I must admit I am somewhat lazy and have not trimmed it down either. OTOH if I did know what part of the WSDL was offending or creating this error I would of course have put it here.

To change the WSDL is not an option either, so I am mainly interested in knowing why F# WSDL type providers can not handle this (WCF) WSDL, or what I am doing wrong.

It works excellent when consumed by C# and svcutil.exe from VS2010.

I have tried all the params to the WsdlTypeProvider and they do give the same result (except ForceUpdate of course). Should I be consuming these services in another way with F#?

=============================================================================== Added info (since I am new and didnt want to answer. dont ask why :):

Thank you all answering/commenting.

I did go partly this way may self (manually using svcutil). As I tried to say above, I tried to use svcutil by hand, and it fails when compiling the generated C# code (in a library besides the F#).

That is, I did the following:

1) Create the contract by setting up a reference in VS 2010 GUI. This works as expected

2) Try to create it by using svcutil from cmd-line. Then the compile of that file fails with same error.

As it seems from my point of view what happens in svcutil from cmd-line and what happens when using svcutil (or what is used) from the GUI adding the same service does not generate the code with the same parameters. I guess this is partly controlled by the fact that what I try to consume is a WCF service and not a "clean" WSDL/webservice, and the type provider assumes that I try to use a "clean" webservice.

I did not manage to find any params for svcutil takeing care of this, or any possible combinations of params, not saying that I did try all permutations of combinations, but trying the ones probable based upon (trying to) deep reading the documentation of svcutil (and I am not entirley new at using it from cmd-line).

So far I have concluded that it is some "missing" params to svcutil which causes this, and that the F# type provider is not at fault. I would still very much like to solve it somehow, still using F# type providers, but a fallback is to generate the code by GUI in C# and then reference that part of code in F# again. That is not the elegant solution I was trying to achieve, since I do have a lot of services and I would very much like to create such a nice way of prototyping and testing those services.

Another fallback would of course also give up the whole F# part and just go with some unit-testing etc., but that again is defating the purpose of sneaking in F# and learning at same time ;-)

Helge Rene Urholm
  • 1,190
  • 6
  • 16
  • "It works excellent when consumed by C# and svcutil.exe from VS2010". This is interesting. I spent a couple of days trying to use type providers with real web services (including WSDL) and failed to get a single thing to work beyond the F# samples. So I'm interested to hear that this might be an F#-specific issue and not a general .NET one... – J D Oct 19 '12 at 10:57
  • I think positively that this is not a .net issue (it works when using svcutil so ...), but rather an issue in the WsdlProvider or the actual service being some WCF doing some advanced or sneaky use of WSDL not taken into account in the provider implementation. Of course it could be me doing something wrong. Or a combination of all. "Good" to hear other have had issues using it. What errors did you get when trying to use WsdlProviders? Was it also WCF services or otherwise created services? – Helge Rene Urholm Oct 19 '12 at 11:05
  • It works excellent when added a reference in VS2010 GUI. It generates kind of the same fault if generating the file from the servicedescription to a CS-file apperently, if using svcutil from cmd-line. – Helge Rene Urholm Oct 19 '12 at 13:05
  • It's really hard to say "this works in C# but fails in F#" without seeing the exact C# and exact F# code in question. If there's any way you can post a small subset of the code in both languages that demonstrates the issue, that would be very helpful. Saying the code is the same in two different languages is a pretty long stretch. – Onorio Catenacci Oct 19 '12 at 15:05
  • What's preventing you from posting the WSDL? Security by obscurity? – Robert Jeppesen Oct 22 '12 at 11:56
  • External consultant posting internal WSDL on Internet is unfortunately somewhat out of scope of what may be allowed. As has been established the case is not related to f#, c#, or WSDL, I think, but rather on the differences between how the WSDL is handled in different cases. – Helge Rene Urholm Oct 22 '12 at 13:50
  • @OnorioCatenacci if you do not understand the case at hand, please do rephrain for answering. The f# wsdl provider is based upon creating c# code in the background and reusing that lib created. as such it is in fact the same code created even in same language. – Helge Rene Urholm Oct 22 '12 at 13:55
  • @user1758475 I didn't answer--I made a commment. From the scant description of the issue you initially gave (which I was commenting upon) it seemed possible that you were making some unjustified assumptions. – Onorio Catenacci Oct 22 '12 at 14:19

2 Answers2

3

The WSDL type provider (and a few others) are using SvcUtil in the background to do the heavy lifting. If you open ProcExp of taskmgr or some similar tool, you can see the SvcUtil process getting spawned after pasting the TP code into Visual Studio. With ProcExp at least, you can see the full command line with arguments which was used.

So find out exactly what SvcUtil command line was invoked by the TP for your service, and check if it works outside of the F# environment.

The fact that SvcUtil works from C#/VS 2010 is interesting. I assume if you are using F# TPs you are on VS 2012 right now. If so, the version of SvcUtil itself might be different, which could be related.

The specific error would appear to be the same as explained here, so you might have some incomplete annotations in your service code.

Community
  • 1
  • 1
latkin
  • 16,402
  • 1
  • 47
  • 62
  • I dont think that link is entirely relevant (it may be me not totally understanding the issue at hand!). Why I assume this is explained more in the addition in the original post, and in short because I are able to generate correct code when using the GUI in VS 2010 to add the services. The code generated are different in the two cases. Cmdline svcutil assumes a "clean" wsdl, but the GUI stuff "understands" that is a WCF (or whatever) and handles the PropertyChangedEventHandler differently. – Helge Rene Urholm Oct 19 '12 at 21:13
  • Both C# GUI and F# TP are using SvcUtil to generate the client side code. There are 2 variables in the use of SvcUtil - the version of SvcUtil itself, and the arguments passed to it. If it's working in VS 2010 C#, but not VS 2012 F#, then either the version of the tool is different, the arguments are different, or both. Find our what that difference is, and that should point you toward your next step of fix/workaround. I included the link to hint at why the tool may be failing - perhaps the latest version is stricter than previous versions. – latkin Oct 19 '12 at 22:06
  • I tried to use the cmdline version of svcutil from 2010. It gives the same error when compiling the C# code... It seems like it also generates the same code with 2012 cmdline. – Helge Rene Urholm Oct 20 '12 at 15:17
  • @latkin "Both C# GUI and F# TP are using SvcUtil to generate the client side code": This is not true for VS 2008, see [link](http://social.msdn.microsoft.com/Forums/en/wcf/thread/7b5222b8-3c6f-4c01-b2c3-73912158084f). I think it is also not true for VS 2010: When I add a service reference via dialog, svcutil.exe is never started in task manager. I do not know about VS 2012. – Marc Sigrist Oct 22 '12 at 09:29
  • @MarcSigrist - You are right, my earlier comment is incorrect. Thanks for pointing out my error for future readers! I guess way back, VS "add service reference" GUI did use svcutil, but since VS 2008 this is no longer the case. Now we end up with inconsistencies between the two approaches - shocking! – latkin Oct 23 '12 at 23:53
  • @MarcSigrist so it boils down to: How can I "force" svcutil to behave like ASR (add service reference)? Or if it is possible? – Helge Rene Urholm Oct 24 '12 at 12:14
  • @user1758475 Apparently, ASR applies some extra checks and other functionality internally, which are unknown to svcutil. Therefore, you cannot "force" svcutil do behave like ASR in all respects. Furthermore, even if you could, this would not help, because svcutil is accessed by the type provider internally. The only way to fix the problem would be to write your own type provider (based on what, if svcutil is not good enough?), or wait for a future, more stable version of the official WsdlService type provider (who possibly re-implements parts of ASR)... – Marc Sigrist Oct 24 '12 at 17:55
  • @MarcSigrist Too bad, when this was a serious attempt to use it. I will of course manage with generating it the ordinary way and then use that lib in F# again, but then I might as well stay in C# and write some ordinary unit tests etc... Cant say I like it! ;-) – Helge Rene Urholm Oct 24 '12 at 18:34
0

I am not able to leave this issue ...

I have now done the following:

  1. Run svcutil with plain vanilla setting: svcutil http://some.address/some/path.svc
  2. Run with some more setting: svcutil /r:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5\System.dll" /r:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5\System.Data.dll" http://some.address/some/path.svc

This does generate the follwowing differences in the C# file (it is present in 1) and not present in 2) obviously):

namespace System.ComponentModel
{
    using System;


    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
    [System.SerializableAttribute()]
    public partial class PropertyChangedEventHandler : System.MulticastDelegate
    {

        public PropertyChangedEventHandler(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : 
                base(info, context)
        {
        }
    }
}
namespace System.Data
{
    using System;
    using System.Runtime.Serialization;


    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
    [System.FlagsAttribute()]
    [System.Runtime.Serialization.DataContractAttribute(Name="DataRowState", Namespace="http://schemas.datacontract.org/2004/07/System.Data")]
    public enum DataRowState : int
    {

        [System.Runtime.Serialization.EnumMemberAttribute()]
        Detached = 1,

        [System.Runtime.Serialization.EnumMemberAttribute()]
        Unchanged = 2,

        [System.Runtime.Serialization.EnumMemberAttribute()]
        Added = 4,

        [System.Runtime.Serialization.EnumMemberAttribute()]
        Deleted = 8,

        [System.Runtime.Serialization.EnumMemberAttribute()]
        Modified = 16,
    }
}

Which again makes the file compile in 2) and is as expected otherwise.

The somewhat strange part then is: Why isnt System.dll used in F# wsdl providers when running svcutil? System.Data.dll I kind of understand, since that isnt default used when running svcutil (at least according to the documentation).

OTOH I think also that the documentations says that IF the assemblies are in the GAC it should use them. So how do I verify they are there, and/or load them to the assembly if not?

Running gacutil -i System.dll (on version 4.5 of the System.dll) gives:

Failure adding assembly to the cache: An attempt was made to load a program with an incorrect format.

Is it some 64/32 bit issue? (Im on a 64 bit windows if that does have any relevance)

Or to rephrase the problem: How do I get System.dll and System.Data.dll to part of the references when running svcutil when I cannot add the references directly through the WsdlProvider-part?

Im pretty sure it does not use System.dll since if I add the collectiontype param to wsdlprovider:

WsdlService<"http://some.url/some/path.svc", "c:\\temp\\wsdl\\some.wsdlschema", true, ".", true, true, false, false, "System.Collections.Generic.List'1">

it also complains with the following:

The type provider 'Microsoft.FSharp.Data.TypeProviders.DesignTime.DataProviders' reported an error: Error: No type could be loaded for the value System.Collections.Generic.List'1 passed to the /collectionType option. Ensure that the assembly this type belongs to is specified via the /reference option.

which should have been available directly if System.dll was referenced (I think).

Any ideas to further investigate or solve this issue?

Helge Rene Urholm
  • 1,190
  • 6
  • 16