Adding a new WCF service to an existing project - c#

I'm adding a new WCF service to a project, but the new one doesn't act the same as the old one.
Each has a similar SVC file:
<%# ServiceHost Language="C#" Debug="true" Service="Company.Project.Service1" %>
Each has an Interface that defines the ServiceContract and OperationContracts:
[ServiceContract]
[ServiceKnownType(typeof(Service1))]
public interface IService1
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "json/method1", RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
ResponseObject Method1(RequestObject req);
}
Each is defined in the web.config file:
<service name="Company.Project.Service1" behaviorConfiguration="ServiceBehavior">
<endpoint address="rest" binding="webHttpBinding" contract="Company.Project.IService1" behaviorConfiguration="web"/>
<endpoint address="soap" binding="basicHttpBinding" contract="Company.Project.IService1"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
However, when I visit the URL for the original service in one of my pre-production environments using Chrome, I see the "Method Not Allowed" error I expect (since I'm using GET).
When I visit the new service, I get a 404 error:
Server Error in [Snipped]
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /[Snipped]/Service2.svc/rest/json/method2
The other oddity is that it worked in my previous pre-production environments, so it could just be something in the deployment process.

Make sure you have routing defined in your Global.asax file for the new service that you have added in existing project. This could be easily missed and resulting in unable to locate resource via Asp.net pipline in hosting environment.
So, if you have new version of service ,let say ApiService2, you would require to add an entry like:
routes.Add(new ServiceRoute("api2", new ServiceHostFactory(), typeof(ApiService2)));

I observed that your method is called Method1 but you are trying to get to the method2
Does your web config also have a section for endpointBehavior like the following. You need this to enable REST endpoints for your webHttpBinding . You should probably add a service behavior as well
<behaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="web">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>

Related

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.

Can't explain 400 Bad Request error

My service model looks as follows.
<system.serviceModel>
<services>
<service name="Web.General" behaviorConfiguration="common">
<endpoint address="basic"
binding="basicHttpBinding"
contract="Web.IGeneral" />
<endpoint
...
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="common">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment
aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
When I hit .../general.svc/ping/1 I get error 400 Bad Request, which I can't explain. What is that and how can I kill it?
My service has interface as follows.
[ServiceContract]
public interface IGeneral
{
//[OperationContract(Name = "Ping")]
[WebInvoke(
Method = "GET",
BodyStyle = WebMessageBodyStyle.WrappedRequest,
//RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "Ping/{input}")]
String Ping(String input);
}
Mate, I'v e been in to this situation and the best approach to solve this out is through Fiddler. 404 can be due to anything at server level. How about running a fiddler and see the RAW request - response
http://www.telerik.com/download/fiddler
Otherwise, enable WCF logging.
http://www.codeproject.com/Articles/383162/Logging-and-Tracing-WCF-Soap-Messages
And then use trace viewer:
http://msdn.microsoft.com/en-us/library/ms732023(v=vs.110).aspx
If you want us to give a concrete answer then you probably need to provide us more details.

Make a WCF Service Accept JSON Data from jQuery.AJAX()

I have been searching around for hours and trying different things to get this to work. I have tried so many articles on stackoverflow and either I am too stupid to get things working or I have some unique and odd configuration that is preventing me from experiencing joy.
I create the WCF service outlined by this tutorial:
http://www.codeproject.com/Articles/97204/Implementing-a-Basic-Hello-World-WCF-Service
It is super basic and has one method and all I want it to do is allow me to consume it with jQuery.AJAX() using json.
I have it hosted in IIS and it works. I can access the WSDL without issues.
I try to consume it with the following code:
$.ajax({
dataType: 'json',
type: 'POST',
contentType: "application/json",
url: "//localhost:546/HelloWorldService.svc/GetMessage",
data: {
name: "Joe"
}
}).done(function(msg){
console.log(msg);
$("#result").append(msg);
});
I always get errors. Based on what I have tried I get 500 errors, 402 errors, errors about incorrect content... All the errors.
I have tried implementing solutions from the following articles. They range from having me change the web.config endpoints (I know I HAVE to change them but nothing I have tried so far works in terms of adding a JSON endpoint) to adding things like
[WebInvoke(Method = "POST", UriTemplate = "json/PostSalesOrderData", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
to the interface.
Here are some of the articles I have looked at and tried to smash into my solution to get it working without much success.
Javascript JSON and WCF webservice on Phonegap Android
HTTP/1.1 415 Cannot process the message because the content type 'application/json; charset=utf-8' was not the expected type 'text/xml; charset=utf-8'
WCF Services with JSON, JSONP and SOAP End Points
Two endpoint (soap ,json) and one service method
WCF REST Service not accepting JSON in .Net 4
I also went through this tutorial and tried to use what he had to say to get my solution working. Still nothing!
http://www.primordialcode.com/blog/post/passing-json-serialized-objects-wcf-service-jquery
This is how my interface looks
[ServiceContract]
public interface IHelloWorldService
{
[OperationContract]
[WebInvoke(UriTemplate = "GetMessage", Method = "POST",
BodyStyle = WebMessageBodyStyle.WrappedRequest,
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
String GetMessage(String name);
}
Can anyone help me experience joy?
Thanks in advance for even looking at my question. If you need more information or I have not provided enough let me know so I can help you help me!
I must be missing something stupid... I know it is not this hard.
EDIT:
Working Web.Config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="false" targetFramework="4.0" />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="WebHTTPEndpointBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="MyServiceTypeBehaviors">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding name="MyWebServiceBinding" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"/>
</webHttpBinding>
</bindings>
<services>
<service name="MyWCFServices.HelloWorldService"
behaviorConfiguration="MyServiceTypeBehaviors">
<endpoint address="" binding="webHttpBinding" bindingConfiguration="MyWebServiceBinding" behaviorConfiguration="WebHTTPEndpointBehavior"
contract="MyWCFServices.IHelloWorldService"/>
<endpoint contract="IMetadataExchange"
binding="mexHttpBinding" address="mex"/>
</service>
</services>
</system.serviceModel>
</configuration>
change this line
data: {
name: "Joe"
}
to
data: JSON.stringify({name: 'Joe'});
EDIT:
Do this to your service. Add WebHttp binding in the config.
<behaviors>
<endpointBehaviors>
<behavior>
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
Hope you know where to add this. If not let me know and I will try to provide some inputs.
EDIT:
Following up on my comment,
<behavior name="myBehaviorName">
<webHttp />
</behavior>
<service name="MyWCFServices.HelloWorldService"
behaviorConfiguration="MyServiceTypeBehaviors">
<endpoint address="" binding="webHttpBinding"
contract="MyWCFServices.IHelloWorldService" behaviorConfiguration="myBehaviorName"/>
<endpoint contract="IMetadataExchange"
binding="mexHttpBinding" address="mex"/>
</service>
I'm coming in late, but you still have some issues you'll need to resolve to get it to work. You need to change the binding for your endpoint to support the HTTP operations.
<bindings>
<webHttpBinding>
<binding name="MyWebServiceBinding" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"/>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="WebHTTPEndpointBehavior">
<webHttp helpEnabled="true"/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="MyWCFServices.HelloWorldService"
behaviorConfiguration="MyServiceTypeBehaviors">
<endpoint address="" binding="webHttpBinding" bindingConfiguration="MyWebServiceBinding" behaviorConfiguration="WebHTTPEndpointBehavior"
contract="MyWCFServices.IHelloWorldService"/>
<endpoint contract="IMetadataExchange"
binding="mexHttpBinding" address="mex"/>
</service>
</services>
The maxBufferSize and maxReceivedMessageSize is optional.
EDIT: Oops, forgot to add your behaviorConfiguration in.

WCF RESTFul Service - 404 with endpoint not found with 2 services

I have two WCF services Exchange1.svc and Exchange2.svc both setup to be RESTful JSON consummables. Exchange1.svc works fine, but when I try to post to Exchange2.svc, I get an Endpoint not found message.
What am I doing wrong?
My IExchange2 interface is:
[ServiceContract]
public interface IExchange2
{
[System.ServiceModel.OperationContract(Name = "InsertReading")]
[WebInvoke(UriTemplate = "/InsertReading?memberID={memberID}", Method = "POST", ResponseFormat = WebMessageFormat.Json)]
void InsertReading(string memberID);
}
The URL I'm trying to hit is: http://localhost:49701/Exchange2.svc/DiaInsertReading?memberID=6519548
My config is:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="MyNamespace.Exchange1Behavior">
<webHttp/>
</behavior>
<behavior name="MyNamespace.Exchange2Behavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="MyNamespace.Exchange1">
<endpoint address="" binding="webHttpBinding" behaviorConfiguration="MyNamespace.Exchange1Behavior" contract="MyNamespace.IExchange1" />
</service>
<service name="MyNamespace.Exchange2">
<endpoint address="" binding="webHttpBinding" behaviorConfiguration="MyNamespace.Exchange2Behavior" contract="MyNamespace.IExchange2" />
</service></services></system.serviceModel>
I have edited my post since the answer did not help. Since you are hosting in IIS with svc you don't need to set an address in your binding as I was saying in my previous answer. The baseaddress will be the location of you server. Ex: http://localhost:49701/Exchange2.svc. If you hit this address you should get to a WCF Service webpage.
Since you are using POST method you can send the data in the request body. If you have fiddler installed, in the composer you can set the method to post and address to http://localhost:49701/Exchange2.svc/InsertReading if this is your address to your service.
In the body of the request body you set { memberID:"123" } change 123 to whatever value you want to send to your service.
Or you can send the data in the address like: http://localhost:49701/Exchange2.svc/InsertReading?memberID=123
If you now execute your request it should return a response 200 OK.
In web.config file specify your endpoint
<service name="MyNamespace.Exchange2">
<endpoint address="Exchange2" binding="webHttpBinding" behaviorConfiguration="MyNamespace.Exchange2Behavior" contract="MyNamespace.IExchange2" />
Then, add this end point in your URL as:
http://localhost:49071/Exchange2/DiaInsertReading?memberID=6519548

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