WCF —— Consuming WCF Services in .NET Core – Best Practices(转发)

https://www.thecodebuzz.com/consuming-wcf-web-services-in-net-core-best-practices/

 

Today in this article on best practices, we shall learn how to consume WCF or ASMX services easily in .NET Core C# based application (like ASP.NET Core API or ASP.NET Core web applications or any other type of projects)

Today we shall cover below techniques of consuming WCF services in .NET or ASP.NET core applications,

 

  • Connected Service in Visual Studio IDE
  • ServiceModel Metadata Global CLI tools(svcutil.exe)
  • Using WSDL to create a proxy
  • Using the Channel Factory approach
  • Enable existing WCF services as REST API

 

WCF (Windows Communication Foundation) is a rich programming platform for building service-oriented applications. Today seamless integration of application in an Enterprise is a standard and with the recent popularity of the framework like RESTful services (WebAPI), It is possible that an organization may need existing WCF or Web legacy services integrated with modern frameworks and technologies.

 

Connecting WCF service from .NET Core

 

To use WCF services in .NET Core, you need to create a proxy client of the required service.

 

Proxy is actually a contract equivalent of actual service and contains complete details of the Interface and method exposed by WCF service.

 

One can also use the Channel factory technique to connect to the WCF service easily.

 

Ways to consume WCF WebServices in .NET Core application

 

We shall see below multiple ways to consume WCF services in C# based .NET Core application.

 

 

Getting Started

 

To get started, you certainly need a WCF service. I already have a sample WCF service with contract details as below. This service we will be consuming within the .NET Core WebAPI application.

You can use the below-discussed techniques for other types of applications as well like .NET Core Console or Form application (.NET Core 3.1) or ASP.NET Core MVC, etc.

 

WCF Service Contract

 

 

This service has a method GetOrderData() which returns an order data for a given order ID input.

 

Create ASP.NET Core API

 

Let’s start creating an API application (you can create any other type of project as required.)

Let’s use ASP.NET Core 2.0 or 3.1

 

Consuming WCF Web Services in .NET Core

 

Above templates creates skeleton code with ready to use controller with GET and Other HTTP methods.

 

 

1. Using Connected Services

 

This is a very simple technique of creating a proxy within the target application. This option is available in .NET Core or .NET Standards.

 

Connected services let’s you create client-side code easily using direct Service URI (If available) or using WSDL file (If shared by the vendor or third party).

 

I have discussed both approaches in detail which are based on ‘Connected Services’ using WSDL and URI.

 

  • Configure WCF web service reference using URI
  • Configure WCF web service reference using WSDL file

 

 

Note: Connected service option is more stable in VS2017 (15.8.0) and above versions only. For the lower version, this option may or may not work. If you come across any issue please try using the 2nd preferred approach- Using ServiceModel MetadataCLI tool which can be used for both VSCode and VS2017 IDE based application.

 

Right-click on “Connected services” as below. This option will be available for all .NET Core or .NET Standards library as given below

 

Or

 

Please select the option “Microsoft WCF Web Service…” as highlighted below,

 

Configure WCF web service reference using WSDL

 

Configure WCF web service reference using URI

 

Let’s look at how to create client code for .NET Core using the service URL.

As shown below please enter the URI as below and click on ‘Next’.

 

Consume WCF web service using WSDL

 

I got the WCF service URL from the sample service as below.

This URL will be generally in the format of .svc. You shall be entering your actual provider/client URL.

 

 

Once you click ‘finish’ you shall see below windows on the progress of service metadata generation and scaffolding etc.

 

 

Post successful completion of the above steps, the service reference will be added as below in .NET Core WebAPI

 

Consume WCF web service using connected service

 

This Reference.cs will have a client class as highlighted below which needs to be instantiated and used to connect with the WCF Service,

 

 

Lets now go to WebAPI method and use the class OrderServiceClient to call the actual WCF service and get the results.

 

As a good practice put this proxy generated class in a proper layer of service. You may consider ‘IntegrationLayer’ or ‘InfraLayer’ repository etc.


The file can also be modified for endpoint configuration to support multiple URLs or proxy and the same can be provided through Configuration in .NET Core or Environment variables etc.

 

Update Controller method to use Proxy client

 

Below we are using Proxy client instance to call WCF service.

 

 

The above logic is just a demonstration. You could create a static shared instance and can use it for all other methods.

 

Here is the successful result finally from a WCF service within .NET Core WebAPI,

 

 

You are all set !!

If you only have access to the WSDL definition, then please use the below techniques to create client code.

 

Configure WCF web service reference using WSDL

 

If you have access to WSDL file (Web Services Description Language) then the same above technique can also be used to create client code for .NET Core.

 

A typical look of .wsdl will be a below,

 

