Invalid Operation Exception - c#

I created a WCF Serice that worked fine when hosted on IIS.
now, I took the same service, and created a host application in WPF, and when trying to start the service from that application, I get this exception :
The HttpGetEnabled property of ServiceMetadataBehavior is set to true and the
HttpGetUrl property is a relative address, but there is no http base address.
Either supply an http base address or set HttpGetUrl to an absolute address.

The error is quite clear - you're using HTTP, you have enabled HttpGetEnabled on your ServiceMetadata behavior, but you have not provided a base address in your config.
In IIS, base addresses are neither needed, nor used, since the location of the *.svc file defines your service address. When you're self-hosting, you can and should use base addresses.
Change your config to look something like this:
<system.serviceModel>
<services>
<service name="YourService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/YourService" />
</baseAddresses>
</host>
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange" />
..... (your own other endpoints) ...........
</service>
</services>
</system.serviceModel>
Now, the "HttpGetEnabled" has a base address http://localhost.8080/YourService to go to to get the metadata from.
Or if you don't like this, again, the error message is quite clear on your alternative: define an absolute URL for the HttpGetUrl in your ServiceMetadata:
<serviceBehaviors>
<behavior name="Default">
<serviceMetadata
httpGetEnabled="true"
httpGetUrl="http://localhost:8282/YourService/mex" />
</behavior>
</serviceBehaviors>
The clients can get your metadata from your "mex" endpoints, either at a fixed URL defined as in this second example, or they will go to the base address of the service for the metadata (if there is one).
If you're coming from IIS and haven't adapted anything, you'll have neither a base address, nor an explicit, absolute URL for your Metadata exchange endpoint, so that's why you get the error you're seeing.
Marc

I faced this error when I tried to use net.pipe binding.In my case, the default service behavior published the service metadata, This is the cause of my error. My solution is to use different behavior for your services. , then I changed my config file according to #marc_s answer and make different service behaviors as follows:
<serviceBehaviors>
<!--Default behavior for all services (in my case net pipe binding)-->
<behavior >
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
<!--for my http services -->
<behavior name="MyOtherServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>

Check that the service class is correct.
It's solved my problem
// Create a ServiceHost for the CalculatorService type and
// provide the base address.
serviceHost = new ServiceHost(typeof(ServiceClass));

Related

Defining baseURL and EndPoint

I made a WCF with three methods:
[ServiceContract]
public interface IService1
{
[OperationContract]
String devolverPisosA();
[OperationContract]
String devolverPisosV();
[OperationContract]
String devolverNoticias();
}
I need to define baseAddress and EndPoint in Web.config file but I don´t know how:
I´m trying this (and some variations) but this is not working... (between system.serviceModel)
<services>
<service
name="ProyectoJosephWCF.Service1">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/Iservice1/"/>
</baseAddresses>
</host>
<endpoint address="devolverPisoA"
binding="wsHttpBinding"
contract="ProyectoJosephWCF.Service1" />
<endpoint address="devolverPisoV"
binding="wsHttpBinding"
contract="ProyectoJosephWCF.Service1" />
<endpoint address="devolverNoticias"
binding="wsHttpBinding"
contract="ProyectoJosephWCF.Service1" />
</service>
</services>
EDITED: If I´m not defining the baseAddress and endpoint before (using default configuration which was created when I created the project), and I launched the Services1.svc, I can reach the result json through testing windows but I can´t (or at least I don´t know how) to reach that JSON result from Android (by Retrofit). I supposed that I configured Retrofit (baseAddress and Endpoint values wrong), so I decided to set those values by my own...
For that I set the code before in Web.config, but I can´t reach them as well...
Beside, I would like to reach JSON result by Mozilla (in browser I mean), because someone said me that could me help to understand what baseAddress and Endpoint I´m using...
EDITED2: Behaviors are settings as:
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
And still don´t reach result by android or browser...
You need to set httpGetEnabled="true" for having WSDL available like below
<behaviors>
<serviceBehaviors>
<behavior name="NewBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
Include the same behavior configuration in your service declaration like
<service name="ProyectoJosephWCF.Service1"
behaviorConfiguration="NewBehavior">
See serviceMetadata for more information.
Finally... Check it out if you need it.
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior" >
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
And:
[OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "devolverPisoA")]
List<pisosAlquiler> devolverPisosA();

