Can ServiceStack mimic a WCF response? - c#

I'm trialling out ServiceStack and loving what I'm seeing so far. However I've run into a bit of a brick wall.
I have a system retrieving data from another system via web services - a service at both ends. These two systems are from different vendors - so I have no control over changing them - and are configured to talk to each other via WCF web services. Let's say "Lemon" calls "Orange" to get some information about a customer.
The way we implement these two systems is slightly different to what the vendors planned - we point their service configuration to our intermediary service - let's call it "Peach" - which goes off and does some other things before returning the information. For example, "Lemon" calls what it thinks is "Orange" but is actually our intermediary service "Peach" using the same method names. "Peach" calls "Orange" for the customer information and for example overrides the email address for the customer with something else before combining all the information appropriately and returning it to "Lemon" in the format it was expecting.
I would like to get "Peach" using ServiceStack. However it's responses needs to be identical to a WCF service returning via wsHttpBinding. Is this possible with ServiceStack? Would it involve overriding the Soap 1.2 type?
Thanks for your help!

If ServiceStack's built-in SOAP Support doesn't return the response you're after, you may need to return the exact SOAP response you're after as a raw string.
Raw Access to WCF SOAP Message
To access the WCF's Raw Request in your Service you can use the IRequiresSoapMessage interface to tell ServiceStack to skip de-serialization of the request and instead pass the raw WCF Message to the Service instead for manual processing, e.g:
public class RawWcfMessage : IRequiresSoapMessage {
public Message Message { get; set; }
}
public class MyServices : Service
{
public object Post(RawWcfMessage request) {
var requestMsg = request.Message... //Raw WCF SOAP Message
}
}
Creating custom WCF Response
Some level of customization is possible by creating a custom WCF Message response and returning the raw output as a string, e.g:
var wcfResponse = wcfServiceProxy.GetPeach(...);
var responseMsg = Message.CreateMessage(
MessageVersion.Soap12, "urn:GetPeach", wcfResponse);
return responseMsg.ToString();
Otherwise you may need to use a HTTP Client like Http Utils to POST raw SOAP to the WCF Service and return the raw string Response.

This question isn't specifically related to WCF. What WCF returns is not a construct of WCF, it is returning a standards based response as specified by the WS* standards. http://en.wikipedia.org/wiki/List_of_web_service_specifications lists many of the standards.
Your question isn't specifically making ServiceStack emulate WCF, it is for ServiceStack to return responses adhering to existing published standards. Standards that WCF has already built in with the WsHttpBinding configuration.

Related

Why does a WCF web service not receive the client payload?

I have inherited a web service built to receive calls from a third party system, "System A". It was a POC that may not have any active functions calling it and I suspect it was only tested from SoapUI or the like and never from the application it was designed for.
When System A is configured to call it, the service is called but the payload, one complex-type parameter, is null.
I have two other web services written years ago that accept calls of the same type from the same function of System A. Pointing System A to either of these services results in the parameter being supplied. Contracts and WSDLs look very similar and the only variations I see (like differing namespaces) seem to vary between the two services that do work.
What would cause a web service to not receive the payload in the call?
Related, where should I look to find it? The parameter is getting dropped between System A calling and the web service code itself getting hit. I've checked the trace logs but see nothing that I recognize as useful.
namespace MyNamespace.StandardNoteReceiverService
{
public class StandardNoteReceiverService : IReceiveNoteService
{
public StandardNoteReceiverResponse ReceiveNote(ReceiveNoteData standardNoteReceiverRequest)
{
string x = standardNoteReceiverRequest == null ? "NULL" : "ok";
LoggingLib.Log($"Service called. Paramter status: {x}");
return NoteReceiverServiceLayer.ReceiveNote(standardNoteReceiverRequest);
}
}
}
which implements
namespace MyNamespace.StandardNoteReceiverService
{
[ServiceContract]
public interface IReceiveNoteService
{
[OperationContract]
StandardNoteReceiverResponse ReceiveNote(ReceiveNoteData standardNoteReceiverRequest);
}
}
It turned out to be the parameter naming. Once I changed the name of the parameter to be the same as the name used by the services that are working, it began receiving the data.
public class StandardNoteReceiverService : IReceiveNoteService
{
public StandardNoteReceiverResponse ReceiveNote(ReceiveNoteData NoteData)
{ ...
How did you build “System A”? Is it a WCF Web HTTP service or an ancient soap web service? How does the client call the service and send the parameter? I think it may be that the format of the parameters sent by the client is incorrect. In the Rest-style service created by WCF, using complex objects as parameters to pass data may not always receive the value of the parameter on the server because of the format of the parameter.
Get the object is null using JSON in WCF Service
While in the WCF SOAP web service, the invocation is completed with a client proxy, the parameters are strong-typed. If the server always gets null, it might be caused by other issues.
I suggest you create a minimal, producible example so that I can try to offer a workaround instead of offering speculation of this issue here.
Feel free to let me know if the problem still exists.

Consume SOAP webservice with GET instead of POST

I need to call an external SOAP webservice over HTTP.
I have the WSDL file and added it in Visual Studio via 'Add service reference'. Visual studio then added a number of files, in the reference file i can find this:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="Service.IService")]
public interface IService {
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/Function", ReplyAction="http://tempuri.org/IService/FunctionResponse")]
namespace.Service.ExecuteFunctionResponse ExecuteFunction(namespace.Service.FunctionRequest request);
}
With additionaly the async version of this call and the objects for sending an receiving, etc.
To call the service I added the folowing code:
BasicHttpBinding binding = new BasicHttpBinding();
EndpointAddress endpointAddress = new EndpointAddress("the address");
serviceChannel = new ServiceClient(binding, endpointAddress).ChannelFactory.CreateChannel();
Response response = serviceChannel.ExecuteFunction(new Request(...));
This results in me getting an exception, error 405 method not allowed.
So it appears I must use a HTTP GET request instead of the default POST request. But i cannot find where this can be altered in with this way of working.
So, where can i set the HTTP method for this call to a webservice?
SOAP services are using HTTP POST because they exchange XML messages (which tend to be complex) and cannot be transferred in a query string.
Are you sure that you must use HTTP GET? Maybe the error you are receiving "405 method not allowed" is caused by some bad configuration.
I would double check the SOAP endpoint URL is set correctly and check that there are no additional security requirements needed.
EDIT
In past, there was a practice to create ASP.NET Web Services which would accept GET as well. But they wouldn't expect XML messages. Instead, you would have to pass all parameters in a querystring. For example: https://foo.bar/service.asmx/Func?param1=X&param2=Y (where param1 and param2 are the expected parameters).
This way it is possible to call a WebService without a need for WSDL and using GET method. You can achieve it by using HttpClient for example.
The downside of this approach is that you will have to deal with plain data instead of objects.
I hope it might help.

