Webreferences sharing classes - c#

I wrote a few SOAP Webservices in Java, running on a JBoss 5.1.
Two of them share a class, AddressTO. The Webservices are deploying correctly on my ApplycationServer and all went well until I try to use the class addressTO in my C#-client. There are two types in the client application, addressTO and addressTO1. This is a problem because this causes errors like:
Fehler 1 Eine implizite Konvertierung vom Typ
"acsysteme.i4workspace.client.webservices.addressTO1[]" in
"acsysteme.i4workspace.client.webservices.addressTO[]" ist nicht möglich.
[...]
This means that it is impossible to cast the to types implicitly.
AddressTo is something like a core class which can be used by other webservices.
The webreferences for the C#-client are created by the command
wsdl.exe /parameters:CreateWebService.xml
The xml-file contains the urls to the differend .wsdl-files of my webservices.
Does someone know how to handle this problem?

Use the /sharetypes option when calling wsdl.exe:
/sharetypes
Turns on type sharing feature. This feature creates one code file
with
a single type definition for identical types shared between
different
services (namespace, name and wire signature must be identical).
Reference the services with http:// URLs as command-line
parameters
or create a discomap document for local files.
If the classes match exactly, they should only be generated once if you generate code for both services in a single command. Both services will be using the same class, so no conversion will be necessary.
Edit:
If the XML namespaces do not match (which is a common occurrence), .NET will consider them to be different types, and rightly so. You will either have to fix the web services so the types are exactly the same (recommended), or do conversion between the two generated types. This will result in a lot of boring property assignment code, so you might want to consider using something like AutoMapper to handle the conversion for you.
wsdl.exe should generate partial classes, so if you want, you can define implicit conversions between the different types:
public static implicit operator addressTO1(addressTO source)
{
addressTO1 result = new addressTO1();
// Assign properties, etc.
return result;
}
I'm not usually a big fan of implicit conversions myself, but in this case it might be warranted.

I solved it!
I followed the hint of Thorarin to use the wsdl.exe option sharetypes. But to use this option is not enougth. First, you need to setup the correct namespace (using a URI) in the Webservice class in your java server with the following annotation:
#WebService(targetNamespace="http://com/project/client/webservices/")
public class WebServiceImplementation implements WebService{
// ... your #WebMethod-methods
}
Second, you need to modify the settings in createWebService.xml accordingly: The namespace of the webservice needs to be added like this:
<wsdlParameters xmlns="http://microsoft.com/webReference/">
<!-- Defaultsettings -->
<language>CS</language>
<sharetypes>true</sharetypes>
<namespace>com.project.client.webservices</namespace>
<!-- output -->
<out>soap/WebServices.cs</out>
<appSettingUrlKey>BaseUrl</appSettingUrlKey>
<appSettingBaseUrl>http://localhost:8080</appSettingBaseUrl>
<!-- web service locations -->
<documents>
<document>http://localhost:8080/Core?wsdl</document>
<document>http://localhost:8080/WebService0?wsdl</document>
<document>http://localhost:8080/WebService1?wsdl</document>
</documents>
</wsdlParameters>
That's it! Call wsdl.exe /parameters:createWebService.xml and you are done.
Thanks for your help!

Related

Activator.CreateInstance returning incorrect type?

I'd be grateful if you could help with this:
I have a base class for a Provider.
This is subclassed to create a
DefaultProvider.
DefaultProvider implements an interface called “IExportProvider”
DefaultProvider is subclassed to create a
DanishProvider.
The base class has various virtual methods that return string values in English.
The DanishProvider overrides these to return strings in Danish.
At runtime, I load either the DefaultProvider or the DanishProvider depending on a config. value. I do this by scanning the current assembly for the type name, which is either “DefaultProvider” or “DanishProvider”, and which implements “IExportProvider”
var importServiceType = assembly.DefinedTypes.FirstOrDefault(type => (type.Name.Equals(providerServiceName, StringComparison.OrdinalIgnoreCase)) && type.ImplementedInterfaces.Any(i => i == typeof(I)));
I then use Activator.CreateInstance to create an instance of the type:
return (IExportProvider)Activator.CreateInstance(importServiceType, …)
Problem
I use the code in a .Net 4.8 Web application, where I load the DanishProvider. This mostly works OK and I can see the Danish strings are returned. However, occasionally (after several days) the application appears to incorrectly load the DefaultProvider, and I see English strings returned.
Once it has switched to English it appears to stay on the DefaultProvider.
Twice I have done an IISRESET which fixes the problem immediately.
The settings
are not being changed.
There is only one type in the assembly called “DanishProvider”
The code is executing on a single UAT server. I have not seen the issue on my local PC.
I do not believe that the issue is related to caching.
Q. Is there a problem with the code approach described above?
Thank you

