1

I know this question has been asked on a number of occassions (believe me I know I have went through almost every one of the posts). However, I still can't get it to work...

I have the following simple service:

[ServiceContract]
public interface IService
{
    [OperationContract]
    [WebGet(UriTemplate = "/data/{id}", ResponseFormat = WebMessageFormat.Json)]
    [FaultContract(typeof(CustomError))]
    Data GetData(string id);
}

[DataContract]
public partial class Data
{
    [DataMember]
    public string Property { get; set; }
}

[DataContract]
public class CustomError
{
    [DataMember]
    public string Message { get; set; }
}

In the implementation of the GetData is as follows:

public Data GetData(string id)
{
    int dataId = -1;
    if (!Int32.TryParse(id, out dataId))
    {
        var detail = new CustomError() { Message = "DataID was not in the correct format."};
        throw new FaultException<CustomError>(detail);
    }

    ... return instance of Data
}

If I pass a valid ID in I get the approprate Data object coming across the wire, however, if I pass an invalid ID in (to trigger the FaultException) it always comes over to the client as a ProtocolException with the same message:

The remote server returned an unexpected response: (400) Bad Request.

I initially went down the road of implementing IErrorHandler and this is where I started getting the issue so to eliminate that from the equation, I implemented this basic service... but I can't even get it to work.

On my client I have created a Service Reference and using the client proxy i.e.

using (var client = new DataServiceClient())
{
    try
    {
        var user = client.GetData("twenty");
        Console.WriteLine(user.Property);
    }
    catch (System.ServiceModel.FaultException<CustomError> ex)
    {
        Console.WriteLine(ex.Message);
    }
}

Is there something I am missing? (I can post the Service/Client configuration settings on request)

NB: I noticed that when you add a service reference and it generates the client proxy (I am on VS2010) you need to manually add the WebGet/WebInvoke attribute to the generated client as it doesn't seem to come over automatically.

James
  • 80,725
  • 18
  • 167
  • 237

3 Answers3

2

Are you using webHttpBinding? If so, then you should use WebFaultException<T> as noted here.

CodingWithSpike
  • 42,906
  • 18
  • 101
  • 138
  • @rally25yrs - yeah I am using webHttpBinding, I have tried using WebFaultException before and I was getting the same issue, I will try it again with this app though. Is there any reason why it *has* to be a WebFaultException though and not FaultException? – James Jul 20 '11 at 20:26
  • @rally25yrs - Tried this again and I was still getting the ProtocolException, however, the status code I set for the exception on the server does appear to come across ok. – James Jul 21 '11 at 13:11
0

I don't think from the error that you are receiving that you are ever getting to the point where you are throwing your FaultException<CustomError>. It looks like the service doesn't know how to handle your request.

msarchet
  • 15,104
  • 2
  • 43
  • 66
0

I am a bit confused here. Are you using a REST or a SOAP service here? The question is tagged REST and the WebGet attribute suggests REST. But the question is also tagged WCF-PROXY and you talk about adding a serve reference which is very much a SOAP operation and doesn't generate a REST client at all. With REST, unless you are using OData service, there is no metadata you can use to do an Add Service Reference. Instead you use a WebClient or HttpWebRequest or something similar to get data using the URL you construct.

Maurice
  • 27,582
  • 5
  • 49
  • 62
  • my reference to wcf-proxy was more along the lines of when you add a service reference to my WCF service and it generates a proxy class on the client. I found a post on here which suggested that you should opt for this approach over HttpWebRequest when your client is a .NET app as you get the advantage of strongly typed parameters/return types. – James Jul 20 '11 at 20:23
  • Well the client code also looks like a soap call. I would open up Fiddler en double check you are doing a REST GET and not a SOAP POST. – Maurice Jul 20 '11 at 20:41
  • I ran my WCF service via Visual Studio and used Fiddler to perform a REST GET and when it throws the exception it just gives me back a status 200 but returns no data. – James Jul 20 '11 at 21:49
  • Try changing the host name from **localhost** to **ipv4.fiddler** on the client and rerun the client with Fiddler open. You should see the request the client made show up in Fiddler and that will tell you what your client is actually calling. – Maurice Jul 21 '11 at 07:11
  • I did as you suggested and this was the request made by the client - `GET /UserService.svc/users/test HTTP/1.1 Content-Type: application/xml; charset=utf-8 Host: 127.0.0.1:50376 Accept-Encoding: gzip, deflate Connection: Keep-Alive` – James Jul 21 '11 at 13:04
  • And the response is `HTTP/1.1 400 Bad Request` – James Jul 21 '11 at 13:05
  • Not at all the URL I was expecting to see. I was expecting **htp://localhost: – Maurice Jul 21 '11 at 13:10
  • apologies, it is the same service, I named it DataService in the example to keep it generic. The above was copied & dumped straight from Fiddler so where you see the word `Data` in the example, I am really referring to `User`. – James Jul 21 '11 at 13:33
  • @Maurice let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/1696/discussion-between-james-and-maurice) – James Jul 21 '11 at 13:34
  • Sorry, at a customer so can't. – Maurice Jul 21 '11 at 13:41
  • no worries, I did manage to get the fault to come over the wire by using `HttpClient` and constructing the request myself (instead of using the service reference class). However, I couldn't catch the exception on client I had to just use the status code of the response to determine whether it was ok or not. I am not sure if this is indeed the correct way of determining problems on the server, however, it does feel more like a more *REST*-like to me? – James Jul 21 '11 at 13:44
  • Using the HttpClient, or similar, and checking the status code is the normal REST way of doing things. – Maurice Jul 21 '11 at 13:46
  • perhaps I was getting myself confused between REST & just a normal WCF service. Do you know of any frameworks or suggest any way of wrapping up this mechanism or is it normally just a case of try/catch blocks for every request? – James Jul 21 '11 at 13:54