1

I'm calling a REST service searchFavoriteCompany that in turn calls another service A. Service A already returns JSON. But since my return type of searchFavoriteCompany my search results are then returned with escape characters:

"{\"responseHeader\":{\"status\":0,\"QTime\":2,\"params\":{\"facet\":\"false\",\"fl\":\"id,title,friendlyurl,avatar,locpath,objectid,objecttype\",\"indent\":\"off\",\"start\":\"0\",\"q\":\"title_search:*castle*\",\"wt\":\"json\",\"fq\":\"userid:\\\"C325D42C-A777-4275-BDD2-D7810A8AB9AB\\\"\",\"rows\":\"10\",\"defType\":\"lucene\"}},\"response\":{\"numFound\":2,\"start\":0,\"docs\":[{\"title\":\"Castle A\",\"objecttype\":1,\"friendlyurl\":\"castle-a\",\"avatar\":\"6_887_castle-a.JPG\",\"objectid\":6},{\"title\":\"Castle B\",\"objecttype\":1,\"friendlyurl\":\"castle-b\",\"avatar\":\"794_360_13j-Castle-by-night.jpg\",\"objectid\":794}]}}\u000a"

I don't know how to make sure my JSON results are returned without these escape characters.

Imyservice.vb

Namespace RestService

<ServiceContract()>
Public Interface Imyservice

    <OperationContract()> _

_ Function searchFavoriteCompany(ByVal q As String, ByVal uuid As String) As String

End Interface

End Namespace   

iservice.svc.vb

Namespace RestService

Public Class iservice
    Implements Imyservice
    Public Function searchFavoriteCompany(ByVal q As String, ByVal uuid As String) As String Implements Imyservice.searchFavoriteCompany
        Dim req As HttpWebRequest = HttpWebRequest.Create("http://localhost/getjson")  <---- this service already returns JSON data
        Dim Resp As HttpWebResponse = req.GetResponse()
        Dim reader As StreamReader = New StreamReader(Resp.GetResponseStream)
        Dim responseString As String = reader.ReadToEnd()

        Return responseString

    End Function

End Class

End Namespace   

Instead of returning the responsestring I also tried:

HttpContext.Current.Response.Write(responseString)
return ""

But then I get the error 'Object reference not set to an instance of an object' And I checked: responsestring contains a value, so that is not the problem.

