11

I have a WCF Restful service and I would like the methods to return HttpResponseMessage because it seems structured rather than just returning the data or the exception or whatever else might make its way there.

I am assuming this is a correct, if not let me know, but my problem is what happens when I try to set HttpResponseMessage.Content. When I do this, the client in which I made the RESTful call request authentication.

Here is my code:

In the interface:

[WebGet(UriTemplate = "/GetDetailsForName?name={name}"
                    , ResponseFormat = WebMessageFormat.Json)]
HttpResponseMessage GetDetailsForName(string name);

In the class:

public HttpResponseMessage GetDetailsForName(string name)
{
   HttpResponseMessage hrm = new HttpResponseMessage(HttpStatusCode.OK)
       {
       //If I leave this line out, I get the response, albeit empty  
       Content = new StringContent("Hi") 
       };

   return hrm;
}

I wanted to try to use Request.CreateResponse but I can't seem to get to Request from my WCF Restful method. OperationContext.Current.RequestContext does not have CreateResponse.

Any pointers?

Matt
  • 25,943
  • 66
  • 198
  • 303
  • When you put "Hi" in content, what happens to the client? – Arghya C Sep 15 '15 at 21:10
  • It throws up the browser credential window, even if I put in credentials, I just get unauthorized. – Matt Sep 15 '15 at 21:11
  • Did you check what is the media type of the response with and without "Hi" ? – Arghya C Sep 15 '15 at 21:29
  • without it's application/json; charset=utf-8 , with, there's no real response other than the unauthorized ASP.NET page – Matt Sep 15 '15 at 21:32
  • Can you try adding manually HttpResponseMessage hrm = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent("Hi", System.Text.Encoding.UTF8, "text/plain") }; – Arghya C Sep 15 '15 at 21:35
  • Or, HttpResponseMessage hrm = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent("{'message': 'Hi'}", System.Text.Encoding.UTF8, "application/json") }; – Arghya C Sep 15 '15 at 21:37
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/89840/discussion-between-matt-and-arghya-c). – Matt Sep 16 '15 at 17:42
  • Maybe you can use HttpResponseMessageProperty and add it to the response. – Naha Sep 21 '15 at 13:02
  • Have you tried HttpResponseMessageType? – Naha Sep 22 '15 at 06:49

3 Answers3

2

Unfortunately this will not work. The demonstrated code says:

Construct an HttpResponseMessage object, serialize it with a JSON serializer and pass the result over the wire.

The problem is HttpResponseMessage is disposable and not meant to be serialized, while StringContent cannot be serialized at all.

As to why you are redirected to an authentication form - the service throws an exception when it cannot serialize StringContent and returns a 400 HTTP status code which gets interpreted as an authentication issue.

Roman Pletnev
  • 5,958
  • 2
  • 21
  • 28
  • Do you have a docs/reference for `HttpResponseMessage is disposable and not meant to be serialized` . And why can't `StringContent` be serialized at all? – ANewGuyInTown Nov 15 '17 at 22:37
  • This answer explains the inner workings of the specific situation in question. In other scenarios, you may be able to serialize almost everything one way or another. If you need that, simply ask a new question with your specifics. – Roman Pletnev Nov 16 '17 at 00:53
  • No, I was trying to understand what you quoted in your answer and asked questions on what exactly you said. You are right that anything can be serialized if you want to, however, the provided or default way of serialization by the framework may refuse to _serialize_ based on what `formatters` you are using and what `attributes` are present in a _class/properties_. – ANewGuyInTown Nov 16 '17 at 06:07
  • Anyone can you suggest the fix to work with HTTPResponseMesage in WCF...? – GokulPgp Oct 10 '18 at 13:59
1

I had a similar error, but not quite the same. I was trying to serialize a plain object and was getting an net::ERR_Conection_Reset message. The wcf method executed 7 times and never threw an exception.

I discovered I had to annotate the class I was returning so that my JSON serializer would understand how to serialize the class. Here is my wcf method:

[OperationContract]
[WebGet(
    UriTemplate = "timeexpensemap", 
    ResponseFormat = WebMessageFormat.Json)]
    public TimeexpenseMap timeexpensemap() {
        string sql = "select * from blah"
        DbDataReader reader = this.GetReader(sql);
        TimeexpenseMap tem = null;
        if (reader.Read()) {
            tem = new TimeexpenseMap();
            // Set properties on tem object here
        }
        return tem;
    }

My original class which failed to serialize had no annotations:

public class TimeexpenseMap {
    public long? clientid { get; set; }
    public int? expenses { get; set; }
}

The annotated class serialized without issues:

[DataContract]
public class TimeexpenseMap {
    [DataMember]
    public long? clientid { get; set; }
    [DataMember]
    public int? expenses { get; set; }
}
birwin
  • 2,524
  • 2
  • 21
  • 41
0

If I am calling, for example a public string getDetails(int ID) and an error is thrown, this works ...

catch(Exception ex)
 {
 OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
 response.StatusCode = System.Net.HttpStatusCode.OK; //this returns whatever Status Code you want to set here
 response.StatusDescription = ex.Message.ToString(); //this can be accessed in the client
 return "returnValue:-998,message:\"Database error retrieving customer details\""; //this is returned in the body and can be read from the stream
 }
Martin Smellworse
  • 1,702
  • 3
  • 28
  • 46