Source code:
http://code.google.com/p/sevenupdate/source/browse/#hg/Source/SevenUpdate.Base
SevenUpdate.Base.Sui cannot be used since it does not match imported DataContract. Need to exclude this type from referenced types.
Now I tried unchecking reuse reference types and I was able to get my project to compile. but when sending a collection from the client it was never received or couldn't be deserialized on the server end.
I really need this to work. Any help would be appreciated, the fullsource code is provided by google code.
I didnt download the source and build it, but could it be that you are missing DataContract on this class? Sui class has a property of type Sua as DataMember so it will need to be serialized as well. It looks like this in your code currently
[ProtoContract, ]
[KnownType(typeof(ObservableCollection<LocaleString>))]
public class Sua
What would I need to do to reproduce this error? The first bit (about matching data-contract) sounds like WCF isn't very happy with you, which suggests you have two similar (but different) contracts "in play". If you are re-using the types from a shared library this shouldn't be a problem.
If you do end up excluding the types (and having a different model at the client and server) then it can get a bit tricker, since "mex" doesn't guarantee the positions will remain intact (and indde, they regularly change) - but you can fix this in a partial class, by using a few [ProtoPartialMember(...)] against the type (not pretty but it works).
But I stress - the main problem here seems to be WCF; if that isn't happy such that the code doesn't codegen / compile etc, then my hands are fairly tied (since it won't get as far as talking to protobuf-net).
Related
I am adding Service References to my project and choosing the "internal" access option. Out of 15 web services, 3 are being stubborn and most of the classes inside the auto-generated Reference.cs are coming in as Public (even though I am choosing "internal")
I have gone through my classes in the Web References having this issue and nothing really jumps out as a major difference between the ones having issues and the ones that are working.
Does anyone know a common cause for this issue? such as an Xml Attribute to a class that might be causing this issue or anything?
The issue is precisely that. XmlSerializer cannot serialize internal types. This limitation is briefly mentioned by Microsoft here in the section titled "Access Level for Generated Classes Setting Has No Effect".
Setting the Access level for generated classes option in the Configure
Service References dialog box to Internal or Friend may not always
work. Even though the option appears to be set in the dialog box, the
resulting support classes will be generated with an access level of
Public.
This is a known limitation of certain types, such as those serialized using the XmlSerializer.
As far as I know, there isn't really an acceptable workaround for this issue in regards to the auto-generated service references. However, DataContractSerializer is not restricted by this limitation so it can be used in other scenarios.
You'll have to take this one up with Microsoft. Assuming there hasn't already been a requested solution rejected as "Won't fix".
Consider the following Visual Studio project structure
ProjectA.csproj
AClass.cs
ProjectB.csproj
References
ProjectA
Web References
AWebService
AWebService.csproj
References
ProjectA
ReturnAClassViaWebService.asmx
The issue occurs when ProjectB adds the web reference to AWebService and automatically generates all the proxy code for accessing AWebService including a new implementation of AClass. Since all of our other code needs to use the AClass defined in ProjectA, we're forced to convert the AWebService.AClass returned from the service into something we can use.
We're currently considering two solutions, neither of which are ideal.
Manually editing the generated Reference.cs to remove new definitions of AClass
Serializing AWebService.AClass to a stream then deserializing to ProjectA.AClass
Does anyone have any better solutions? This seems like something common enough for other developers to have experienced it.
Ideally we would like to have the proxy code generated in ProjectB to reference ProjectA.AClass rather than generating a whole new implementation.
Our environment is VS 2008 using .NET 2.0.
I have had the same problem that you are describing and I have tried both of the options you specify without being entirely happy about either of them.
The reason we both have this issue is at least partly because the shared-library-between-consumer-and-provider-of-a-web-service-solution is in violation of accepted patterns and practices for web service design. On the consumer side, it should be sufficient to know the interface published in the WSDL.
Still, if you are prepared to accept a tight coupling between your web service provider and web service consumer and you know for certain that your current client will never be replaced by a different client (which might not be capable of referencing the shared library), then I understand why the proposed solution seems like a neat way to structure your app. IMPORTANT NOTE: Can we really honestly answer yes to both of these questions? Probably not.
To recap:
The issue appears when you have classes (e.g. a strongly typed dataset) defined in some sort of shared library (used on both client and server).
Some of your shared classes are used in the interface defined by your web service.
When the web reference is added there are proxy classes defined (for your shared classes) within the web reference namespace.
Due to the different namespaces the proxy class and its actual counterpart in the shared library are incompatible.
Here are four solutions that can be tried if you want to go ahead with the shared library setup:
Don't. Use the proxy class on the client side. This is how it is intendend to be done. It works fine unless you simultaneously want to leverage aspects of the shared library that are not exposed by the web service WSDL.
Implement or use a provided copy/duplication feature of the class (e.g. you could try to Merge() one strongly typed dataset into another). A Cast is obviosuly not possible, and the copy option is usually not a very good solution either since it tends to have undesirable side-effects. E.g. When you Merge a dataset into another, all the rows in the target dataset will be labeled as 'changed'. This could be resurrected with AcceptChanges(), but what if a couple of the received rows were actually changed.
Serialize everything - except for elementary data types - into strings (and back again on the consumer side). Loss of type safety is one important weakness of this approach.
Remove the explicit declaration of the shared class in Reference.cs and strip the namespace from the shared class wherever it is mentioned within Reference.cs. This is probably the best option. You get what you really wanted. The shared class is returned by the web service. The only irritating drawback with this solution is that your modifications to the reference.cs file is lost whenever you update your web reference. Trust me: It can be seriously annoying.
Here is a link to a similar discussion:
You can reuse existing referenced types between the client and service by clicking on the 'Advanced' button on the 'Add Service Reference' form. Make sure the 'Reuse types in referenced assemblies' checkbox is checked and when the service client is generated it should reuse all types from project A.
In past versions this has not always worked correctly and I've had to explicitly select the shared type assemblies by selecting the 'Reuse types in specified referenced assemblies' option and then checking the appropriate assemblies in the list box. However, I just tested this with VS 2008 SP1 and it appears to work as expected. Obviously, you need to make sure that the types that are being used by the service and client projects are both from project A.
Hope that this helps.
We encountered a similar problem with one of our projects. Because we had several dependencies, we ended up creating a circular reference because project 1 required objects from project 2, but project 2 could not be build before project 3, which relied on project 1 to be build.
To solve this problem, we extracted all the public standalone classes from both projects and placed them inside a single librarie. In the end we created something like this:
Framework.Objects
Framework.Interface
Framework.Implementation
WebService
The WebService would be linked to all projects in our case, whereas external parties would only be linking to the objects and interface classes to work with. The actuall implementation was coupled at runtime through reflection.
Hope this helps
I am trying to write some code in C# that will call a WCF service on the fly by importing the WSDL, examining it and then making calls to it dynamically.
The service I am calling can change from time to time - so if it does I want my client to know about new methods and new input parameters and output parameters to the calls, without rebuilding my client.
One possible solution to this is to import and compile a service reference on the fly.
Outlined here: Creating an assembly on the fly from a WSDL
I would like to avoid the generation of an assembly and then reflecting over it if possible.
I looked into the code of the dynamic proxy in the link and they use a framework class to do the import. This class is the WsdlImporter. So I had thought great - I can use that and examine the WSDL schema and determine what calls are present and what inputs and outputs are available.
The problem is that the type information is missing in the MessagePartDescription objects that the WsdlImporter creates. Apparently this is missing because it cannot find the types yet - see the response to the question from Brian.
So any advice on how I should proceed? Am I completely on the wrong track here?
This is probably not an answer but I will post it as one to fully describe my opinion.
Dynamic proxy:
IMO this is example of wrong usage of technology. It is elementary behavior of WSDL - if it changes you have to change client or you have to make good WSDL versioning and create new client.
You still have to somehow say your client to get WSDL - does it mean that you will parse WSDL before each call? Doesn't seem like a good idea.
Information about types is really not part of WSDL because by default WSDL is generated as interoperable. CLR types are not operation needed for interoperability. When you create service proxy by Add service reference or Svcutil it will generate code for types defined in WSDL. That code then need to be compiled.
You can try to use NetDataContractSerializer instead of default DataContractSerializer. NetDataContractSerializer adds CLR type information into WSDL but I still expect that new types must be known to your clients - it means deploying new assembly with types and use it by clients. This almost sounds like same approach when simply deploying assembly with new static client proxy.
Dynamic WF client
I also don't see too much usage of this architecture - you still need to change client to reflect new WF steps, don't you?
Changing the WF
Are we talking about Windows Workflow foundation? I can hardly imagine scenario where you create WF, expose it as a service and then change it. When you expose WF as service you are probably defining long running WF. Long running WFs use persistance which is based on serialization (at least in WF 3.5 but I believe it is same in WF 4). When you change WF definition, all persisted WFs are most probably doomed because they will never ever deserialize. This situation is usually solved by parallel deployment of new and old version where old version is only used to finish incomplete WFs. Again it means new clients.
If you look at the problem from a different angle. Do you need to regenerate the proxy each time or do you need a contract that continues to work when things change?
WCF has a mechanism for this IExtensibleDataContracts see: http://msdn.microsoft.com/en-us/library/ms731083%28v=VS.100%29.aspx
Best practices for versioning of contracts can be found here
Basically, I have a server-side type "Foo" with members X and Y. Whenever I use Visual Studio's "Add Server Reference" then I see the WSDL and the generated proxy both append the word "Field" to all the members and change the casing of the first letter. IE, "X" and "Y" are renamed "xField" and "yField". Any idea why this is happening? I can't figure out the pattern.
Details -- I have a legacy ASMX web service which exposes a "Foo" type. I created a new WCF service that's a wrapper around that old web service -- the new service just wraps those methods and maybe updates the values of a few fields, but it exposes the exact same methods and returns the exact same types. I've tried re-creating the referenes several times, and every time, it always renames my fields: the varible "STUFF" is exposed in the wsdl and proxy as "sTUFFField". Variable "X" is exposed as "xField", etc.
Funny thing is I can't figure out the pattern -- I tried creating a new ASMX web service as a test and wrapping that -- variables are not renamed then. So I can't figure out the pattern of why/when WCF renames variables.
Anybody know?
I had the same issue, and sergiosp's answer got me headed in the right direction. Just adding some additional info to hopefully help someone else.
Adding [System.ServiceModel.XmlSerializerFormatAttribute()] to the interface, and re-generating the client code resolved the problem for me.
public interface IMyService
{
[System.ServiceModel.XmlSerializerFormatAttribute()]
[System.ServiceModel.OperationContract]
recordResponse GetRecord(recordRequest request);
}
I had the same problem but i was able to find solution.
In the interface if you add [DataContractFormat] tag you will end up with "XFieldField" case.
But if you replace it with [XmlSerializerFormat] in the interface it will not change the names in the proxy generated.
Typically, the generated proxy will have "XField" and "YField" as internal/protected/private fields, and expose the values through properties called "X" and "Y". There are options you can set when creating the proxy client to tweak that to your liking, I think.
UPDATE: I don't seem to find any switches or options to control this behavior. It might depend on which serializer (DataContractSerializer vs. XmlSerializer) WCF uses for creating the client proxy.
In the end, it's really more or less just an issue of coding style - functionally, it shouldn't make a difference.
Marc
I had this problem too, but from the client I was still getting Field at the end of the class members even after making the mentioned change at the interface.
The problem was, I was using a DataContractSerializer to work with disk file serialized requests (during the test of our service, we were getting serialized requests from the provider, to be able to debug before going live).
After changing the DataContractSerializer to a XmlSerializer, specifying on its constructor the root element (by a typeof() call) and the rootnamespace (because by default, XmlSerializers write the standard namespace), I could deserialize the requests and work perfectly with the WCF Service.
Hope this helps somebody. I lost soooo many time with this "issue".
Adding XmlSerializerFormat worked for me. Got solution from http://geekswithblogs.net/mipsen/archive/2010/02/06/field-postfix-in-wcf-reference.aspx
[ServiceContract(Namespace="http://somenamespace.com/contracts")]
public interface ISchemaService
{
[OperationContract]
[XmlSerializerFormat]
void DoSomething(GeneratedType data);
}
I'm still new to the ASP.NET world, so I could be way off base here, but so far this is to the best of my (limited) knowledge!
Let's say I have a standard business object "Contact" in the Business namespace. I write a Web Service to retrieve a Contact's info from a database and return it. I then write a client application to request said details.
Now, I also then create a utility method that takes a "Contact" and does some magic with it, like Utils.BuyContactNewHat() say. Which of course takes the Contact of type Business.Contact.
I then go back to my client application and want to utilise the BuyContactNewHat method, so I add a reference to my Utils namespace and there it is. However, a problem arises with:
Contact c = MyWebService.GetContact("Rob);
Utils.BuyContactNewHat(c); // << Error Here
Since the return type of GetContact is of MyWebService.Contact and not Business.Contact as expected. I understand why this is because when accessing a web service, you are actually programming against the proxy class generated by the WSDL.
So, is there an "easier" way to deal with this type of mismatch? I was considering perhaps trying to create a generic converter class that uses reflection to ensure two objects have the same structure than simply transferring the values across from one to the other.
You are on the right track. To get the data from the proxy object back into one of your own objects, you have to do left-hand-right-hand code. i.e. copy property values. I'll bet you that there is already a generic method out there that uses reflection.
Some people will use something other than a web service (.net remoting) if they just want to get a business object across the wire. Or they'll use binary serialization. I'm guessing you are using the web service for a reason, so you'll have to do property copying.
You don't actually have to use the generated class that the WSDL gives you. If you take a look at the code that it generates, it's just making calls into some .NET framework classes to submit SOAP requests. In the past I have copied that code into a normal .cs file and edited it. Although I haven't tried this specifically, I see no reason why you couldn't drop the proxy class definition and use the original class to receive the results of the SOAP call. It must already be doing reflection under the hood, it seems a shame to do it twice.
I would recommend that you look at writing a Schema Importer Extension, which you can use to control proxy code generation. This approach can be used to (gracefully) resolve your problem without kludges (such as copying around objects from one namespace to another, or modifying the proxy generated reference.cs class only to have it replaced the next time you update the web reference).
Here's a (very) good tutorial on the subject:
http://www.microsoft.com/belux/msdn/nl/community/columns/jdruyts/wsproxy.mspx