I'm trying to instantiate a web service in my .NET web application. But as soon as it hits this line:
registerService register = new registerService();
Then i get the following error:
Unable to generate a temporary class (result=1). error CS0030: Cannot
convert type 'Test.Website.ProxyTest.registerType[]' to
'Test.Website.ProxyTest.registerType'
I didn't write the web service. But does this mean the web service has an error somewhere (in an XSD or something)?
Does this mean that the 3rd party developers need to fix this web service?
It seems to be a Known issue and the details can be found here
Cause: A known issue with WSDL.EXE included in the .NET Framework can
cause a proxy class to be generated incorrectly if an array of complex
type includes an element that is also an array of complex type for
which only one element exists
.
There is no resolution available at this time however there are three
available workarounds:
Generate the proxy class manually using WSDL.EXE and then modify the
proxy class where the datatype has been inappropriately created as a
two-dimensional array (e.g. 'CustomType[][]') and correct it to be a
single-dimensional array (e.g. 'CustomType[]'). Modify the datatype in
the desired WSDL so that a second, optional element is included in the
definition. This can be done by adding an element such as
''. Modify the complex type in the desired WSDL so
that the boundary attributes are part of the complex type rather than
the element (i.e. move the "minOccurs" and "maxOccurs" attributes to
the complex type and remove them from the element).
A similar stackoverflow question
Related
I have a WCF service that requires me to add the folowing to Reference.svcmap
<NamespaceMappings>
<NamespaceMapping TargetNamespace="http://schemas.datacontract.org/2004/07/System.DirectoryServices"
ClrNamespace="System.DirectoryServices" />
</NamespaceMappings>
If I don't have that line I get the following error:
Warning 1 Custom tool warning: Cannot import wsdl:portType
Detail: An exception was thrown while running a WSDL import extension:
System.ServiceModel.Description.DataContractSerializerMessageContractImporter
Error: ISerializable type with data contract name 'DirectoryServicesCOMException'
in namespace 'http://schemas.datacontract.org/2004/07/System.DirectoryServices'
cannot be imported. The data contract namespace cannot be customized for
ISerializable types and the generated namespace
'DomainManagement.Console.UserManagementProxy' does not match the required CLR
namespace 'System.DirectoryServices'. Check if the required namespace has been
mapped to a different data contract namespace and consider mapping it
explicitly using the namespaces collection.
XPath to Error Source:
//wsdl:definitions[#targetNamespace='http://example.com/v1']/wsdl:portType[#name='IUserManagement']
I also know having a common DLL between the client and server will also solve the issue but I do not want to have to require any client to also have the accompanying DLL to communicate with the service.
I understand the issue, and the fix (both dll and editing the file). What I would like to know is: Is there anything I can do on the Host side so every client that subscribes to this service does not need to any extra configuration of the service after generating the proxy in visual studio? (i.e. Using SvcUtil and using the /n:http://schemas.datacontract.org/2004/07/System.DirectoryServices,System.DirectoryServices parameter is not a preferred option)
I think this is simply down to the fact that some types "don't serialize well". Trying to pass a NameValueCollection across WCF (prior to VS2010) produced exactly the same error as you are seeing, despite it being serializable. Another one that I've seen crop up from time to time is the SqlException (see here).
Alas I'm not aware of any server-side solutions. I find that providing clients with a "service interface" DLL to be the cleanest approach - it avoids having to generate client-side code via svcutil/add service reference, but you seem to have your reasons for not doing this. The alternative would be to refactor your server-side code to avoid passing around a DirectoryServicesCOMException. You could try Googling the "NameValueCollection WCF serialization" issue and see if any of the suggested workarounds from back then might be applicable to your scenario. I suspect not though, as this was caused by the way it implemented certain interfaces internally.
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 have a declared element "RecordRefSet" in the basetypes XSD; it is a container element for "RecordRef" elements. The "RecordRefSet" element is referenced in various places in a set of WSDL.
When my first project generates code from those WSDL and XSD, the generated code includes a class called "RecordRefSet", which is used in various places.
But when my second project generates code from a subset of those WSDL and XSD, the generated code does not include a class called "RecordRefSet" and instead directly uses arrays of "RecordRef" in the places where the first project uses instances of "RecordRefSet" class.
I want to know what determines when SVCUTIL decides to generate the "RecordRefSet" class and when it decides to use arrays of "RecordRef" directly.
I have checked that it is running the exact same version of SVCUTIL, with the same command-line options (generate service contracts, XMLSerializer), in both cases. The only difference is that the first project includes all my WSDL and XSD files, generating a larger total amount of code, the second project use a subset of WSDL and XSD files.
I don't know the exact details of SvcUtil but if you add the [KnownType(typeof(YourType)] attribute to your class this will tell the proxy generator what types is the service using and according to that it should generate the RecordRefSet class for you everytime
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.
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