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.
Related
I have a WCF project with two endpoints. One endpoint "EP1" shows detailed exceptions in the WCF Test Client but "EP2" does not and shows an error message saying:
The server was unable to process the request due to an internal error. For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the configuration behavior) on the server in order to send the exception information back to the client
I am wondering why this is? I have set the web.config in the same way as "EP1" and on the "EP2" web service class I have added:
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
I can't imagine what could be different. I have double checked the class name is definitely correct. Here is the section of the web config:
<system.serviceModel>
<services>
<service name="Portal.EP1" behaviorConfiguration="debug"></service>
<service name="Portal.EP2" behaviorConfiguration="debug"></service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="debug">
<!-- To avoid disclosing metadata information, set the value below to false 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="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Am I crazy?
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
I have created my first WCF webservice and I am trying to return an image from it based on some passed parameters. I am getting the error:
The content type image/jpeg of the response message does not match the content type of the binding (text/xml; charset=utf-8). If using a custom encoder, be sure that the IsContentTypeSupported method is implemented properly.
What do I need to do to resolve this issue?
The web.config file of my website that is calling the service has the following config:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IRestImageService" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:59473/RestImageService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IRestImageService"
contract="RestImageService.IRestImageService" name="BasicHttpBinding_IRestImageService" />
</client>
The webservice web.config looks like this:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- 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>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true"/>
The Service Contract:
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "Image/{type}/{typeid}/{imageid}/{size}/{extension}",
RequestFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped)]
Stream Image(string type, string typeid, string imageid, string size = "lrg", string extension = "jpg");
I am very new at WCF, so any help/pointers would be greatly appreciated!
Update
After implementing Tim's suggestion, I am getting a new error:
There was no endpoint listening at localhost:59473/RestImageService.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
I am not sure how to configure the web service to fix this issues. Any suggestions?
This is how I'm accessing the web service:
RestImageServiceClient client = new RestImageServiceClient();
client.Image(WSC.Common.BO.User.User.ImageFolder.Buyer, "27085", "BuyerPhoto", "LRG", "jpg");
I hope to be able to set the src tag of my image to the web service url once I get it working.
basicHttpBinding is SOAP (version 1.1). To enable REST-based services, I believe (haven't done much of it myself) that you need to use the webHttpBinding.
I would try something like this. In your service's config file, make the following changes:
<protocolMapping>
<add binding="webHttpBinding" scheme="http"/>
</protocolMapping>
This should configure your default binding to be webHttpBinding for http calls.
<behaviors>
<endpointBehaviors>
<behavior>
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<!-- 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>
</behaviors>
The above code should add a default endpoint behavior for webHttp.
Finally, in your client config file, make the following change:
<client>
<endpoint address="http://localhost:59473/RestImageService.svc"
binding="webHttpBinding"
contract="RestImageService.IRestImageService"
name="WebHttpBinding_IRestImageService" />
</client>
I can't say for certain that this will work, but I've done a lot with WCF (on the SOAP side), so I think this will at least get you pointed in the right direction.
EDIT
RestImageServiceClient is a SOAP client. To use a REST service, you need to use an HTTP API. Here's an example from [WCF REST Service with JSON]http://www.codeproject.com/Articles/327420/WCF-REST-Service-with-JSON):
WebClient client = new WebClient();
byte[] data = client.DownloadData("http://localhost:11523/Service1.svc/GetData");
Stream stream = new MemoryStream(data);
DataContractJsonSerializer obj = new DataContractJsonSerializer(typeof(string));
string result = obj.ReadObject(stream).ToString();
I recommend googling "WCF REST JSON Client exmaple" - you'll get lots of hits and a few different ways to do this.
As an added note, you could make a SOAP call with your SOAP client, as long as you have a SOAP endpoint exposed on the service.
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)
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));