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.
Related
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>();
}
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.
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
At client side, I have this class without [DataContract]:
public class UserEntity
{
public string login;
public string password;
}
when I put [DataContract] and refresh the reference of this class at WCF side, then I can't initiate the web service. It says an error:
cannot create metadata...
What's wrong?
Are you sure that you actually know, why you can't refresh the reference? I mean you add [DataMember] - and it fails, you remove it - it works? Or it works several days ago and now you add [DataMember] (and many other stuff) and it not works now?
But anyway, the easiest way to solve "refresh reference" issues - to refresh reference manually with SvcUtil.exe. In this case error message would be much more descriptive the simple "oops! error!".
What is client and server side in your case? What is refreshing reference on the WCF side? Your description is very uncommon. Here is description how to create service with complex data type and WCF Class library:
Create WCF class library
Add data contract to the class library
Add service to class library
Implement service contract and service in the class library
Add host project
Reference WCF class library from host project
Host service from class library in host project
Add Metadata endpoint to your hosted service
Create client project
Run the host project outside the visual studio
Use Add service reference to create proxy on WCF service hosted in your host project
Implment code to call your service through created proxy
As you see there is no modification of data contract on the client side and no refreshing WCF service.
Is a web service reference the proxy class itself? Or is it the classes created inside that you see in object explorer when you look at your web service reference?
example, I created this web service reference
http://www.elbalazo.net/post/TestWebProject%5FObjectExplorer%5FWebReference.jpg
I assume ServiceAuthResponse is one proxy class inside my web service reference?
When you add the WebService reference a proxy class is generated for you.
In your example it looks like LitleWebService will be your service proxy, ServiceAuthResponse sounds more like a data contract that will be used by the service. If you read about the Proxy Design Pattern it may be of some interest
Normally you proxy will inherit from ClientBase, this is where you can specify the service contract.
public class MyProxy : ClientBase<IServiceContract>, IServiceContract