I wanted to use IHttpClientFactory in my .NET Core project. The problem is that there are bulk of APIs that I need to consume. So should I use a single Typed Client for all the API's or should bifurcate those? All the API requests are to the same source.
public interface IStudentClient
{
}
public class StudentClient : IStudentClient
{
}
services.AddHttpClient<IStudentClient, StudentClient>();
I have followed the above structure and was planning to include all the API's inside IStudentClient and implement those in StudentClient. Now my question is, won't this will make the StudentClient more complex class when including all the API's implementation in only one class.
In my opinion writing one big typed client for all the access to a specific remote service is the right way to go. That's exactly the usage pattern envisioned by Microsoft for the typed http client.
At the same time I understand your concern, but the situation il less desperate than you might think it to be.
First of all you will get a huge interface and, consequently, a huge implementing class, but the responsibility of them is clear: the typed client has the responsibility of defining a proxy to access a remote web service (the student service in your example).
The typed client class isn't indeed complex: it can be huge, for sure, but it's stateless and just exposes methods to access the endpoints of the remote web service. Each method has a clear and well defined responsibility: accessing a specific endpoint on the remote web service; code like that is rarely complicated.
The only concern is consuming the interface IStudentClient from a controller or a service. The interface is huge, so if you inject it as a dependency in a consumer class you will violate the interface segregation principle. A possible solution for this problem is modeling smaller interfaces, shaped for the specific needs of the consumer classes.
Imagine that one of the endpoints exposed by your remote web service lets you get the details for a single student (it could be something like GET /students/{studentId}). This means that one of the methods exposed by IStudentClient will be GetStudentById(Guid studentId) which wraps the GET request to /students/{studentId}.
At this point you can define a smaller interface called IStudentProvider, shaped like this:
public interface IStudentProvider
{
StudentContract GetstudentById(Guid studentId);
}
Now you can inject the smaller interface IStudentProvider in your consumer classes (for example an MVC controller or a service class that you define in your application).
To implement the interface IStudentProvider you can do the following:
public class HttpStudentProvider : IStudentProvider
{
private readonly IStudentClient client;
public HttpStudentProvider(IStudentClient client)
{
this.client = client;
}
public StudentContract GetstudentById(Guid studentId)
{
return this.client.GetStudentById(studentId);
}
}
IMPORTANT DISCLAIMER: in order to keep the discussion simple I didn't use the Task class on the interfaces, but of course all of the methods should return Task<T> and accepts an instance of CancellationToken as a parameter, because http calls are natural asynchronous operations and you do not want to perform blocking calls with your http client.
How to register these classes on the DI container
The Microsoft DI container will offer you some extension methods to register a typed client. The service will be registered as a transient dependency, so each other service depending on it must be registered as a transient dependency too (in order to avoid the captive dependency issue).
This is the way you should register your services:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient<IStudentClient, StudentClient>();
services.AddTransient<IStudentProvider, HttpStudentProvider>();
}
Related
Our project consists of several ASP.NET projects which are microservices. There is a service that is in charge of authentication only, and then sends the requests down stream to the appropriate service.
The microservices are exposed only locally, so they assume that the request is authenticated and expose various controllers that the authenticator service can call.
However, we also expose "internal" controllers that we can call by using a debug endpoint that can only be accessed through VPN.
To differntiate between the internal and external controllers, we simply put them under different namespaces with the same name, but the internal controllers are prefixed with a dot (e.g. GET /.accounts for internal, and GET /accounts for external).
For the contracts classes, we use a subclass. For example:
public class CreateAccountRequest
{
[Required]
public string Name { get; set; }
public class Internal : CreateAccountRequest
{
public bool SomeRequiredInternalFlag { get; set; }
}
Then you can use the external/internal classes respectively.
The issue we are facing is the services themselves. For example, the AccountService has a CreateAsync method to create a new account with certain logic. However, the internal create account method needs a different logic.
The solutions we thought of:
Make the services classes partial with different names. For example, the external accounts service named AccountsService.cs and contains the external methods (e.g. CreateAsync(CreateAccountRequest request) and the internal accounts service named AccountsService.Internal.cs, and contains the internal methods (e.g. CreateAsync(CreateAccountRequest.Internal request).
Create a separate class for the internal service, with the same dependencies, and register it through the DI.
Create a subclass for the internal service methods, and expose an Internal property which is an instance of that subclass.
Do you guys have other ideas maybe?
I have service now wfc services in my application each service has different base class
public partial class ServiceNowSoapClient : SNtoVSTSIntegration.SNInterfaceIncident.ServiceNowSoap
public partial class ServiceNowSoapClient : SNInterfaceAttachmentMetadata.ServiceNowSoap
The problem is that there's no simple base class for a WCF Web Service
how to create generic class which return me object of ServiceNowSoapClient
Is ther any way to do this?
Different service base addresses correspond to different service endpoint addresses. We must specify the service endpoint address when instantiating the client proxy, so there is no way to implement a generic class for all service proxy classes.
Besides, Channel Factory also can encapsulate the creation of a client proxy.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-use-the-channelfactory
Feel free to let me know if there is anything I can help with.
Is it possible to add as a reference and call an APIs controller methods as a service on another project? What are the alternatives if this is not possible?
Web API types of applications do not have a 'service reference' anymore. They do not produce WSDL, so you cannot add them like you used to do with SOAP services. No proxy classes are generated... no intelli-sense.
Web APIs are typically called with lightweight http requests and return JSON and not XML based SOAP responses like traditional ASMX or SVC (WCF) services.
You have some reading to do I believe.
To answer your question, you CAN indeed call API services from a web application (say a controller method in an MVC app), but you won't have proxy classes to help you.
https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client
When you create a service reference you end up with a reference to an interface and a client class that implements the interface.
You can follow pretty much the same pattern without a WCF service reference. In fact, that's one of the benefits of depending on an interface. It doesn't matter to your application whether the implementation is a call to a WCF service, an API, or anything else.
First declare an interface that describes how you will interact with the API.
public interface ISomethingService
{
public SomeData GetSomeData(string id);
}
That interface is what your other classes depend on. They'll never know what the implementation is.
Your implementation could be something like this. I'm using RestSharp to create the API client because I like it better than managing an HttpClient:
public class SomethingServiceApiClient : ISomethingService
{
private readonly string _baseUrl;
public SomethingServiceApiClient(string baseUrl)
{
_baseUrl = baseUrl;
}
public SomeData GetSomeData(string id)
{
var client = new RestClient(_baseUrl);
var request = new RestRequest($"something/{id}", Method.POST);
var response = client.Execute<SomeData>(request);
return response.Data;
}
}
In your startup you would register this class as the implementation of ISomethingService and pass the base url from configuration. That would also allow you to pass a different url for development, production, etc. if needed.
Ultimately it's no different from depending on a WCF service. One difference is that a WCF service defines an interface, but in this case you have to do it. That's actually a good thing, because it's better for your application to define its own interface rather than directly depending on the ones someone else provides. You can wrap their interface or API in a class that implements your own interface, giving you control over the interface you depend on.
My project is a consumer for a 3rd party web service (old school web service vs. WCF service), and it has two versions, the "sandbox" (staging), and prod services. The APIs on these services are almost identical, and I am looking for a way to cleanly switch between the two versions, preferably without using conditional compilation.
I instinctively rushed off and extracted an interface from the client generated by Visual Studio's "Add web reference", i.e. AgentImport but that class is not partial, so I can't make it derive from the interface, or from any other superclass. I already have the creation of AgentImport instances nicely encapsulated in an abstract base for all my clients of AgentImport, but without using more risky compiler directives, how can I switch between v1 and v2 of AgentImport?
Some code:
using Clients.PrivateProperty.AgencyServicesApiService;
namespace Client.PrivateProperty
{
public abstract class PrivPropFacilityBase
{
protected static AgentImport Client;
protected PrivPropFacilityBase()
{
Client = new AgentImport();
Client.Timeout = 10000;
}
protected virtual AgentImport GetClient()
{
return new AgentImport();
}
}
}
I have tried adding service references instead of web references, as advised in comments below, to at least get access to partial classes, but when I add the first service reference, for the production service, and extract an interface from the auto-generated SOAP client, i.e. IAsapiClient, that interface references objects declared in other auto-generated classes, in the same namespace as the client, e.g. SecurityToken:
void UpdateUniqueAgentID(string PrivatePropertyAgentId, string AgentId, AgencyServicesApiService.SecurityToken Token);
If I add the second service reference, for the staging service, that second auto-generated SOAP client references objects in its own namespace, e.g. now it uses AgencyServicesApiSandbox.SecurityToken, so my compiler tells me that it doesn't implement the interface I extracted the first time. I am then left with the messy business of having to extract an new interface for each object that the main interface, IAsapiClient, references, so that this main interface only uses the extracted contracts, not actual class names.
In pursuing the above< I have reached the conclusion that my only feasible, and lowest risk, way forward is to use two client projects, one specifically for the production service, and one for the staging service. Then, at execution time, I only need to worry about dynamically choosing between two well known, i.e. not auto-generated, client objects.
Is it possible to send objects through RoutingService to peer WCF services without having the router know about the exact type of these objects ?
My intention is to create a router once for all, then be able to add new WCF services, dynamically add them to the routing table, and allow clients to communicate with these services without having to stop, change the code of the router, then start it again.
I was thinking of a generic contract like this:
[DataContract]
public class RequestObject
{
}
[DataContract]
public class ReplyObject
{
}
[ServiceContract]
public interface IGenericServiceInterface
{
[OperationContract]
ReplyObject DoJob(string jobType, RequestObject request);
}
I could put this in a common library that all 3 components link to (client, router, services). But, I am not sure, it will be possible to derive new sub classes to allow new clients/services with new data exchanges to be added without having to change the router.
Any advise ? is it possible for the solution to work when encryption is enforced through clients till services ?
Thanks in advance.
There's a good msdn on using the Message class in WCF to build contract agnostic endpoints. Does not use routing service, but you could build a router using this:
http://msdn.microsoft.com/en-us/library/ms734675.aspx