Silverlight, WCF and rewriting response - wcf

I am trying to write a WCF service as a proxy for my Silverlight control to do cross-domain requests to an internet REST web service. I just want to make the requests to my service, and it would format and forward the request to the 3rd party web service (replace the hostname and part of the URL), then simply return the response to the caller.
Is my approach correct? The 3rd party server does not have the crossdomain.xml file to allow my call otherwise.
My question is, given my WCF service approach, I would like to rewrite the response body in my service with the response body I retrieved from the 3rd party service, and if possible, rewrite the response header to also be the one I got from that service. This way it minimizes the translation that my web service has to do on the response. Is it possible for me to do this rewrite? if so, how? if not, what are the best practices to implement this?
My interface is right now very primitive, something like this, simply because i don't need anything more than this. The response from the 3rd party service is a JSON response.
[ServiceContract]
interface IMyProxy
{
[OperationContract]
[WebGet(UriTemplate = "relay/{requestOptions}")]
string ForwardRequest(string requestOptions);
}
p.s. I do not need it to work with HTTPS, so no need to worry about the man-in-the-middle issue.

I figured it out, I believe (WebOperationContext).
I am still having an issue that if I duplicate the "Transfer-encoding" of the 3rd part service in my reply, I get an obscure exception down from the guts of the framework (something is "NotFound")... but that's a different story.

Related

WCF routing and service metadata

I'm building a WCF router which needs to act as a proxy for a number of internal web services (WCF and ASMX). The routing part is fairly straight-forward, but I can't understand how the service metadata exchange would work in this solution.
In other words: how would a client obtain metadata for an internal service behind the router? Do I need to manually supply WSDL files to the consumer? Can I somehow setup the router to return the metadata for an appropriate internal service?
Or perhaps my architecture is completely wrong?
I see 2 options here:
It may be an option to create a "non-transparent" proxy, if you don't want to expose the internal addresses. The advantage is that you can do more than just routing messages (i.e. such proxy may serve as a "security boundary", unwrapping ciphered messages and passing them plain to the internal endpoint). It can also provide an "interoperable level", exposing a WCF service as simple SOAP using same datatypes/message XML structure. The downside is that you'll have to update its code along with the proxied services
You may implement a WSDL rewriter. With it, you can mask the internal service URL on-the-fly - depending on your conditions, a simple string replace may or may not suffice.
Refer to:
Message Inspectors
IWsdlExportExtension
The same "router service" can also be used to get the individual WSDL for internal services behind the router.
Check out this thread
Have you considered using a simple HTTP Proxy instead? All WCF using REST or SOAP are at their core HTTP requests. It seems like the routing functionality (which I am assuming you are basing on hostname, URL path or parameters) could be performed by proxying the HTTP request without needing to understand the contents. ASP.Net will do a fairly good job of sanitizing incoming requests on its own, but you could always add additional custom filtering as necessary.

WCF basic auth to service that does not send 401 but 500 instead

I have to consume 3 web services (Sharepoint/Alfresco/Documentum CMIS) via WCF with HTTP Basic auth.
With Sharepoint or Alfresco, first request goes without Authorization header, receives HTTP 401, gets auto-retried by WCF with header, everything's fine.
But with Documentum, I receive HTTP 500 and a SOAP Fault instead, so WCF never gets an opportunity to send the header and returns the exception as-is.
I can of course add the headers manually via HttpRequestMessageProperty, but this looks like an ugly hack to me. Is there anything that could be configured on the WCF side to send headers with the first request, or on Documentum side to return 401?
You could try fronting the Documentum service with another web server that behaves properly, and passing the requests through?
I implemented something similar using IIS to front Apache Tomcat in order to use Windows Auth, and used the isapi_redirect.dll filter to pass requests through. More information about that can be found here: http://tomcat.apache.org/connectors-doc/reference/iis.html
Don't know if something like that is an option for you, but it may provide an easier solution in code.

Redirect the wcf service request to a internal address

Now i have a public Wcf REST service A, and several internal wcf REST services B, each of internal services are identified by name. Is it possible to create a router/proxy in service A, and then, when the users request the interface of service A, it can redirect the request to the internal services based on name?
I tried using:
WebOperationContext.Current.OutgoingResponse.Location = targetInternalPath;
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.Redirect; // or MovedPermanently
All works fine except the headers that we get on the client side, Here is the details from Fiddler:
Transport
Location: http://locahost:9856/internalAddress/getimage
Content-type: null (It should be "image/png")
Content-Length: 0
In other words, the client knows the exact internal address, the content-type and content-length is incorrect. All are not what i want. I have been struggling with this issue for days, anybody has any idea?
Best Regards.
Johnny
I'm confused. What you are seeing in fiddler is exactly what you are asking it to do. Your service A is returning a redirect response. The client is supposed to respond to that redirect by following the URI in the Location header.
If you truly want to hide the internal services then you need to make the service A work like a proxy. It needs to make the request to the internal services itself and then return the response it gets back.
Are you trying to hide the internal services for security reasons or is it just the clients don't know about those internal servers in advance?
The WCF RoutingService functionality can't be used because it only supports soap-based bindings. You could use the IIS 7 URL Rewrite Module as suggested here by Matthias in the MSDN forum answer. You could configure it to redirect the calls to the internal REST based services (an overview of its use at this link). I'm not sure it will help re-write the response header contents but it's worth a look.

calling a wcf/soap method as an http get

Is there any way to enforce that a method call in soap based wcf is called as an HTTP get? I'm not sure if this would be handled on the client or server side. We wanted to have the wcf call process as a get vs. post for cacheability, etc.
I'm also not sure how to monitor a wcf service to determine if calls are doing gets or posts (or if it always does one or the other). Can I use fiddler for this?
I would imagine I could use a restful wcf service to wrap the call, but I wasn't sure if there was a way to do it straight in a soap based service.
Out of the box WCF functionality does not support SOAP HTTP GET. But WCF is extensible so you can try to develop custom binding (with cutom channel or behavior) supporting this feature.
Caching is supported in WCF 4 REST services. REST services allow all basic HTTP methods.
You can use Fiddler to monitor the gets and posts.
Check out this post about calling a WCF service with an HTTP GET.

Reading a cookie from a WCF RESTful webservice

Writing a suite of IIS hosted WCF webservices (both GET and POST), and I need to be able to read a cookie for an authentication token so I know the user has been auth'd previously.
Will HttpContext.Current.Cookies give me what I need or is there something cleaner and more appropriate for a WCF web service with WebGet and WebInvoke attributes?
string cookieHeader = WebOperationContext.Current.IncomingRequest.Headers[HttpRequestHeader.Cookie];
works for me