21

I have a problem while adding WCF in the .NET core project. When I used .net in the past I can add multiple environments in web.config so I can load the correct web service at runtime (Dev, Rec, Prod).

The problem in the .net core project when I added a reference of my WCF service as Connected Service it created one file ConnectedService.json that contains a URL for the WCF service.

{
  "ProviderId": "Microsoft.VisualStudio.ConnectedService.Wcf",
  "Version": "15.0.20406.879",
  "GettingStartedDocument": {
    "Uri": "https://go.microsoft.com/fwlink/?linkid=858517"
  },
  "ExtendedData": {
    "Uri": "*****?singleWsdl",
    "Namespace": "Transverse.TokenService",
    "SelectedAccessLevelForGeneratedClass": "Public",
    "GenerateMessageContract": false,
    "ReuseTypesinReferencedAssemblies": true,
    "ReuseTypesinAllReferencedAssemblies": true,
    "CollectionTypeReference": {
      "Item1": "System.Collections.Generic.List`1",
      "Item2": "System.Collections.dll"
    },
    "DictionaryCollectionTypeReference": {
      "Item1": "System.Collections.Generic.Dictionary`2",
      "Item2": "System.Collections.dll"
    },
    "CheckedReferencedAssemblies": [],
    "InstanceId": null,
    "Name": "Transverse.TokenService",
    "Metadata": {}
  }
}

My question how can I load the correct service based on the used environment.

Note.

In my Project, I did not have an appsettings neither web config. It is a .net core class library and it is called in ASP.NET core Application as Middleware.

Useme Alehosaini
  • 2,998
  • 6
  • 18
  • 26
Adouani Riadh
  • 1,162
  • 2
  • 14
  • 37

5 Answers5

20

As I understand from this article, this is Microsoft's recommendation:

  1. Add new class file
  2. Add same Namespace of service reference.cs
  3. Add Partial Class to expand reference service class (declared in Reference.cs)
  4. And Partial Method to implement ConfigureEndpoint() (declared in Reference.cs)
  5. Implement ConfigureEndpoint() Method by Setting a new value for Endpoint

Example:

namespace Your_Reference_Service_Namespace
{
    public partial class Your_Reference_Service_Client
    {
        static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials)
        {
            serviceEndpoint.Address = 
                new System.ServiceModel.EndpointAddress(new System.Uri("http://your_web_service_address"), 
                new System.ServiceModel.DnsEndpointIdentity(""));
        }
    }
}
  1. Here, you can take the value from the appsettings.json file

    new System.Uri(configuration.GetValue("yourServiceAddress")

Refael
  • 6,753
  • 9
  • 35
  • 54
14

For whom are interested by the solution I added an endpoint for my service in each appseetings.{environment}.json and in Service class I inject new Instance of my service based on the environment variable ASPNETCORE_ENVIRONMENT

   services.AddTransient<Transverse.TokenService.ITokenService>(provider =>
        {
            var client = new Transverse.TokenService.TokenServiceClient();
            client.Endpoint.Address = new System.ServiceModel.EndpointAddress(Configuration["Services:TokenService"]);
            return client;
        });

Maybe is not the best but it works fine.

Adouani Riadh
  • 1,162
  • 2
  • 14
  • 37
  • Hi, Could you also please share how you are then calling the WS. I added the code you mentioned. I verified the new address url is coming from appsettings. But when in my code I want to execute the ws method by first DemoServiceClient client = new DemoServiceClient(); I check the variable client's address it is still using the original address url and not the one from appsettings. thank you! – Benk Nov 21 '18 at 00:47
3

I am using .Net Core 3.1, this is my way when I call WCF Service.

var sUserClientRemoteAddress = _configuration.GetValue<string>("WCFRemoteAddress:UserClient");
UserClient userService = new UserClient(UserClient.EndpointConfiguration.CustomBinding_IUser, sUserClientRemoteAddress);

First, Get the endpoint remote address from appsettings.json

Second, Call web service client using that address in CTOR WCF Client Class parameter

Thanks in advance.

0

Use a ChannelFactory to consume your service. WCF ChannelFactory vs generating proxy

A ChannelFactory allows you to set an EndpointAddress. How to: Use the ChannelFactory

The URL for the endpoint can be loaded from a configuration file. In a more advanced setup a directory lookup for the service can be performed to retrieve the URL for the environment where the application is deployed. https://en.wikipedia.org/wiki/Service_provider_interface

https://github.com/jolmari/netcore-wcf-service-proxy

Example of consuming multiple WCF services using a proxy implementation in a ASP.NET Core Web-application.

ofthelit
  • 1,341
  • 14
  • 33
0

I just went with the simple route. Note: I'm on .NET 6.

Step 1:

Add the service reference by following steps in the MSFT guide:

https://learn.microsoft.com/en-us/dotnet/core/additional-tools/wcf-web-service-reference-guide

Step 2:

Create a factory to create WCF service client. You can pass the wcfUriBasedOnEnvironment from the main project or anywhere you want.

public static class WCFServicesClientFactory
{
    // APIWCFServicesClient is the service client inside Reference.cs generated in Step 1
    public static APIWCFServicesClient CreateUsingUri(string wcfUriBasedOnEnvironment)
    {
        return new APIWCFServicesClient(APIWCFServicesClient.EndpointConfiguration.BasicHttpBinding_IAPIWCFServices,
                 new System.ServiceModel.EndpointAddress(new System.Uri(wcfUriBasedOnEnvironment)));
    }
}

Step 3:

Use it like:

var wcfClient = WCFServicesClientFactory.CreateUsingUri("http://your_web_service_address");
Ash K
  • 1,802
  • 17
  • 44