How can I use generic methods in wcf service?
I wrote this code:
[OperationContract]
void AddItem<T>(T item);
But I receive the following Error:
Type 'T' cannot be exported as a schema type because it is an open generic type. You can only export a generic type if all its generic parameter types are actual types.
You simply can't. It's not possible to do that, as soap does not support this. See this article, which mentions how to get around generics, by creating an intermediate local object that is called and casts the object before calling the WCF operation.
You shouldn't be trying to do this. In a SOAP enabled web service all types need to be known when the WSDL is published so that clients would be capable of generating a proxy. Generics simply don't exist in the SOAP specification. SOAP is intended to be interoperable and generics don't exist in all languages.
As all the others have already mentioned, WCF and SOAP do not support this. The issue is: anything you pass back and forth between client and server must be expressible in a XML schema document.
XML schema supports all the usual atomic types, like string, int, datetime - and it supports complex types made up of those atomic types, and it supports inheritance.
But XML schema has no support for generics - and thus, anything you exchange via WCF and SOAP cannot be generic - you need to use concrete, non-generic types only.
I don't know of any way around this, either. It's a limitation and you have to live with it for now.
Bounded generic types in data contracts can be used but must be specfied types parameters in the service contract and as the specified type parameters with valid data contracts
The error says that open types are not allowed. What probably is allowed is something like:
[OperationContract]
void AddItem<T>(T item) where T : MyBaseType;
Ofcourse, all inherited types should be added with the KnownType attribute.
Related
I consume a web service that has a numeric element. The Delphi wsdl importer sets it up as Int64.
The web service allows this element to be blank. However, because it is defined as Int64, when I consume the web service in Delphi without setting a value for it, it defaults to 0 because it's an Int64. But I need it to be blank and the web service will not accept a value of 0 (0 is defined as invalid and returns an error by the web service).
How can I pass a blank value if the type is Int64?
Empty age (example)
<E06_14></E06_14>
could have a special meaning, for example be "unknown" age.
In this case, the real question is how to make the field nillable on the Delphi side.
From this post of J.M. Babet:
Support for 'nil' has been an ongoing issue. Several built-in types of
Delphi are not nullable. So we opted to use a class for these cases
(not elegant but it works). So with the latest update for Delphi 2007
I have added several TXSxxxx types to help with this. Basically:
TXSBoolean, TXSInteger, TXSLong, etc. TXSString was already there but
it was not registered. Now it is. When importing a WSDL you must
enable the Use 'TXSString for simple nillable types' option to make
the importer switch to TXSxxxx types. On the command line it is the
"-0z+" option.
The DocWiki for the Import WSDL Wizard also shows two options related to nillable elements:
Process nillable and optional elements - Check this option to make the WSDL importer generate relevant information about optional
and nillable properties. This information is used by the SOAP runtime
to allow certain properties be nil.
Use TXSString for simple nillable types - The WSDL standard allows simple types to be nil, in Delphi or NULL, in C++, while Delphi
and C++ do not allow that. Check this option to make the WSDL importer
overcome this limitation by using instances of wrapper classes.
I need to convert the XML which comes as a message from a different system into the Type which i am looking. For example if i have a Generic interface like
IMessageHandler<CustomerCreated>
Then when the XML comes with i should be able to Find the type and create a Genric type. So that i can use the Dependency injection to call the appropriate class which would have implemented the method.
I have Seen this kind of Code in NServiceBus so i am the tag as well
I have some WCF services which employes default DataContractSerialization. Some of the service methods return Dictionary objects. One of the clients are generating XSD files from WCF services (biztalk related) and he is requesting to convert all dictionary types to a new dictionary type which implements IXmlSerializable.
I wonder, if there will be any unexpected results of this conversion which may affect the DataContract serialization somehow?
Update:
Server and client share the same domain dlls, clients do not generate them from service. Maybe in the question I was missing the main point; I wonder if an object is to be serizalized through datacontract serialization, implementing IXmlSerializable in the object will cause any problems.
Is your client sharing dlls with the service?
Unless he is sharing libraries (dlls) with service then making changes at the service end won't make any difference. Your WCF is returning data, not classes. That data is being reconstituted into classes which are created by the client based on the definitions in the WSDL your service returns. You can't control those generated libraries (by making chnages on the server) unless you share dlls between the client and the server.
If he wants to wrap the generated dictionaries in an IXmlSerializable dictionary then he can, or if he wants to generate a different type of dictionary then he can probably do that as well, but I don't think there is anything you can do server side.
Tell your client to use the following serializable dictionary when they need to serialize a dictionary result from a service call: C# Serializable Dictionary – a Working Example
It accepts an ordinary dictionary as constructor argument thus converts any dictionary into a serializable one. You can also return SerializableDictionary type as the service call result if you like.
There is an unexpected problem; since domain objects are already implementing data contract serialization, there is no way to implement IXmlSerializable without modifying the whole serialization mechanism.
This isssue may have several aspects so please read through first.
Suppose that you have a stuct with a few small ints that pack well into Int64 and while you want to use your struct as a type in C# you want it to be exposed as In64 via web methods - so that WSDL has it and you retain basic REST ability (simple types make GET invocation possible).
The closest to that I've found so far is SqlDateTime - it auto-morphs into dateTime in WSDL (there's an attrib that seems to govern XSD/WSDL type equivalence plus IXmlSerializable) but that's not enough. The web method still gets recognized as "having complex params" and therefore is rendered unavailable to GET requests.
Update: XSD/WSDL and SOAP invocation respected type equivalency perfectly fine - the problem is with GET invocation - the RESTful URL path doesn't get generated at all.
Looking for info on possible additional attribs, interfaces, hook-up points, of if someone stumbled upon a struct or internal class that managed to do full type equivalence with any "primitive", scalar type (DayTime is not exactly primitive but still gets such treatment). Also if soemone knows a way to establish stronger type equivalence or add/mark a struct to be treated as a simple (scalar) value type - even better.
Please don't post just to say something nasty or preach private ideology. This is serious, gray-zone question for people who know their way in Reflector and read the code. If you think you can ideologize this you don't even have the clue about the issue. If however you can point to actual code that causes/makes the decison about what will be servable via GET request please post even if by doing that you prove the impossibility of extending type equivalence to GET requests.
Oh and CLR is 2.x/3.x.
Thanks to those who help and to those who don't disrupt.
This is not doable.
Why would it be? You're talking about an egregious hack. Why on Earth would .NET ever support it, or allow it?
The only thing you'll be able to do is to implement the IXmlSerializable interface on your struct, so you can do the serialization and deserialization yourself.
I'm trying to convert an ASP.Net web service to WCF application. The client is on the .Net Compact Framework which does not support WCF so I need to make sure the WCF keeps supporting ASP style webservices. When I add the web service reference in Visual Studio the generated proxy class' methods have extra arguments.
For example if a method is defined as:
public void GetEmpInfo(int empNo)
That method will appear in the proxy class as:
public void GetEmpInfo(int empNo, bool empNoSpecified)
What causes this, and how do I get it to stop?
Check out this blog post ...
Where did these extra boolean
“specified” members come from and what
do they do? The answer is the schema
that the WCF data contract serializer
generates by default. Because of the
way its versioning model works, the
serializer generates all data members
as optional elements. The older web
services stack, ASP.NET Web Services
(“ASMX”), uses a different serializer,
the XmlSerializer, which maintains
full schema and XML fidelity. The
XmlSerializer maps all optional
elements to two members: one
represents the data itself, and one
specifies whether or not the data is
actually present – this is the
“xxxSpecified” member. These
xxxSpecified members must be set to
true to enable the serialization of
the corresponding “actual data”
members.
The .NET Compact Framework does support a subset of WCF. You can review this support on MSDN. Take a look, it may support enough for you to remove your legacy Web Services support.
This happens for types with a default value of not null. In these cases, it's impossible for the web service to know whether a parameter was set to the default value or simply not set at all.
You can get rid of the extra specification parameter by decorating your operation with the [XmlSerializerFormat] attribute like:
[OperationContract]
[XmlSerializerFormat]
string GetEmpInfo(int? empNo);
This attribute can also be added at the Class level, and this would make sense in most cases.
I understand you can handle this situation using nullable types (int?), but I was unable to fix it using this.