Adam
  • 6,041
  • 36
  • 120
  • 208
  • Take a look at [this question](http://stackoverflow.com/questions/17097841/return-a-json-string-explicitly-from-asp-net-webapi) and see if that helps. – Joe Enos Sep 12 '13 at 23:01
  • If the service _already returns JSON data_, what is all the above for (anyway)? Don't really see anything you're doing except return a string (presumably now with string content-type instead of application/json)? – EdSF Sep 12 '13 at 23:04
  • @JoeEnos: I updated my post with your suggestion from your other post, but it still doesn't work EdSF: you are correct, but my other service is local and not directly approachable via REST. How would I go about changing the content-type like you suggest? – Adam Sep 13 '13 at 07:09
  • Is this hosted in IIS or is this self-hosted, like in a Windows service? If it's self-hosted, then the `NullReferenceException` on HttpContext.Current makes sense. – Joe Enos Sep 13 '13 at 13:35
  • How do I check that? :$ and if it's self hosted how would I fix it? – Adam Sep 13 '13 at 14:17
  • Since you've got a `.svc` file, I'm guessing it's IIS, not self-hosted. If your project is an ASP.NET web project, then it's probably going to be IIS. If it's a console app or Windows service (if there's a `void Main` method somewhere), then it's probably self-hosted. In any case, throw a debugger on there and see if `HttpContext.Current` or `HttpContext.Current.Response` is null, since you got a `NullReferenceException` there, just to make sure that's the case. If one of those are null, then you won't be able to use that solution, but if not, your exception must be coming from somewhere else. – Joe Enos Sep 13 '13 at 14:49
  • Thanks! HttpContext.Current is indeed nothing. Does that mean my REST service is self-hosted and not IIS? And now what? Would this perhaps be the way to go from here? http://social.technet.microsoft.com/wiki/contents/articles/1265.hosting-a-wcf-rest-service-on-iis.aspx – Adam Sep 13 '13 at 15:08
  • If you're self-hosted, then that was an architectural decision that was made, so you'd need to talk with whoever designed your application to find out if it can be changed to IIS. But rather than re-architecting your entire application, I'd probably just recommend biting the bullet and de-serializing/re-serializing the original response in a type-safe manner, instead of doing a simple string passthrough. I'll add an answer describing one way of doing this. – Joe Enos Sep 13 '13 at 15:26
  • Actually there's more to it here, since I also want to 'secure' my REST service a bit more. By accessing the session OR cookie of the logged in user which holds his userid, I can make sure that only logged in users will be able to access the service. For me to access the user's session I would HAVE to host it on IIS correct? – Adam Sep 13 '13 at 15:31
  • You'll need to describe your application a little better. Is your client a web browser, or is it an application connecting to your API via code? If it's a browser, and your WebAPI stuff is in the same application as your web application, and you use AJAX from the browser to hit your API, then you will have access to cookies and session and forms authentication and all that good stuff. If the client is some program running, and your WebAPI is standalone, then security is a much larger topic. – Joe Enos Sep 13 '13 at 15:39
  • Yes, my client is the web browser of the visitor. Also my REST service is part of the same application (sanity check: in my solution explorer I see the weddingservice.svc and Iweddingservice.vb files). But still I seem to be unable to access the user's session via HttpContext.Current.Session as HttpContext.Current is nothing. Does that clarify my situation? Thanks! – Adam Sep 13 '13 at 15:45
  • Sorry, I've got WebAPI on the brain right now - an MVC WebAPI service would have access to the regular app's HTTP stuff, but I'm not sure about WCF - I haven't done WCF REST, and Microsoft has abandoned it in favor of WebAPI over MVC. If you're going to make an architectural change, I'd recommend that - using MVC (with or without WebAPI - even plain MVC works very well as a JSON service). If you stick with WCF, I don't know how you can do the security stuff mixed in with your regular ASP.NET security. – Joe Enos Sep 13 '13 at 16:56
  • Ok, I'll have to look into that. I also have a .asmx webservice in which I do have access to the session via _ Public Sub GetSearch() Is a .asmx files considered WCF or MVC? – Adam Sep 13 '13 at 17:04
  • ASMX is a "classic" ASP.NET web service. People generally avoid those in favor of WCF or WebAPI these days. ASMX generally returns SOAP, unless you're using the ASP.NET AJAX extensions to return JSON, and even then, I believe it does some funky stuff to the response. But for simple services, it tends to be the easiest method, and generally doesn't require any configuration, so if you can get your service working the way you want inside an ASMX, that might be a good solution. – Joe Enos Sep 13 '13 at 17:17
  • I found another way of doing it, add this to web.config: And then for the service add _ See here: http://stackoverflow.com/questions/7570235/access-session-in-wcf-service-from-webhttpbinding and http://www.roelvanlisdonk.nl/?p=1232 Now the service can use the session. Still having escape characters though (what this post was about ;) so will into your answers there :) Thanks! – Adam Sep 13 '13 at 17:23

1 Answers1

0

If you can't pass the output directly to the response, your best bet is to go back to traditional methods, and return a type-safe object from your method. You've got the JSON that the original service passes you, and your end-goal is to return that exact object back to your caller.

Assuming you've got a complete JSON object in your example - you can first go to json2csharp to take your JSON and create classes out of it. It uses C#, but you can easily convert it to VB using something like Telerik's Code Converter.

If you follow these steps, you'll end up with several classes, including one called RootObject, which contains properties for responseHeader and response, and the other classes needed. You can rename the classes as you see fit, and put them into proper namespaces - just leave the property names alone, so they match the JSON.

Once you've got this RootObject class (or whatever you rename it to), you can deserialize the JSON you got from the original service into an object of type RootObject, then your WebAPI method would simply return a RootObject. Just like any other WCF call, the framework will take care of serializing that object back into JSON (or XML) for the caller.

Joe Enos
  • 39,478
  • 11
  • 80
  • 136