Roslyn CodeFix with multiple variants to fix

I have a CodeFix provider, purpose of which to inject service to current class, like add new private field, parameter to constructor, assignment statement in constructor, using ServiceNamespace, and use of this field in proper place(s).
At some point, I have a name of this service, and I need to find namespace for this service to add correct using. I'm doing this via compilation.GetSymbolsWithName(typeName), but this method can return several matched symbols from different namespaces/assemblies.
So, the question: is there any way I can show this variants to user so he can decide the correct type?
For each diagnostic, you can add more than one fix.

Disable proxy types for OrganizationServiceProxy

I'm working with pre-defined IOrganizationService object I cannot modify — it's out of my control.
And it seems to be by default this IOrganizationService returns resolved types as if EnableProxyTypes() was called implicitly somewhere on originating OrganizationServiceProxy.
And this ruins all business logic, since early bound entities could not be serialized that easily, since on different installations they could be resolved to different types. So even if they would be successfully serialized, cannot be 100% certain that they could be de-serialized.
To be more specific it's plugin for XrmToolBox. If hosting application loaded plugin that uses early bounding, these generated types will be discovered via reflection and applied to results of Retrieve and RetrieveMultiple calls.
For example RetrieveMultiple to account entity response will normally contain Entity[], each item of this array will have LogicalName property set to account.
But if early bound types was discovered in assembly, let's call it EarlyBouldLibrary.dll, the same RetrieveMultiple will return EarlyBouldLibrary.Account[]. Each item of this array will be derived from Entity and will contain same field as in first example, but with additional properties.
The problem is in following. If we will try to serialize EarlyBouldLibrary.Account[] to XML it will fail. Because EarlyBouldLibrary.Account is unknown.
Ok, it's possible to add types to known. But there is no guarantee, that one day another early bound types will be found in NewEarlyBouldLibrary.dll... And they will have name NewEarlyBouldLibrary.Account... Which is unknown...
Ok, let's assume serialization succeeded, no matter which types are referenced EarlyBouldLibrary.Account or NewEarlyBouldLibrary.Account, but if we will try to de-serialize, on environment where these early bound libraries not present... action will fail.
So only way will be not to use specific early bound types, that out of our control, and use standard and safe Entity. But it's impossible while system automatically resolves proxy types.
So, question: is there any way to disable resolve of early bound types?
You can redirect your proxy to another assembly containing the types you need (or even containing no early bound types at all).
The example below resets the proxy assembly:
private void ResetProxyAssembly(IOrganizationService service)
{
var serviceProxy = (OrganizationServiceProxy) service;
serviceProxy.EnableProxyTypes();
}
In certain scenarios this may not work. Instead you can explicitly select the desired proxy assembly:
private void ResetProxyAssembly(IOrganizationService service)
{
var serviceProxy = (OrganizationServiceProxy) service;
serviceProxy.EnableProxyTypes(typeof(MyEarlyBoundEntity).Assembly);
}
Could you add [assembly: Microsoft.Xrm.Sdk.Client.ProxyTypesAssembly] to the AssemblyInfo file of the EarlyBouldLibrary.dll or NewEarlyBouldLibrary.dll assembly?

