I were studying WCF here http://msdn.microsoft.com/ru-ru/library/bb386386.aspx and I successfully did Testing the Service step. However in Accessing the Service step I faced problems. It builds without any error, but when I tried to write smth to textLabel space and pressed button1 I get the error in button1_Click function, namely
ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
Error message
Could not find default endpoint element that references contract >'ServiceReference1.IService1' in the service model client configuaration section. This might be because no configuaration file >>was found for your application or because no end point element matching this contract could >>be found in the client element.
I find such code in the app.project file
<endpoint address="http://localhost:8733/Design_Time_Addresses/WcfServiceLibrary1/Service1/"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService11"
contract="ServiceReference1.IService1" name="BasicHttpBinding_IService11" />
I`m 100% sure, that code is without any error, because I copied it from the above site without any modification. So I will be glad to hear your assumptions how fix that.
You should specify the name of the endpoint when constructing the client:
using (var client = new ServiceReference1.Service1Client("BasicHttpBinding_IService11"))
{
client.SomeMethod();
}
or use * if you have only one endpoint in the config file:
using (var client = new ServiceReference1.Service1Client("*"))
{
client.SomeMethod();
}
The reason you need to specify the name is because you could have multiple endpoints (with different bindings for example) for the same service in the config file and if you do not specify the name the framework wouldn't know which endpoint you want to invoke.
Also notice how I have wrapped the IDisposable client in a using statement to ensure proper disposal once you have finished working with it.
Related
I have a simple web service that looks something like this:
[WebMethod]
public OrderForecastItem GetOrderForecast(int shipTo, string catalogName, bool showPricing)
{
return OrderForecastManager.GetOrderForecast(shipTo, catalogName, showPricing);
}
I'm calling it from another place in a fairly simple way:
using (OrderForecastWS.OrderForecastWS service = new OurSite.Web.Reporting.OrderForecastWS.OrderForecastWS())
{
OrderForecastItem orderForecastItems = service.GetOrderForecast(2585432, "DENTAL", false);
}
After some gymnastics to get the systems to understand that I'm talking about the same type of objects on the client and server sides (I had to open the Reference.cs file inside my Web References, delete the generated OrderForecastItem and add a link to our real OrderForecastItem), the system runs and attempts to get the item.
Unfortunately, it now bombs during the service call, claiming:
Exception There is an error in XML document (1, 1113).(InvalidOperationException)
I can go to the web service in a browser, put in the same values, and I get a seemingly valid XML response. (It looks okay to me, and I ran it through the XML parser at W3Schools, and it cleared it.)
I think the numbers in the error are supposed to be the line and character number...but the browser seems to reformat the xml document, so I can't easily see what the original (1, 1113) location is.
I don't see an easy way to intercept the response and examine it, since it seems to be blowing up as soon as it gets it.
How can I debug this?
If you control the service, you can step into it. If it is a part of your solution and hosted in VS WebDev on your local box, just F11 from Visual Studio, if service is hosted remotely (eg by IIS on other computer) run remote debugging tool on service host msdn, and then you will be able to step in to the service remotely.
By the way, you can tell Visual Studio to re-use objects from referenced libraries for types from the service: just pick configure Service Reference from service context menu and tell which libraries to re-use.
On second thought this error may happen if returned XML could not be deserialized into your business object. May happen when class is changed on either side, or you are trying to use different version of business library than service is using.
If you use Firefox, I'd recommend Firebug. You'll be able to easily view the response from the website in its original format, which might get you closer to the line and position you're looking for.
So I created winforms client and added wcf class library to the solution.
In winforms I do
ServiceHost svc = new ServiceHost(typeof(...), new Uri("net.pipe://localhost/MyNamedPipe")
and then svc.Open() which executes fine.
Now, how do I add a service reference so in same winforms I can get proxy for that wcf?
I only was able to generate that by using ASP.NET Development Server which started when winforms was ran and so I copied that url, stopped debugging (Development Server was still running) and then added a service reference from there. But that isn't correct I guess.
Of course I can reference wcf contract class directly and use it, but that is not proper either.
When you are controlling both ends like that, I prefer to use ChannelFactory:
NetNamedPipeBinding binding = new NetNamedPipeBinding();
EndpointAddress address = new EndpointAddress("net.pipe://localhost/MyNamedPipe");
ChannelFactory<YourInterface> factory = new ChannelFactory<YourInterface>(binding, address);
YourInterface yourInterface = factory.CreateChannel();
Have you tried adding a Service Reference... to the project, then entering your URI directly in the Address box of the dialog?
Note that this should be the complete URI, such as net.pipe://localhost/MyNamedPipe.
You can find step-by-step instructions from MSDN here.
I need to change my unit test from local to remote tests and so far I thought that all I had to do is change UrlToTest to point to another server... But VS keeps on insisting to create a Development Web Server instead of using the one that is already running.
So after reading some docs my question actually is do I have install Test Controller and Test Agent on both remote and local computer or what? What if the WebService is on Linux...
Note that I don't want to debug the application that I'm testing. I simply want tests to be executed for a WebService that is already running, that is deployed.
I probably should mention that all my tests consists of WebService calls and some checks like this:
[TestMethod()]
[HostType("ASP.NET")]
[AspNetDevelopmentServerHost("MainProjectName", "/")]
[UrlToTest("http://servername:port/websitename/TestingOnlyWebForm.aspx")]
public void LoginEmptyDataTest()
{
IUserService userService = CreateIUserService();
string email = "";
string password = "";
ReturnMessage<User> actual;
actual = userService.Login(email, password);
Assert.AreNotEqual(true, actual.Status);
Assert.AreNotEqual("db_error", actual.Info);
}
But I have also more complicated tests in which I change some data and send it to another WebService and so on.
Note that UrlToTest previously was pointing to localhost at which point it works but starts a developer server which is not what I want.
What you are trying to is not possible. All that generated unit test is trying to do is to run the test locally on the machine either using the development server by specifying AspNetDevelopmentServerHost or by using local IIS, when AspNetDevelopmentServerHost is not present.
If you want to test remote services right click your unit test project and add a service reference. Point to your service give it a namespace, say Services, and generate the proxies. Once you have the proxies generated just instantiate them and call the methods. Also remove all the unneeded attributes from your test. Your test should roughly look like this:
[TestMethod]
public void LoginEmptyDataTest()
{
using (var userServiceClient = new Services.UserServiceClient(
"BasicHttpBinding_IUserService",
"http://someremotehost/userservice.svc"))
{
var result = userServiceClient.Login("user", "password");
// asserts go here
}
}
This may solve your immediate problem however you should re-think what you are doing as #eglasius said. what happens if the code you call changes state internally? Next test might fail because of that so you need clean-up strategies otherwise your tests will be very brittle and you'll end up ignoring them.
Update: passing an address at run-time. Change the first parameter to whatever enpoint configuration name you have in your config file.
I'll take a stab in the dark at this one because I did something similar recently.
In my case my test project referenced the service project to provide visibility of the service and data contracts the Web Service implements and consumes.
To resolve this - though it can be ignored - move the contracts to a new project. Then have the service and test projects reference the new project, and remove the test projects' reference to the service.
Hope that makes sense!
Once the reference is removed, VS will no longer feel the need to start up your service when you run your tests.
You can disable the startup of the Service Host in the Project settings of your WCF Service Project. Right Click - WCF Options - Uncheck "Start WCF Service Host when debugging another project in the same solution".
You really have to consider the nature of what you're trying to achieve here.
It's hard to tell exactly what you're hitting of the code. I have the impression, you have is a website that calls a web service. You're testing the client code in that context, instead of just testing the service.
If that's the case, remove the attributes and point the url to the correct service like UrbaEsc guided you to. If you don't remove the attributes, you're running the calling code in the context of the site.
Even if the above is not the scenario, and based on what you replied to UrbanEsc in the comments, you'd then be testing an external call to the webservice initiated from the same site process.
You said:
"Found it, but VS still starts something on localhost and then trys to reach external server... Seems like VS is just not designed for real remote testing of webservices"
Read the above. I'd say you need to better understand what you're enabling. You can certainly test remote web services, like you can do pretty much anything you can code. You do that from client code that knows nothing different that what any other external client of the service would know. Support doesn't stop there, as you can do load testing of the service.
Note that what you're doing aren't unit tests, these are integration tests. Or depending on the scope of your system, full system tests.
I have created one WCF service , which is working fine, now i want to consume it in a client application.
using SVCutil.exe i have generated proxy and aap.settings for that service and added that to the client sln(console application)
But the problem is i am unable to access the wcf methods.
using System.ServiceModel;
namespace WCFClient
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
p. // not getting the wcf methods
}
}
}
what I am doing wrong?
Depends on how your service is called. When you created the service reference, you gave it a namespace name - in that namespace, there should be a class called (yourservicename)Client - instantiante one of those and get going.
You should find those files under the Service Reference - if you click on the "show all files" button in the Solution Explorer, you'll start seeing a ton of files under your service reference - one in particular should be Reference.cs. Those classes are defined in that file - you can check it out, it's a regular C# file.
Update: If you create your proxy using svcutil.exe, depending on your options used with svcutil, you should also get a .cs file that contains the classes needed.
svcutil http://yourserver/yourservice
would create a file called (your WSDL name).cs and an output.config in that directory where you run this command.
You can also specify a file name for the C# file:
svcutil http://yourserver/yourservice /out:MyService.cs
and then your file is called MyService.cs.
SvcUtil has a ton of options - can't explain them all to you, play around with them, read up on the MSDN docs for it.
Again, one of them will be called (your service name)Client. Include that *.cs file in your project, check the namespace, create an instance of the .....Client class and use it to call the WCF service.
Example:
Grab info from URL
svcutil http://www.ecubicle.net/iptocountry.asmx?wsdl /out:IP2CountryClient.cs
Include the resulting IP2CountryClient.cs in your project; by default, the classes in that file are in no particular namespace, so they're globally visible
Instantiate the client class iptocountrySoapClient
iptocountrySoapClient client = new iptocountrySoapClient();
Call methods - e.g. this one here:
string result = client.FindCountryAsString("82.82.82.82");
I'm connecting to a web service hosted by a third-party provider. I've added a service reference in my project to the web service, VS has generated all the references and classes needed.
I'm connecting with this piece of code (client name and methods anonymized):
using (var client = new Client())
{
try
{
client.Open();
var response = client.Method(...);
return response.Status;
}
catch (SoapException ex)
{
throw CreateServiceException(ex);
}
finally
{
client.Close();
}
}
When reaching the client.Open(), I get an exception with this message:
The top XML element '_return' from
namespace '' references distinct types
System.Boolean and
Service.Status.
Use XML attributes to specify another
XML name or namespace for the element
or types.
In reference.cs, I can see that the "_return" variable is decorated with
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="", Order=0)]
Is there a problem with the wsdl, the generated service reference or in my code?
Update: Generating the service as an old school Web Service solves the problem. I've marked Sixto's answer as accepted for now, but I'm still curious what could've caused the problem and if any parameters to the service generator could solve the original problem.
If you were able to create a service reference then the WSDL is valid. The exception message is saying you have namespace/type ambiguity problem with _return. The generated code is probably using it in some context as a boolean and in another context as a Service.Status type.
I don’t call the ClientBase.Open method before invoking a service method because I’ve never seen the need for it. I do always call the Close & Abort methods as appropriate. The Open method basically just changes the state of the client to no longer be configurable. I’m not sure how that would trigger code in the generated class since it is an inherited method. I’d try just removing that line and see if you get the same exception. Otherwise, if you haven’t already done so, search the generated code for all the places _return is used and see if you can manually sort-out the appropriate type. You may need different names for each context.
Another way to troubleshoot the WSDL is to create a Web Reference (assuming it’s an HTTP based service) and see if the generate code works as expected. If it does work, go with the ASMX client unless you have a need for WCF proxy capabilities.