Please use the same connected service configuration and browse through WSDL file as shown below,

 

Using WSDL Schema for Proxy generation

Click on Next and choose the option as appropriate.

Finally, you shall see proxy scaffolding generation which is already explained above.

Please follow the same above steps to connect a WCF service from .NET Core app.

Happy Coding !!!

 

2. Using ServiceModel Metadata (svcutil.exe) Global Tool

 

The above option of ‘Connected Services‘ was very easy and simple to use.

However, this UI extension will make you fuzzy due to dependency on the right version (Visual Studio 2017, and the below versions are not stable.Works fine in VS2019 and above version).

 

SVC-UTIL utility available as NuGet package generates proxy(client-code) using URI and WSDL both approaches. Please see below article for more details on this approach,

 

 

If you using other IDE like VSCode or looking for global working cross-platform on Linux, macOS, and Windows then you can use this option for creating client-side code.

 

3. Using Channel Factory Method

 

Don’t want to create/maintain proxy? Yes ..then this could be one of the preferred approach if you don’t want to maintain a proxy code. Please see below article for more details on this approach,

 

4. Enable existing WCF services as REST API

 

If you need to enable WCF services for additional endpoints like a REST API endpoint you can do easily so that it can be consumed across any type client

The good news is you can do it without breaking any client.

This technique will give you breather time if budget or capacity etc. issues are hindering you.

 

 

Do you have any comments or ideas or any better suggestions to share?

 

Please sound off your comments below.

 

Summary

 

WCF Web Service integration with modern technologies like .NET Core services is possible. In this post, we learned three possible approaches like using,

  • ‘Connected Services’ using Visual Studio
  • ‘ServiceModel Metadata (svcutil.exe)’ a CLI utility and
  • Channel Factory approach.

First, two techniques use proxy scaffolding of service contracts and last techniques make use of ChannelFactory thereby allowing connecting .NET Core application with WCF Web services.

 



Please bookmark this page and share this article with your friends. Please Subscribe to the blog to get a notification on freshly published best practices of software development.

 

 

Use ChannelFactory to Consume WCF Web Services in .NET Core

In our previous article, we learned a few techniques of consuming WCF services in .NET Core applications using proxy generations and for the same, we looked at few useful tools like using

 

Today we will see yet another simple approach of using a Channelfactory for consuming WCF( Windows Communication Foundation) services in the .NET Core applications

Let’s first see the pros and cons of this approach before digging into more details.

 

Advantages of ChannelFactory

 

  • No need to create or maintain a proxy/client code
  • No need to add a service reference or connected service reference
  • This is the best option provided the contract definition is known.

 

Disadvantage

 

  • Require prior knowledge service contract definition

 

Please note that Channel factory options can be leveraged if the service contract definition is known already. Perfect for an internal organization where service contract definition can be shared easily.

 

Getting Started

 

I already have a sample WCF service with contract details as below. This service we will be consuming within the .NET Core WebAPI application.

However, you can use the below technique for other types of applications as well like C# .NET Core Console, Form application (.NET Core 3.0) or ASP.NET Core MVC app, etc.

 

WCF Service Contract

 

 

This service has a method GetOrderData() which returns an order data for a given order ID input.

Let’s run this WCF service locally. We shall try connecting this service using Channel factory from the .NET Core app.

 

Create ASP.NET Core WebAPI

 

Let’s start creating a WebAPI application (you can create any other type of project as required.)

 

 

Please add below code in any of the Controller methods.

 

This is an example only, we will add code to the GET method,

 

1
2
3
4
5
6
7
8
9
10
11
12
13
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
    BasicHttpBinding myBinding = new BasicHttpBinding();
    EndpointAddress myEndpoint = new
    EndpointAddress("http://localhost:60141/Order.svc");
    ChannelFactory<IOrderService> myChannelFactory =
    new ChannelFactory<IOrderService>(myBinding, myEndpoint);
    // Create a channel
    IOrderService wcfClient1 = myChannelFactory.CreateChannel();
    string result = wcfClient1.GetOrderData(id);
    return result;
}

 

As shown above, ChannelFactory lets you define endpoint – ABC i.e AddressBinding, and Contract for service and helps you connect to the target WCF service from .NET Core framework.

 

The generic interface ChannelFactory<TChannel> class helps to create a communication channel with a WCF service. Please do also check cache-control techniques for channel factories to get better performance.

 

Next step is to add the contract/Interface definition in your .NET core project.

 

The Contract/Interface definition looks as below,

 

 

That’s all. Simply execute your GET API, you shall see result as below.

 

This was very much basic we covered in this article. I hope this helps you get started.

You can also use Channel Factory with Credentials if needed.

 