How to determine if I am using a Restful service or not?

I need to create a Restful service for my application. More I dig deep in to this more I get confused. I understand that a Restful service uses http for CRUD operations which makes it faster and lighter. But I am not sure how to determine if a web service is Restful or not.
However I found some help online that claims to be a Restful service but that has some Custombinding type . Here is how the web.config looks like
<system.serviceModel>
<services>
<service behaviorConfiguration="" name="RestRaw.Service1">
<endpoint address="" behaviorConfiguration="web" contract="RestRaw.IService1" binding="customBinding" bindingConfiguration="RawReceiveCapable"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<bindings>
<customBinding>
<binding name="RawReceiveCapable">
<webMessageEncoding webContentTypeMapperType="RestRaw.RawContentTypeMapper, RestRaw, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<httpTransport manualAddressing="true" maxReceivedMessageSize="524288000"
transferMode="Streamed" />
</binding>
</customBinding>
</bindings>
</system.serviceModel>
Is that a Restful service. If yes how can that be determined??
I am confused at the moment any suggestions to clarify my doubt would be really appreciated.
In this particular case you can tell it's a REST style webservice by the added behavior.
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
The webHttp behavior modifies the operation dispatch pipeline and instead of reading a destination action from a SOAP body, it uses the service interface attributes to decide where to route it. Here is a good page on msdn that shows the basics of creating a REST style webservice in WCF. The following example is from that page.
[ServiceContract]
interface ICustomer
{
//"View It" -> HTTP GET
[WebGet( UriTemplate="customers/{id}" )]
Customer GetCustomer( string id ):
//"Do It“ -> HTTP PUT
[WebInvoke( UriTemplate="customers/{id}", Method="PUT" )]
Customer UpdateCustomer( string id, Customer newCustomer );
}
The WebGet attribute matches the GET verb, then the request URI is pattern matched to decide which method to call. Then parts of the URI can be extracted and converted to parameters and passed to the method call. In the second method, UpdateCustomer, the Customer parameter comes from the request body as it's the only parameter that doesn't get matched elsewhere. In order for the request body to be used like this, the webMessageEncoding binding element is used in the custom binding. If you simply use the WebHttpBinding, it does all of this for you. The config you provided is doing it the explicit way.
The web.config file shows a typical WCF application. To check whether it is RESTful, you might learn WCF REST related topics, such as
https://msdn.microsoft.com/en-us/library/dd203052.aspx

Web Service hosted on GoDaddy fails

I have a WCF web service that works on my local machine, both through the debugger, and installed as a service on IIS.
When I install it on my GoDaddy host, this web service fails. The logging call at the beginning of the function is not executed, and the browser receives a 400/Bad Request response.
Other services compiled together with this work as expected, so it is not a matter of the Connection String, web.config, or such.
The URL to call the service is a simple "GET" call:
http://tucansdev.com/TalLimoService.svc/GetTransportationOffers/1,2,1410885561,false
The Operation contract looks like this:
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "GetTransportationOffers/{pickupLocID},{dropoffLocID},{pickupTime},{isAsInstructed}")]
List<GetTransportationOffersResult> GetTransportationOffers(string pickupLocID, string dropoffLocID, string pickupTime, string isAsInstructed);
The log on the GoDaddy server confirms the fact that the call was received, but nothing more.
Just to be thorough, here is my service model from web.config:
<system.serviceModel>
<services>
<service name="TalLimoService.TalLimoService" behaviorConfiguration="ServiceBehavior">
<!--Service Endpoints-->
<!-- Unless fully qualified, address is relative to base address supplied above-->
<endpoint address="" binding="webHttpBinding" contract="TalLimoService.ITalLimoService" behaviorConfiguration="web"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true"/>
Worse yet, it used to work. I changed the third parameter from an explicit date to time ticks, which doesn't affect the interface as far as I can tell. When I revert to the old version, I still get the 400 response, so I guess it isn't the code as such. What is it?
NEXT STEP
Since it used to work, I simplified the code to a completely trivial interface, which then had no problems. I then restored all the parameters to the endpoint, but with an empty function.
The first two lines of the function look like this:
List<GetTransportationOffersResult> transList = new List<GetTransportationOffersResult>();
TalLimoDataDataContext tlData = new TalLimoDataDataContext();
When the function has only the first line, everything is fine. The second line causes the service to return Error 400. I would then say that there is something wrong with my .dbml file, but other functions in this web service make the same call, and there is no problem!
It turns out that the problem was in the web.config file after all. On my machine I had:
<connectionStrings>
<add name="DataSourceConnectionString"...
and on the server, for some reason, it was
<connectionStrings>
<add name="TalLimoConnectionString"...
So on my machine it worked, and on the server it didn't. I guess the moral of the story is never assume anything.