Deserializing JSON object to runtime type in WinRT (C#)

I have a small WinRT client app to my online service (Azure Web Service). The server sends a JSON encoded object with (with potential additional metadata) to the client and the client's responsibility would be to deserialize this data properly into classes and forward it to appropriate handlers.
Currently, the objects received can be deserialized with a simple
TodoItem todo = JsonConvert.DeserializeObject<TodoItem>(message.Content);
However, there can be multiple types of items received. So what I am currently thinking is this:
I include the type info in the header serverside, such as "Content-Object: TodoItem"
I define attributes to TodoItem on the client side (see below)
Upon receiving a message from the server, I find the class using the attribute I defined.
I call the deserialization method with the resolved type
(Example of the attribute mentioned in 2.)
[BackendObjectType="TodoItem"]
public class TodoItem
My problem with this approach however is the Type to Generics in the deserialization as I can't call:
Type t = ResolveType(message);
JsonConvert.DeserializeObject<t>(message.Content);
I tried finding some solutions to this and getting method info for the DeserializeObject and calling it using reflection seemed to be the way to go. However, GetMethod() does not exist in WinRT and I was not able to find an alternative I could use to retrieve the generic version of the DeserializeObject (as fetching by the name gives me the non-generic overload). I don't mind using reflection and GetMethod as I can cache (?) the methods and call them every time a message is received without having to resolve it every time.
So how do I achieve the latter part and/or is there another way to approach this?
Alright, I feel like this was not really a problem at all to begin with as I discovered the DeserializeObject(string, Type, JsonSerializerSettings) overload for the method. It works splendidly. However, I would still like to hear some feedback on the approach. Do you think using attributes as a way to resolve the type names is reasonable or are there better ways? I don't want to use the class names directly though, because I don't want to risk any sort of man-in-the-middle things be able to initialize whatever.
Just a few minutes ago we have posted the alternative way to do what you want. Please look here, if you will have any questions feel free to ask:
Prblem in Deserialization of JSON
Try this
http://json2csharp.com/
Put your Json string here it will generate a class
then
public static T DeserializeFromJson<T>(string json)
{
T deserializedProduct = JsonConvert.DeserializeObject<T>(json);
return deserializedProduct;
}
var container = DeserializeFromJson<ClassName>(JsonString);

does enriching Poco or Inteface, force recompile?

I'm writing some service.
I'm asking 2 questions regarding 2 situations:
Situations
1) i use it "in-house", meaning as a referenced dll
2) I use it over the net, as webService
Questions
A)
If it exposes an interface to some client-class.
and now I added some method to that interface.
Do I have to recompile all its clients to recognize
the new interface even if they don't use the new methods?
B)
If a method in my service's interface expect some PoCo with property a,b
and one of the client calls that method with the same Poco type, but this Poco is defiened in the client-code as one that has a,b as before and also c,d.
Do I have to recompile the service? Does the contract breaks?
For web services, if you are certain that changes will happen, you may want to design a 'versioned' interface that takes generic arguments and a version number. I have done this using an XML string that holds the contents of the parameters passed (XML string passed to web service a HTML encoded to avoid breaking SOAP envelope).
In the web service methods, checking the version number than proceeds to parse the XML into the expected type(s) for that method:
public void GenericWebServeceMethod(int version, string encodedXMLParameters)
{
string xmlParameters = HTMLDecode(encodedParameters);
switch(version)
{
case 1:
ParameterType1 p1 = DecodeVersion1XML(xmlParameters);
MethodVersion1(p1);
break;
case 2:
ParameterType2 p2 = DecodeVersion2XML(xmlParameters);
MethodVersion2(p2);
break;
}
}
When new versions are added, you extend the switch statement with new versions which still allows clients using older versions of the parameter types to continue working.
For a referenced DLL used 'in-house' you can force the reference to be version independent by adding the reference using the 'Browse' option in Visual Studio, and then selecting the reference's properties and ensuring that the 'Specific Version' property is set to False. Then you can still use a system similar to above to change the way than XML-encoded parameters are handled based on a passed version number. Adding new methods is allowed but the calling client will not 'see' them until it it recompiled.

Categories