ServiceStack Renaming SyncReply Client

I am looking at using a ServiceStack web service in place of an existing third-party web service. I have matched the DTOs used by the third-party service. However, the client is expecting a proxy class named "NotificationServiceClient", like this:
var client = new NotificationService.NotificationServiceClient();
var response = client.SendNotification(message);
I am unable to alter the source code for the client application, so I would like to configure ServiceStack to use NotificationService for the client proxy, instead of SyncReply. Is there a way to do this?
UPDATE - It seems what I'm looking for is a way to configure ServiceStack so that it generates a different value for the name attribute of the wsdl:service tag; from SyncReply to NotificationServiceClient. I can save the current WSDL, manually manipulate it, and verify the proxy class name using a throw-away client.
Don't use ServiceStack's .NET Service Clients for consuming 3rd Party APIs, they're only designed and opinionated towards consuming ServiceStack Services.
The only HTTP Client we recommend for calling 3rd Party APIs is HTTP Utils which is a our general purpose HTML client.
Based on the comment by mythz, I have overridden the GenerateWsdl in my AppHost, and set the ServiceName property on the wsdlTemplate. Here's an example:
public override string GenerateWsdl(WsdlTemplateBase wsdlTemplate)
{
wsdlTemplate.ServiceName = "NotificationService";
return base.GenerateWsdl(wsdlTemplate);
}

WCF Rest service to receive Push notification data

I have Restful WCF service which will be used to read the data push by another Restful service hosted somewhere on the internet. I have to expose one method to read the Json data push by the other service.
[ServiceContract]
public interface ITestService
{
[OperationContract]
[WebInvoke( Method = "GET",
ResponseFormat = WebMessageFormat.Json )]
string GetData(string JsonData);
}
Is it right to receive data in string parameter or should i make the DataContract (Class) to receive the Json data. I know the structure of the Json data push by other service and Is it ok to make Get Method ? Also Push service can send bulk of data at once. how can i restrict it so my server works fine even with bulk data.
I personally don't like the default JSON handling in WCF and thus we use Newtonsoft.Json! We define the data values as string and then check the incoming data versus a JSON Schema file. In my opinion it depends on how extensive you use WCF. For use we use WCF primarily for tcp connections where we use the defined Data interfaces. The REST api is just for internal debugging and not exposed. So a clearly documented api isn'T that important. By defining proper data contracts you can utilize the automated docs WCF generates under the root url of the restful service + /help.
Anyway you should NOT use an HTTP GET to receive push notifications.
POST/PUT would be an appropriate endpoint for a push notification. The following article explains quite well how and why to define REST routes the way to be:
http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api#restful
Hope that helps a bit.

Protocol Buffers over HTTP GET using WCF

I have a WCF service hosted that is returning a byte[] of protobuf-net serialized data. Originally this was hosted over the default webHttpBinding settings (SOAP) and everything was working properly. I recently found out that I need to call HTTP GETs and POSTs directly from our client so I thought it'd be easier to switch to use a RESTful service. I switched to use the WebGet attribute and the WCF REST Template.
I attempted to create a simple web site to test the client and I'm having trouble deserializing the data. This is an example of how I'm calling the service:
using (WebClient client = new WebClient())
{
result = client.DownloadString(url);
}
// Deserialize
BinaryVehicles binVehs;
using (var ms = new MemoryStream(StrToByteArray(result)))
{
binVehs = Serializer.Deserialize<BinaryVehicles>(ms);
}
An example of what is returned in "result":
< base64Binary xmlns="http://schemas.microsoft.com/2003/10/Serialization/">ChsKCzEyMy00NTYtNzg5EgU0NDAwMBoFQmxhY2sKHAoLOTYzLTg1Mi03NDESBTIzMDAwGgZTaWx2ZXI=< /base64Binary>
I also attempted to deserialize the data between the < base64Binary > tags with no results. Does anyone have any idea on how I should go about sending the binary protobuf-net data from an WebGet method and how I should deserialize the data? Thanks.
protobuf-net primarily handles just the serialization aspects (the protobuf spec by Google doesn't define any further than this). So it really comes down to: how are you serializing it?
I must admit that the WCF GET approach is not something I've looked at hugely, so there is no special handling there. One simple approach may be to look at just returning a string, and handling the base-64 encoding yourself, but to be honest if you are doing HTTP GET, then WCF itself seems overkill.
I blogged here about using ASP.NET MVC at the server for protobuf via HTTP GET. The linked sample code also includes a wire-compatible ASP.NET implementation.
If there is something appropriate we can do to make WCF GET easier, I'm all ears...

Categories

Resources