Consume External WCF without Add Reference or project in .Net Core 3.1

Riccardo Pezzolati 21 Reputation points
2022-02-14T15:28:11.887+00:00

I need to implement an Api to expose the methods of a WCF

I add http service in my configuration:

private static IServiceCollection AddHttpServices(this IServiceCollection services, IConfiguration configuration)
 {
 // HttpContextAccessor
 services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

            services.AddTransient<AuthHandler>();

 services.AddHttpClient<ServiceClient>(config =>
 {
 var url = $"{config.GetValue<string>(urlWCF)}";
 config.BaseAddress = new Uri(url);
 }).AddHttpMessageHandler<AuthHandler>();


 return services;
 }

config.GetValue<string>(urlWCF) contains the url of service that changes according to the environment (test or production)
The question is: in the ServiceClient class I have to continue the configuration (ChannelFactory, BasicHttpBinding for example) and implement the calls to the service methods, but how do I configure everything correctly without having to add the reference to the service via the option of "Connected Services "or include the service project in my solution?

The service url reports the following info: "To test this service, you will need to create a client and use it to call the service. You can do this using the svcutil.exe tool from the command line with the following syntax:

svcutil.exe url ", url changes as specified before so I would discard this solution

.NET
.NET
Microsoft Technologies based on the .NET software framework.
3,415 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,309 questions
0 comments No comments
{count} votes

4 answers

Sort by: Most helpful
  1. Michael Taylor 48,826 Reputation points
    2022-02-14T15:39:36.21+00:00

    Why don't you want to use Connected Services. All that really does is run svcutil and generate an assembly that allows you to call the service. You don't need to write any of this code yourself.

    As for the URL, not sure where you're going there but the actual URL you call isn't relevant for the configuration. The URL you give during the configuration part is just so it can find the WSDL and generate the client code. After that you can point it to any URL (dev, test, prod, etc) that implements that WSDL and it'll continue to work correctly.


  2. AgaveJoe 26,146 Reputation points
    2022-02-14T16:32:08.44+00:00

    Because I don't know the url in advance,

    As far as I can tell, this is a nonissue.

    It's true that the parameterless constructor (connected services) defaults the binding (YourServiceNameSoap11) and the URL used when creating the service reference. Simply use the parameter constructor that takes the endpoint configuration, which is just an enumeration, and the remote URL rather than the parameterless constructor. Read the generated code.

    I would simply store the URL in configuration and use the standard ASP.NET Core environment features.
    https://learn.microsoft.com/en-us/aspnet/core/fundamentals/environments?view=aspnetcore-6.0

    The code you shared above configures HttpClient which I assume calls Web API??? Then Web API calls WCF??? Or does the .Net Core 3.1 application call the WCF service directly??? Regardless the WCF client should store the URL in configuration.


  3. Riccardo Pezzolati 21 Reputation points
    2022-02-14T16:32:09.86+00:00

    The user calls the API that will be provided to him, the API inside it queries the service and returns the result in output, the end user will only have the url to call, he has no access to the service or the WSDL, in actually I will have to call the methods implemented in that service

    I wrote services.AddHttpClient, because having the url I thought I had to use http calls

    what i actually do is like

    var service = new MyService()
    var output = service.Something(input);
    

  4. Riccardo Pezzolati 21 Reputation points
    2022-02-17T09:43:05.133+00:00

    I added the reference to the project and I added this to IServiceCollection

    services.AddScoped<IServiceClient,ServiceClient>(x =>
                 new ServiceClient($"{configuration.GetValue<string>(Constant.Url)}")
       );
    

    Class ServiceClient

    public class ServiceClient : IServiceClient
        {
            private string urlService;
            private WCFServiceReference.WCFServiceServiceClient _WCFServiceServiceClient; //WCF Service to wrap
    
            public ServiceClient(string urlService)
            {
                this.urlService = urlService;
                BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
                this._WCFServiceServiceClient = new WCFServiceReference.WCFServiceServiceClient(basicHttpBinding, new EndpointAddress(this.urlService));
            }
    
            public Task<CalculateResponse> CalculateAsync(Request input)
            {
                return CalculateAsync(input, CancellationToken.None);
            }
    
            public Task<GetProductListResponse> GetProductListAsync(ProductRequest input)
            {
                return GetElencoProdottiAsync(input, CancellationToken.None);
            }
    
            public Task<GetVariableOfProductResponse> GetVariableOfProductAsync(GetVariableRequest input)
            {
                return GetVariableOfProductAsync(input, CancellationToken.None);
            }
    
            private Task<GetProductListResponse> GetProductListAsync(ProductRequest input, CancellationToken none)
            {
                return this._WCFServiceServiceClient.GetProductListAsync(input);
            }
    
            private Task<GetVariableOfProductResponse> GetVariableOfProductAsync(GetVariableRequest input, CancellationToken none)
            {
                return this._WCFServiceServiceClient.GetVariableOfProductAsync(input);
            }
    
            private Task<CalculateResponse> CalculateAsync(Request input, CancellationToken none)
            {
                return this._WCFServiceServiceClient.CalculateAsync(input);
            }
        }
    

    When I start my application, this call CreateHostBuilder(args).Build().Run(); in Main rises the following Excpetion:

    Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Namespace.IProductService Lifetime: Scoped ImplementationType: Namespace.ProductService': Unable to resolve service for type 'Namespace.ServiceClient' while attempting to activate 'Namespace.ProductService'.)
    

    Would it be convenient for me to do the direct add to the wcf service?