There was no channel actively listening

maybe you can help me set up my WCF service.
First, here is my config file:
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<bindings />
<services>
<service name="AuthenticatorService.Authenticator">
<endpoint address="auth" binding="basicHttpBinding" bindingConfiguration=""
name="AuthEndpoint" contract="AuthInterface.IAuthenticator" />
<endpoint address="mex" binding="mexHttpBinding" name="MetadataEndpoint"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True" />
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
And this is how I call my service from c#:
//This creates a link to the WCF service using basicHttpBingind
httpFactory = new ChannelFactory<IAuthenticator>(new BasicHttpBinding(), new EndpointAddress("http://myUrl/auth.svc"));
httpProxy = httpFactory.CreateChannel();
It worked fine when I was doing this on localhost but now it keeps telling me no endpoint was found.
Also, the server generated the following error:
System.ServiceModel.EndpointNotFoundException: There was no channel actively listening at 'http://myURL/auth.svc/$metadata'. This is often caused by an incorrect address URI. Ensure that the address to which the message is sent matches an address on which a service is listening.
Im really confused, I have no idea why this is happening. Do I need to create another service file for the metadata exchange?
Do I need to set a baseAddress?
Thanks
How did you deploy the service? I assume the service is running in IIS on your box - did you try hitting the service URL (http://myUrl/auth.svc) in a browser to see if it is indeed up?

WCF Methods Return 404 When Wildcard Mapping Is Enabled In IIS6

I have a REST WCF service defined as follows:
[ServiceContract]
public interface IRest {
[OperationContract]
[WebGet(UriTemplate = "/test")]
int Test();
}
With the following web.config:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="ServiceX.RestBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ServiceX.RestBehavior">
<serviceMetadata httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" />
<services>
<service behaviorConfiguration="ServiceX.RestBehavior"
name="ServiceX.Rest">
<endpoint address="" behaviorConfiguration="ServiceX.RestBehavior"
binding="webHttpBinding" contract="ServiceX.IRest" />
</service>
</services>
</system.serviceModel>
All works fine without wildcard mapping; I can browse to '/services/rest.svc/test' and I'll receive the expected result.
However, as soon as I enable wildcard mapping (.* > C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll), then I start receiving 404s when I attempt to access a method (although I can still view '/services/rest.svc').
Any ideas? I've exhausted Google and StackOverflow. No-one seems to be sharing this problem :(
EDIT: You can all reproduce this by creating a new WCF Service in VS2008 (new Project > WCF Service Application). Browse to the dummy method ('GetData')... you will notice it returns 400... that's fine because it shows it's still forwarding to WCF. However, if you enable wildcard mapping in IIS6 you will now get a 404, meaning WCF is no longer intercepting the request.
I just had the same problem with a WCF service running on IIS6.
I could browse the service on http://someurl/service.svc, but I would get a 404 when hitting a method on the service such as http://someurl/service.svc/somemethod.
The fix, in my case, was easy. The .svc file type was configured in IIS to be handled by C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll, but my service was running in a ASP.NET v4.0 apppool, so I simply pointed the .svc file type to be handled by C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll
In the popup dialog where you specify the path for the wildcard mapping, there is check box for a setting called 'Verify that file exists'. This setting needs to be turned off.
If it is not turned off, you will get a 404 (page not found)

Categories