Are you dealing with any complex scenarios? Please do let me know or sound off your comments below.

 

Other references:

 

Summary:

 

WCF Web Service integration with modern technologies like .NET Core services is possible. In this post, we learned the simple approach of using ChannelFactory to connect any .NET Core application with WCF Web services. We understood with this approach we need not have to create a proxy (client-side) code or maintain service references etc. as ChannelFactory wraps up those things provided Service contract definition is provided.

 



Please bookmark this page and share this article with your friends. Please Subscribe to the blog to get a notification on freshly published best practices of software development.

 

Close and Abort release resources safely when network connections have dropped

The UsingUsing sample demonstrates using the Close and Abort methods to clean up resources when using a typed client. The using statement causes exceptions when the network connection is not robust. This sample is based on the Getting Started that implements a calculator service. In this sample, the client is a console application (.exe) and the service is hosted by Internet Information Services (IIS).

 

This sample shows two of the common problems that occur when using the C# "using" statement with typed clients, as well as code that correctly cleans up after exceptions.

 

The C# "using" statement results in a call to Dispose(). This is the same as Close(), which may throw exceptions when a network error occurs. Because the call to Dispose() happens implicitly at the closing brace of the "using" block, this source of exceptions is likely to go unnoticed both by people writing the code and reading the code. This represents a potential source of application errors.

The first problem, illustrated in the DemonstrateProblemUsingCanThrow method, is that the closing brace throws an exception and the code after the closing brace does not execute:

 

using (CalculatorClient client = new CalculatorClient())
{
    ...
} // <-- this line might throw
Console.WriteLine("Hope this code wasn't important, because it might not happen.");

Even if nothing inside the using block throws an exception or all exceptions inside the using block are caught, the Console.WriteLine might not happen because the implicit Dispose() call at the closing brace might throw an exception.

The second problem, illustrated in the DemonstrateProblemUsingCanThrowAndMask method, is another implication of the closing brace throwing an exception:

C#
using (CalculatorClient client = new CalculatorClient())
{
    ...
    throw new ApplicationException("Hope this exception was not important, because "+
                                   "it might be masked by the Close exception.");
} // <-- this line might throw an exception.

Because the Dispose() occurs inside a "finally" block, the ApplicationException is never seen outside the using block if the Dispose() fails. If the code outside must know about when the ApplicationException occurs, the "using" construct may cause problems by masking this exception.

Finally, the sample demonstrates how to clean up correctly when exceptions occur in DemonstrateCleanupWithExceptions. This uses a try/catch block to report errors and call Abort. See the Expected Exceptions sample for more details about catching exceptions from client calls.

C#
try
{
    ...
    client.Close();
}
catch (CommunicationException e)
{
    ...
    client.Abort();
}
catch (TimeoutException e)
{
    ...
    client.Abort();
}
catch (Exception e)
{
    ...
    client.Abort();
    throw;
}

 Note

The using statement and ServiceHost: Many self-hosting applications do little more than host a service, and ServiceHost.Close rarely throws an exception, so such applications can safely use the using statement with ServiceHost. However, be aware that ServiceHost.Close can throw a CommunicationException, so if your application continues after closing the ServiceHost, you should avoid the using statement and follow the pattern previously given.

When you run the sample, the operation responses and exceptions are displayed in the client console window.

The client process runs three scenarios, each of which attempts to call Divide. The first scenario demonstrates code being skipped because of an exception from Dispose(). The second scenario demonstrates an important exception being masked because of an exception from Dispose(). The third scenario demonstrates correct clean up.

The expected output from the client process is:

Console
=
= Demonstrating problem:  closing brace of using statement can throw.
=
Got System.ServiceModel.CommunicationException from Divide.
Got System.ServiceModel.Security.MessageSecurityException
=
= Demonstrating problem:  closing brace of using statement can mask other Exceptions.
=
Got System.ServiceModel.CommunicationException from Divide.
Got System.ServiceModel.Security.MessageSecurityException
=
= Demonstrating cleanup with Exceptions.
=
Calling client.Add(0.0, 0.0);
        client.Add(0.0, 0.0); returned 0
Calling client.Divide(0.0, 0.0);
Got System.ServiceModel.CommunicationException from Divide.

Press <ENTER> to terminate client.

To set up, build, and run the sample

  1. Ensure that you have performed the One-Time Setup Procedure for the Windows Communication Foundation Samples.

  2. To build the C# or Visual Basic .NET edition of the solution, follow the instructions in Building the Windows Communication Foundation Samples.

  3. To run the sample in a single- or cross-machine configuration, follow the instructions in Running the Windows Communication Foundation Samples.

 

posted @ 2022-01-17 12:20  PanPan003  阅读(2862)  评论(0编辑  收藏  举报