8

I have a collection of related webservices that share some of the types between them, notably the "token" generated by the TokenService.

When using "add reference" in Visual Studio, proxy classes are generated and many classes, such as the Token class, are duplicated for each webservice.

To resolve this I have written the following powershell script to generate .cs files for the webservices which reuse the types.

$svcutil = get-item ((get-item 'Env:\ProgramFiles(x86)').Value + "\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\x64\svcutil.exe")
$csc = "C:\Program Files (x86)\MSBuild\14.0\Bin\csc.exe"

& $svcutil "http://Path/to/WebService/WSTokenService?wsdl" /o:WSTokenService.cs
& $csc /target:library /out:temp.dll WSTokenService.cs

& $svcutil "http://Path/to/WebService/WSAssetService?wsdl" /r:temp.dll /o:WSAssetService.cs
& $csc /target:library /out:temp.dll WSTokenService.cs WSAssetService.cs 

& $svcutil "http://Path/to/WebService/WSContactService?wsdl" /r:temp.dll /o:WSContactService.cs
& $csc /target:library /out:temp.dll WSTokenService.cs WSAssetService.cs WSContactService.cs
..
repeat for 8 webservices

This "chains" the webservices together, resusing the shared classes, and seems to work.

Are there any problems with this approach and/or is there a better way to achieve sharing classes between the related webservices?

Edit: please note that these are not webservices developed by us and we do not have access to the code or classes that are used server-side.

CooncilWorker
  • 405
  • 3
  • 12
  • Your project should be organized like [THIS](https://imgur.com/05HwP8s). **ClassLibrary1** should contain all classes you want to share across services. **WcfServiceLibrary1** is your service implementation. **ClassLibrary2Proxy** is where you are going to add your *Service Reference* ONLY ONCE in your entire **SampleWcfSetup** solution and generate your proxy for that particular service. **ConsoleApp1** is your client app. Note that now you don't need to add a *Service Reference* here or anywhere else, as you would normally do for each client. – jsanalytics May 27 '19 at 20:51
  • All you need to do now is to add a `using ClassLibrary2Proxy.ServiceReference1;` in your source code. – jsanalytics May 27 '19 at 20:51
  • "ClassLibrary1 should contain all classes you want to share across services. ". So I should write these classes? They are usually generated from the WSDL(s). – CooncilWorker May 28 '19 at 16:25
  • If you are the owner of these services (and corresponding WSDL), then yes, of course you should and probably did write them. If you properly decorated these classes with `DataContract` and `DataMember` attributes, AND, they are part of your `IService` interfaces, then they will be picked up by `svcutil` and included in the namespace for the corresponding service. – jsanalytics May 28 '19 at 18:42
  • We are not the developers of these webservices - we are consuming them. – CooncilWorker May 30 '19 at 11:01
  • Well, there you have it... had the developers followed our advice...:O), it would've worked fine in both, [YOUR APPROACH](https://imgur.com/OEtdcKl) and [OUR APPROACH](https://imgur.com/KIGCTm8). However, notice though, our approach is still a lot better because each proxy is in its own namespace, which is good because it allows you to selectively add a `using` only for the proxies you want... – jsanalytics May 30 '19 at 20:05
  • ...And in your approach, as it stands, notice that both proxies are located in the same scope but _outside any namespaces_ ... which first, is not standard .NET procedure, and second, does not allow you to include proxies selectively. And remember, like we mentioned before, in our approach you have to **Add Reference** only once in the entire solution, and that's it. So, which one are you gonna pick ?? :O) – jsanalytics May 30 '19 at 20:05
  • Forgot to mention: `CompositeType` is the boilerplate class being shared between services 1 and 2 in our example. – jsanalytics May 30 '19 at 20:08
  • I have uploaded a picture of what our object browser looks like for "shared types" using the approach above here: https://imgur.com/a/j26o8os . Since the consensus seems to be that we shouldn't do this I am going to revert back to not sharing types as it seems to make little practical difference besides forcing us to types some namespaces and/or use the var keyword.. – CooncilWorker Jun 03 '19 at 13:59
  • And here's how object browser looks using "add reference" (without sharing types): https://imgur.com/a/9vRRQ5w – CooncilWorker Jun 03 '19 at 14:28

2 Answers2

1

Why you did not create one class library project for sharing code between multiple solution? Or you can create project template for all of your microservices. I think, your current method is dirty and unsupported hack.

Mixim
  • 972
  • 1
  • 11
  • 37
  • >create one class library project for sharing code between multiple solution I am making a class library for use in multiple solutions. This is not my problem. >you can create project template for all of your microservices I am not sure what you mean by this or how it would solve the problem. My problem is that if I use "add reference" then I get duplicate proxy classes. >your current method is dirty and unsupported hack Thanks. I am looking for for alternatives. I'm not sure this is unsupported - seems to work but I hope that there may be a more elegant solution. – CooncilWorker May 24 '19 at 16:04
0

I am making an assumption in my response that you are asking if the web services can share access to a single path where the DLL (library) is stored.

This is something that you can do in windows using the GAC (requires strong named assemblies) in order for multiple applications to have easy access to it. But to date I don't believe there is a comparable service available for micro-service architecture to do something similar.

So each web services requires it's own instance of the DLL in order to use the requisite internal code.

JoeTomks
  • 3,243
  • 1
  • 18
  • 42
  • Sorry, I should have specified that these are not webservices developed by my team. We have URLs to connect to the webservices and are using either svcutil or "add reference" to generate c# classes to use the webservices. – CooncilWorker May 30 '19 at 16:12
  • 2
    Yep I understand, and you do that inside of each web service solution, and it generates the classes, and each web service ends up with a copy of it's own version of those classes etc. That's fine, there's really no better way of 'sharing' the references, at least not one that gives you any meaningful benefit. – JoeTomks May 30 '19 at 16:14
  • 1
    "each web service ends up with a copy of it's own version of those classes etc. That's fine, there's really no better way of 'sharing' the references" You may be right. I was hoping for a comparable solution to using wsdl.exe with the /sharetypes parameter. – CooncilWorker May 30 '19 at 18:44