I'm developing an .NET application (WinForms, .NET Framework 4.0) and i need to call a method from a web service.
The problem is that the client's web service is only accessible from inside its network. So at development time, i can't access it, so I can add it as a refference.
How should I proceed?
Should I create some kind of replica of that web service in my network?
Which would be the best option?
I'd get the WSDL and write a mock of it that i can call from my side.
I'd then make it return data that i was expecting and then later on have it return data that i wasn't expecting.
Then when you deploy it (should) be ok but you would need to run some integration tests.
The alternative it to tell them to open a port for you to use so that you can write the s/ware.
You could replicate the web service which returns dummy data.
I would wrap the call to the service in a separate abstraction layer, this would allow you to provide a different implementation if you wish during testing.
Eg. Something along the lines of..
public interface IXYZServiceInvoker
{
SomeData SomeServiceCall();
}
public class SomeServiceInvoker : IXYZServiceInvoker
{
public void SomeServiceCall()
{
//Calls a real service
}
}
public class FakeServiceInvoker : IXYZServiceInvoker
{
public SomeData SomeServiceCall()
{
//returns some dummy/test data
}
}
Related
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.
I'm going to be creating a service that needs to make a call to a hosted WCF service halfway around the world. This isn't that big of a deal since the number of transactions that will be made is relatively low. However, I need to pass in an instance of a class that will possibly be defined in the WCF to the necessary WCF function.
So my question is, will that instance of the class exist on my server? Or will I be contacting the host server every time I attempt to set a variable in the object?
EXAMPLE:`
public class Dog
{
public string noise;
public int numLegs;
}
public class doSomething
{
public string makeNoise(Dog x)
{
return x.noise;
}
}
`
All of those are defined in the WCF. So when I create an instance of class Dog locally, will that instance exist on my side or the server hosting the WCF service? If I'm setting 1000 instances of Dog, the latency will definitely build up. Whereas if I DON'T have to contact the server every time I make a change to my instance of Dog, then the only time I have to worry about latency is when I pass it into doSomething.makeNoise.
The host creates a new instance of the service class for each request, if you're using the default per-call instantiation method (which is the recommended way).
So either this is the IIS server which hosting your WCF service that creates an instance of your service class, or it is the ServiceHost instance that you've created inside your own self-hosting setup (a console app, a Windows service etc.).
The service class instance is used to handle your request - execute the appropriate method on the service class, send back any results - and then it's disposed again.
There's also the per-session mode in which case (assuming the binding you've chosen support sessions) your first call will create a service-class instance, and then your subsequent calls will go to the same, already created instance (until timeouts come into play etc.).
And there's also the singleton mode, where you have a single instance of the service class that handles all requests - this is however rather tricky to get right in terms of programming, and "challenged" in terms of scalability and performance
You will need to host your WCF service on a public available server (for example IIS). Successful hosting will provide you with a link for the svc file. Clicking on that will give you a link ending in singleWsdl. You need to copy that link. On your client side, the one that requires a reference to the WCF, you will need to Add Service Reference and pass that link. This will generate proxy code with Client objects that you can use to access your WCF ServiceOperation methods.
At a minimum you should have three projects. A website project to host the actual site. A WCF project to host your services. And finally a shared project, which should contain the classes you are concerned with (the models).
Both the website and wcf projects should reference the shared project, this way they both know how the models look.
The wcf project should return serialzed models as json objects, which I usually do by referencing Newtonsoft.Json.
Your website project should expect this json, and deserialize them, also using Newtonsoft.Json. This is why your class (model) should exist in the shared project, so you can use the same class on both sides of your service call.
Due to network architecture of our software, our application servers cannot connect directly to the web service of our customer. Because of this we have an integration server between the application servers and customer's servers. This integration server hosts a proxy web service. The problem is that the necessary credentials and some other additional information needs to be passed from the database at our application server to our proxy web service at the integration server.
I wouldn't want to pollute the API and pass the object containing credentials and additional information on each web service request. Additionally we have multiple integration servers which can be shut down at will so I cannot just initialize the web service with credentials and other information in a separate method because the subsequent web service requests might be passed to another integration server.
Is there a way to add some kind of SoapExtension which could be used to pass the information to my web service instance on each method? If not, is there something else I could do besides adding an argument to each web method and use that to pass the information?
The answer was actually quite obvious.
Firstly I need to create a class which is derived from SoapHeader. This class is used to store all credentials and other additional information. For easier explaining, let's give this class a name CredentialContainer.
In the actual web service class we need to add a new public property of type CredentialContainer. The property in this example is named Container.
Lastly, we have to add new attribute called SoapHeader to each method with WebMethod attribute. This handles transferring the information passed in the header of SOAP message to our CredentialContainer instance. Because new web service instance is created for each web service request, there are no risk even with multiple concurrent web service requests.
Here's the example code:
[WebService]
public class ExampleWebService
{
public CredentialContainer Container { get; set; }
[WebMethod]
[SoapHeader("Container")]
public void PerformSomething(string value)
{
var actualWebServiceClient = new MyWebServiceClient(Container.Url, ...);
actualWebServiceClient.SendValue(value);
}
}
public class CredentialContainer : SoapHeader
{
public string Url { get; set; }
...
}
Hi Im using silverlight ria services and trying to called a domain service method
the domain service class signature goes like this public class UserDomainService : DomainService
and I have a simple operation to return data
public IQueryable GetUsers()
{
return userService.GetAll()
).AsQueryable();
}
this compiles fine an a silverlight proxy is generated on the silverlight client side
how ever when makeing calls from silverlight eg
LoadOperation op = UserDomainContext.Load(UserDomainContext.GetUsers(),UserLoadedCallback,null);
int i = op.Entities.Count();
i is always 0, the domain servcice method is never hit when i put a breakpoint, please help!!!
You may not have enough detailed code to see the exact problem.
Have you put [EnableClientAccess()] on the service class?
The proxy must be generated because it must be compiling to run.
Hope it helps
I have a WCF service and methods are exposed as below:
public interface IService
{
[OperationContract]
bool Read();
[OperationContract]
bool Write();
}
public class MyService : IService
{
//Constructor
MyService()
{
//Initialization
}
public bool Read()
{
//Definition
}
public bool Write()
{
//Definition
}
}
I have a desktop based application that consumes the Web service through URL.
This web service can be deployed at multiple location so user can connect to any web service by choosing a url from the combo box.
In the client application I create a Service client dynamically as shown below:
ServiceReference1.DXMyServiceClient _client = null;
_client = new DXMyServiceClient ();
_client.Endpoint.Address = new System.ServiceModel.EndpointAddress(url);
Questions
While debugging I notice whenever I call any methods of web service each time the constructor of MyService is invoked ( if I am connected to the same service).
like for example when I do:
_client.Read();//MyService () constructor is called
_client.Write();//MyService () constructor is called
The problem is I have to do all the initialization again.. like if I connecting to the database then I have to again build the connection string and all stuff..
Is this the natural behavior or I am doing something wrong?
Secondly,
I want to validate user for the valid url ( of web service ). If it is connecting to the valid url or not.. I am doing that through Ping command..
What is the best approach for that!!
Questions While debugging I notice whenever I call any methods
of web service each time the constructor of MyService is invoked
(if I am connected to the same service).
The problem is I have to do all the initialization again..
like if I connecting to the database then I have to again
build the connection string and all stuff..
Yes, that's the default behavior, and the recommended behavior. You should NOT rely on any state on your service side! That is generally not a good idea and can lead to a multitude of problems.
In its recommended "per-call" mode, a WCF service has a ServiceHost() class instance running, which will listen for incoming requests / messages. Each time a request comes in, a new, fresh instance of the service class (that implements your service contract) is constructed to handle the request - just like each time you hit a URL in ASP.NET, your page class is instantiated to handle the request.
Yes, of course - this means you should keep your service classes simple and lean and not do a lot of initialization / state management. Anything that needs to be persisted between service calls should be put in a persistence store, like a database, anyway.
You should look at the ServiceBehaviorAttribute class and it's InstanceContextMode property. It controls the lifetime of your service object.
The problem is I have to do all the
initialization again.. like if I
connecting to the database then I have
to again build the connection string
and all stuff..
Is this the natural behavior or I am
doing something wrong?
By default InstanceContextMode is set to PerSession and ConcurrencyMode is set to Single. However, if you don't use session, basically every time you call service new instance is created. This is desired behavior because it is considered more scalable. If it is a problem for you, you should implement session between subsequent calls then for every session you will get one instance of your service.
Here is a guide how to do that: Using Sessions.