I've created a REST web service that I need to consume from within an asp.net app. The service is hosted from a console window. I can get it running fine, and I can get output from it as well when surfing to it in a web browser. The problem is, when I try to "Add Service Reference" from my asp.net app, it complains of various things depending on which service URL I point it at. End result is I cannot figure out how to add the service reference.
My Interface is defined like so:
[ServiceContract]
public interface IWave {
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "/devices")]
List<Device> getDevices();
...
}
Here's how I'm hosting my service:
// Port is 1178
var endPoint = new EndpointAddress(string.Format("http://localhost:{0}/wave", port));
var waveServiceSingleton = new WaveSVC();
binding = new WebHttpBinding();
var behavior = new WebHttpBehavior();
behavior.FaultExceptionEnabled = true;
host = new WebServiceHost(waveServiceSingleton, endPoint.Uri);
// Get the service debug behavior and tell it to include details about errors
ServiceDebugBehavior sdb;
sdb = host.Description.Behaviors.Find<ServiceDebugBehavior>();
sdb.IncludeExceptionDetailInFaults = true;
host.AddServiceEndpoint(typeof(IWave), binding, "");
// Add mex endpoint
ServiceMetadataBehavior mexBehavior = new ServiceMetadataBehavior();
mexBehavior.HttpGetEnabled = true;
host.Description.Behaviors.Add(mexBehavior);
host.AddServiceEndpoint(typeof(IWave), MetadataExchangeBindings.CreateMexHttpBinding(), endPoint.Uri.AbsoluteUri + "/mex");
host.Open();
When I browse to http://localhost:1180/wave/devices, I see a json string in the body of my browser. This is expected and works as desired. I cannot point my "Add Service Reference" wizard to this URL, as it complains that:
The document at the url http://localhost:1178/wave/devices was not recognized as a known document type.
The error message from each known type may help you fix the problem:
- Report from 'XML Schema' is 'Data at the root level is invalid. Line 1, position 1.'.
- Report from 'DISCO Document' is 'Data at the root level is invalid. Line 1, position 1.'.
- Report from 'WSDL Document' is 'There is an error in XML document (1, 1).'.
- Data at the root level is invalid. Line 1, position 1.
Metadata contains a reference that cannot be resolved: 'http://localhost:1178/wave/devices'.
The remote server returned an unexpected response: (405) Method Not Allowed.
The remote server returned an error: (405) Method Not Allowed.
If the service is defined in the current solution, try building the solution and adding the service reference again.
I have a nagging suspicion that I need to point my "Add Service Reference" to the mex, but that doesn't work either and indeed, when I browse to the mex address of http://localhost:1178/wave/mex, I get a blank page.
EDIT 1
Just to eliminate JSON being the culprit, I changed my contract to output Xml instead of Json. The result was the same: I can't add a service reference using this URL: http://localhost:1178/zwave/devices/xml (even though that URL produces XML).
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Xml, UriTemplate= "/devices/xml")]
Thanks in advance for any help provided.
Traditionally, the "add web reference" option you are using in Visual Studio is meant for referencing XML Web Services only. Your service is defined in terms of rest/json and not in terms of soap/xml/wsdl that visual studio expects.
I suspect that Visual Studio simply isn't able to generate proxies for a json/rest service as yours. This is confirmed in the documentation on the WCF rest starter kit for .NET 3.5 (see the section "Consuming RESTful Services with HttpClient", search for "not possible to generate strongly-typed proxies like you’re used to with SOAP").
I'm not sure whether it is still unsupported in VS2010 / .NET 4.0, but I think you have to look for another option than "add web reference".
Perhaps found for the blank page:
Replace
host = new WebServiceHost(waveServiceSingleton, endPoint.Uri);
with
host = new ServiceHost(waveServiceSingleton, endPoint.Uri);
this worked for me
Related
I'm working on client application to utilize SOAP web service. Added SOAP web services as Service reference. It connects to IBM server and server requires WS-Security basic authentification.
Called with default settings and got an error(no authentication header)
Modified code to look like so:
var service = new RealTimeOnlineClient();
service.ClientCredentials.UserName.UserName = "xxxxx";
service.ClientCredentials.UserName.Password = "yyyyy";
Now when I look at response in Fiddler - works properly (I get expected envelope from server), I get proper envelope back.
However, I get exception from WCF:
Security processor was unable to find a security header in the message. This might be because the message is an unsecured fault or because there is a binding mismatch between the communicating parties. This can occur if the service is configured for security and the client is not using security.
Quick search and bunch of answers here on SO points me to HotFix from Microsoft where they added new property EnableUnsecuredResponse. Problem is - I can't figure out WHERE to apply this property in my code OR in config. Adding to security tag in web.config doesn't work (errors out can't find property).
I understand hotfix came out for .NET 3.5 and most questions from 2009-2010. It should be in 4.5 already, correct? How do I apply this property to my code?
I had to add following code to alter value of "EnableUnsecureResponse"
var service = new RealTimeOnlineClient();
service.ClientCredentials.UserName.UserName = "xxxxx";
service.ClientCredentials.UserName.Password = "yyyyy";
var elements = service.Endpoint.Binding.CreateBindingElements();
elements.Find<SecurityBindingElement>().EnableUnsecuredResponse = true;
service.Endpoint.Binding = new CustomBinding(elements);
I want to make a simple WCF Hello world client which could connect to a WCF REST service.
But I've got the following error:
"Could not find default endpoint element that references contract 'ServiceReference1.IService1' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element."
What I did:
-I created a new project called "WCFerror" with the "WCF Service Application" template
-My web.config is like this: http://pastebin.com/KEGqRgPr
-My service interface is also simple:
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebGet(UriTemplate = "GetData?value={value}", ResponseFormat = WebMessageFormat.Json)]
string GetData(int value);
}
-I created a new Console Application.
-I started a new instance of my WCFerror service (via "Start Debugging"), it is hosted, I tried it out in a web browser
( like: http://localhost:58475/Service1.svc/GetData?value=4 ), it worked fine.
-Then I added a service reference to the Console Application (the address was: http://localhost:58475/Service1.svc) and in the background, the svcutil generated the Client code, and an app.config - but an empty app.config!
-So my client not works:
ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
Console.WriteLine(client.GetData(4));
-I tried to run the svcutil via the command prompt like this:
svcutil.exe /language:cs /out:GeneratedProxy.cs /config:app.config http://localhost:58475/Service1.svc
But it generates the same empty app.config.
What did I do wrong? :(
Add Service Reference uses WSDL or WS-MetadataExchange. Both of these are SOAP constructs. REST does not have a metadata standard. You will have to roll the messages yourself, preferably using a framework. Have you looked at HttpClient that is part of the new Web API? Its available via Nuget
I would like to build an app in C# that connects to an Apache AXIS web service and performs the following operations via SOAP.
Login in to the server.
POST string data to server
Receive and display server response
Here's the tough part. I do not have access to the server, nor do I know where the .JWS file is located on the server. I was able to get to the WSDL file in my web browser, so I know a "Login" operation exists as well as an operation to take in data.
I have tried accessing the web service via URL, but I keep getting this message:
Hi there, this is an AXIS service!
Perhaps there will be a form for
invoking the service here...
In summary, is there anyway I can connect to this web service when all I have is the URL of the WSDL file? Are web services accessible via URL?
Thank you
Use WCF, and generate client proxies to the web service using the svcutil.exe tool.
running svcutil.exe http://url.to/webservice?WSDL the_wsdl.wsdl /language:C# should generate proxy classes you can use in your C# project, and you'd call the service e.g. like
BasicHttpBinding myBinding = new BasicHttpBinding(); //might not even need these
// 2 lines if you ran svcutil.exe directly on the web service URL
EndpointAddress myEndpoint = new EndpointAddress("http://url.to/webservice");
TestClient client = new TestClient(myBinding,myEndpoint); //the generated classes
// svcutil.exe created
client.SomeOperation(42); // call an SomeOperation of the web service
Thanks for everyone's help. Looking back on this question, I can see how severely confused I was. Here is the solution I followed.
Assuming you know the URL of the WSDL file of the service you wish to connect to then just do the following.
Boot up Visual Studio
On the top toolbar navigate to Data -> Add New Data Source then choose Service in the new dialog
In the address bar, enter the URL of the wsdl file (EXAMPLE: http://server.com/services/displayName?wsdl)
Near the bottom of the dialog, change the namespace to something relevant to the project (EXAMPLE: sampleService)
Now Visual Studio should compile the client proxies for you that you can use to access the web services on your server. To access one of the services, all you need to do is create a new object from the class.
//Example
sampleService.ClassName test = new sampleService.ClassName();
test.displayName("Jack");
See http://msdn.microsoft.com/en-us/library/bb552364.aspx for a starting point
I'm trying to build a C# service in .NET 3.5 that supports both SOAP - and shows the WSDL - and REST.
The SOAP service and WSDL generation was easy enough to do using the ServiceHost and a BasicHttpBinding classes. Got that working and the client was happy.
Because the SOAP calls all used simple parameters, the client developers requested a REST interface for some of the commands. So I changed the ServiceHost class to a WebServiceHost, added necessary WebInvoke and WebGet attributes, added a WebHttpBinding class, and bingo - REST and SOAP were both working out of one service. Way cool, change one interface and both REST and SOAP got the new stuff.
But one problem - the WSDL no longer gets generated. I couldn't browse to http://server/service?wsdl and get the WSDL file. Checking the MSDN docs, that appears to be behavior for a default WebServiceHost.
Question: can I override this behavior so that the WSDL could be obtained? Doesn't have to the same URL as before - it can change - but I just need to have some URL into service to get the WSDL for those SOAP developers.
When you say "added a WebHttpBinding class", it sounds like you are doing a lot of the configuration in code as opposed to in configuration files.
If this is the case, you could try moving the configuration to the configuration file. Then create 2 endpoints for the contract one REST and one SOAP, with 2 different addresses and bindings.
But one problem - the WSDL no longer
gets generated. I couldn't browse to
http://server/service?wsdl and get the
WSDL file. Checking the MSDN docs,
that appears to be behavior for a
default WebServiceHost.
Yes - that's one of the drawbacks of REST - no more WSDL, no more machine-readable service description. You need to hope the service provider gives you a usable and up to date documentation on what you can do.
There's no WSDL for REST - period. Can't be turned on or anything - it just doesn't exist.
There are some efforts under way to provide something similar - called WADL (Web Application Description Language), but as far as I know, it's still far from an established standard by any means. Also see: Do we need WADL?
Circa, 2007, WSDL v2.0 is supposed to be able to describe RESTful services. I have found that with WCF in .Net v4.0, that the WDSL generated from a purely RESTful service is invalid (WSDL v1.0?).
I created a similar project that exposes both SOAP and RESTful endpoints, and enabled this by, as you did, modifying the interface as such:
// Get all Categories - complex object response
[OperationContract] // categories
[WebGet(BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "GetAllCategories")]
CategoryCollection GetAllCategories(); // SubSonic object
[OperationContract] // categories - respond with a JSON object
[WebGet(ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "GetAllCategories.JSON")]
CategoryCollection GetAllCategoriesJSON(); // SubSonic object
One caveat to this is that all input parameters now must be of type string for all SOAP requests.
Any way of getting around this?
I am developing a c# desktop application and using a webservies which is developed in a php application when i try to consume that application. I just add web REference of that web service and try to access throught the following code
WebReference.TestWSDL pdl = new testingApp.WebReference.TestWSDL();
string copy = pdl.verify("testing");
it throws the error when i try to call the method verify. the error is
Possible SOAP version mismatch: Envelope namespace http://schemas.xmlsoap.org/wsdl/ was unexpected. Expecting http://schemas.xmlsoap.org/soap/envelope/.
and the web service link was like
http://171.139.101.12/code/index.php/webservice/wsdl
The error you are encountering is informing you that when you invoke the webservice, you are being given the WSDL (Web Service Definition Language) for the service - this is the metadata that describes the service functions, but cannot actually be used to invoke the service. Usually, you access the WSDL by appending either "?wsdl" or "wsdl" to the service URI.
There are two elements to the webservice you are attempting to consume.
The actual service exists at:
http://171.139.101.12/code/index.php/webservice
The metadata describing it, which Visual Studio via wsdl.exe used to generate a proxy, resides here:
http://171.139.101.12/code/index.php/webservice/wsdl
You need to edit the properties of the Web Reference and update the address appropriately. Alternatively, you can alter the properties of the pdl variable, and change the endpoint in code.