I have a WCF web service that I am working on and I built it and was delighted to find that I could use complex types in it. I added some and then realized that they were still not useable as those types on the client end. This is an internal web service so these types are known on both sides. Anyway, that's not the problem, as I took the complex types out, but I think it may have left some residual issues.
When I then changed my additions to all be base types (string, date, int, etc) then added the web service to the client project, I got a "[enumtype] is already defined" error. It occurred in the reference.cs file so I opened it up. Sure enough there were duplicate enums. Plus there were a bunch of helper (serializing) functions. The duplicate enum was from code that had been in there before I picked this web service up to work on. It had not caused an issue previously.
I opened up the reference.cs for the previous (successful) service reference. It did not have the duplicates or functions and also I noticed a difference between the entries that were in there. The reference.cs that was failing to compile had this additional attribute in several places:
[System.ServiceModel.XmlSerializerFormatAttribute()]
I also see that my new failed code was using string[] and the old was using ArrayOfString. I did not intentionally change this, but must have somehow set something differently in the process.
Does anyone have a few clues?
Thanks!
Have you tried deleting the service reference from the project and re-adding it? You may have to manually remove some (or all) of the serviceModel contents too. If that is the only Service Reference then definitely remove the serviceModel element contents too.
Once its all gone, re-add the Service Reference. If you're still having problems then it may be that the service metadata is generating invalid WSDL causing the duplicate enums.
UPDATE: Just for verifying the WSDL is not valid, you could try creating the service proxy manually using the SvcUtil command line utility. It generates your proxy code like Visual Studio does and may give you more troubleshooting info.
After a lot of experimentation this is what I found out:
Our web service up to this point was using the Request / Response classes for input and output. There were required in 1.0, and were a carry over from that. I attempted to create a simple entry point that sent in a string and returned a string. This compiled ok, but:
Although you can use regular types for input and output, if you are using Request / Response types exchanges for other entry points, then you cannot.
Mixed method of request / response and regular types will compile, but it will not successfully import (at least into Visual Studio 2008). What ends up being created seems to be an attempt to create input and output classes for all of the functions to translate them to their complex types, along with the Request / Response types which creates duplicate entries and will not compile.
This then also means that you cannot send in a request object and return a string (which is how I found out that this was not allowed) – this generated an error in the unit test, which started me down this path.
So if you have a request / response web service, all functions must follow that protocol.
Related
There are a bunch of questions regarding global error handlers and such but none of those address what I need.
Is there any way to add a behavior that will attach to every endpoint or service through .config?
*Specifically what I want to do is add a logger that will capture and log every SOAP request/response. But I would prefer that behavior to be automatically added to every service I have instead of having to manually add it to each.
I looked into behavior extensions and thought that would be the solution but no, you have to add the behavior to every service.*
You may be able to use the <commonBehaviors> section of your machine.config file to define a behavior which would be applied to all services in your machine. Notice that updating the machine.config is really like using a bazooka to solve your problem (and in many scenarios the group policy may forbid you from doing that), so it may not work for all scenarios. You'll also need to make sure that the behavior extension is registered (also in machine.config), and that whatever application you're using with WCF has access to the assembly referenced in the extension (possibly via GAC).
Another alternative would be to use a common library for creating the service hosts (either directly for self-hosted services or via a service host factory for webhosted services), and use that library (which would in turn add the inspector).
Its always good to have a message inspector to get rid of this kind of problem. Message Inspector is an implementation of WCF extension which works nicely to track every incoming request(s) and outgoing response(s) for your service, even if its fails in Message Validation it has an option to trap and work accordingly. More precisely the message inspector can configure using configuration files without making changes in your existing service.
More details about your Message inspector and its implementation can be found Here
Hope this helps !!
Happy Coding :)
I'm calling a WCF operation and was running into the classic circular reference issue where my primary object (Persons) included a reference to another object (Reminders) which I need to contain a reference back to Persons. I fixed this using ReferencePreservingDataContractFormatAttribute (documented well online if you Bing it). And the fix works great for calling my service from my website project. When I attempt to call it from WCFTestClient, however, I get a Stackoverflow Exception. If I take off my .Include("Person") in my service operation then it works just fine in both. Does anyone have any ideas why this might happen? I compared the serviceModel sections of the config files to be sure there were no significant differences. Thanks for any ideas you can provide.
Keeping in mind that it works from your website project but not from your test client there are 3 possibilities:
You have not updated the service reference in your test client (9 times out of 10 that is the problem)
There is some other bug in your test client
The call from your test client uses different parameters and is therefore returning different data.
I'm having very strange issue with my WCF Service Proxy client generated by "svcutil.exe" . My WCF Service works very fine if I don't have a function that returns DataTable. As soon as I add a method that returns a DataTable the client generated by svcutil.exe is behaving very strangely. The Interface is no longer found and client is not able to call the service. But if I add as a Service Reference its working very smoothly. I know its not a good habit to use DataTable as a return type but I need to. I cannot use the Service Reference :-( Any idea why its behaving or what I'm missing!!!
Have a look at the DataTableSurrogate class. It is used by the SyncFramework for serialization and really easy to use.
MSDN DataTableSurrogate
You shouldn't really serialize datasets, instead you should use datamodels and keep anything to do with datasets, tables, readers etc on your backend & in the business layer.
But.. if you want to do so you need to add the following "include" in svcutil, which is causing your issue. (Tells to reuse the types defined in System.Data.dll and not generate them in the proxy)
/r:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Data.dll
I have been consuming a service for some time in development, and have been updating my service reference almost daily with no problems. Collection types have been set to generate as System.Collections.Generic.List in the Advanced options.
However, for no apparent reason, now when I update the Service Reference, it's generating Array types for all my collections! It is still configured to generate the List type, why is it all of a sudden going back to the Array type?? I'm using VS 2010..
Here's the answer. A code change on the service was as follows: a class was marked as Abstract, and used in another class as List<AbstractClass>. Generating the service proxy on the client machine (EVEN WITH SVCUTIL.EXE) was forcing all of my list collections to be generated as Class[] instead of List<Class>. Removing the Abstract from the Class fixed everything and I am able to generate my service proxy from within VS and from the command prompt without issue.
I have an existing asp.net application that talks to load balanced wcf services (iis hosted, in app pool running under account configured as servicePrincipalName, etc.). The wcf services return a few custom faults, all defined with FaultContract(typeof(x), ProtectionLevel = ProtectionLevel.None) -- these services are not exposed to the public. The client uses the 'service reference' generated classes to access the services.
This has worked fine but now, with the latest code base, we are getting "The primary signature must be encrypted." exceptions on the client when the service returns one of these faults. The service code and configuration is unchanged (at least the legacy parts that generate the faults). The client side service reference generated code appears the most changed (it often gets removed and recreated).
The security configuration is unchanged for over a year. All the updates are pretty current. We've tested this in three environments and as soon as we deploy the new code base, the faults start generating exceptions. Seems like it has to be in the generated classes but they are generated by Visual Studio so it is very perplexing.
Does this sound familiar to anyone? Any suggestions?
Update: Removing the ProtectionLevel attribute and allowing it to default makes the problem 'go away', but I am curious why specifying None causes it to fail. Perhaps it conflicts with the default level of the operation contract or service contract, but those values have not changed in the past year so that doesn't explain why what had worked now doesn't.
Update: For what it is worth, this change in code gen happened between 2.0.50727.3053 and 2.0.50727.3082 (according to the runtime-version comment in the generated code).
I haven't experienced this problem myself, but my questionn is: why on earth do you specify a "ProtectionLevel=None" in your fault contract? Any particular reason for that?
If not, I'd strongly recommend not specifying that at all - the default is ProtectionLevel=EncryptAndSign and that's usually your best bet all around. Try it, unless you have a very strong and explicit reason against it.
Marc