Link to home
Start Free TrialLog in
Avatar of jxbma
jxbmaFlag for United States of America

asked on

How do I write a C# client to consume a WCF RESTFul service with mutiple input parameters?

Hi:

I have a WCF Restful service call which expects multiple parameters.

Consider the following data and service contracts.
public class ClassA
{
   public string aString{ get; set;}
   public int aInt {get; set;}
}

public class ClassB
{
   public string bString{ get; set;}
   public int bInt {get; set;}
}

[ServiceContract]
public interface ISampleService
{
   [OperationContract(IsOneWay = false)]
   ClassC GetSomeData(ClassA classA, string sValue, ClassB classB);
}

Open in new window


I have a C#/winform based test application. I know all these parameters need to be wrapped before calling the service. I'm having difficulty figuring out what the C# code to call the service would look like on the client side.

Can someone show me an example of how I would structure the code on the client side to call the above defined service?

Thanks, JB
Avatar of Alexandre Simões
Alexandre Simões
Flag of Switzerland image

Did you create the service reference?

Once you do that, the proxy c# class will be generated for you and you can simply call the service.
In the web.config or app.config of the consumer app, you'll find the bindings and endpoint configurations, being the service url one that you have to pay special attention because it will probably change with the environment.
Avatar of jxbma

ASKER

This is a restful service.
ASKER CERTIFIED SOLUTION
Avatar of kaufmed
kaufmed
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Ah, I read RESTful and answered SOAP; sorry about that.

You're doing WCF anyway, so if you need to consume it both from HTTP and from backend C# code, why don't you create two endpoints? One SOAP and another REST.

It will make your life easier and there's nothing to change at the service implementation level.
Avatar of jxbma

ASKER

Sorry, forgot to add RESTFul decoration on service definition:

        [WebInvoke(Method = "POST",
                UriTemplate = "/GetSomeData",
                RequestFormat = WebMessageFormat.Json,
                ResponseFormat = WebMessageFormat.Json,
                BodyStyle = WebMessageBodyStyle.WrappedRequest)]

Open in new window

Avatar of jxbma

ASKER

The service supports both RESTFul and SOAP based interfaces. I've got a single winforms C@ based test app I'm using to test all my service interfaces.

How do I call a RESTFul (WCF) service with multiple parameters from a C# based client?
Well, you can do Web requests from the backend  but if your service supports soap, why don't you use it from the backend?

REST is not the best thing to use from the backend.
Using SOAP will make debugging and maintenance much easier.
REST is not the best thing to use from the backend.
Using SOAP will make debugging and maintenance much easier.
That's a highly opinionated answer, and, if we're going to be opining, quite frankly I couldn't disagree more.

Personally I find WCF to be more of a pain to work with. WCF is great out of the box. It's super quick to set up a service; super quick to deploy; super quick to add new functionality; you get the magic of "Add Service Reference"...  everything with WCF is sunshine and rainbows...right up until it breaks. Then, because WCF is such a large topic, you spend 3 days trying to track down the issue only to end up changing random configuration values until something works. Meh. I find that RESTful services are much easier to digest in terms of debugging, understanding. There is only one call to worry about when you're working with REST, whereas with WCF there may be multiple calls per one logical request as the runtime sets up the SOAP environment. </rant>

I gave you a link above to a tutorial for calling REST services. If it's not sufficient, or if you have trouble or questions regarding HttpClient, please let us know what they are.
Avatar of jxbma

ASKER

käµfm³d 👽: Thanks for the link. I can do POST, GET requests from the client for single parameters. How do I call the RESTFul interface when the interface expects multiple (complex object) parameters.
That is the basis of my question.

AS: I think you are missing the point of my question. I'm writing a simple test app to test all my service calls. All I am asking is "How do I call the RESTFul interface when the interface expects multiple (complex object) parameters."
It's out of the scope of this question to start arguing about that and, I certainly agree with you that REST is much easier than SOAP (implemented with WCF or something else).

My point here is just that the SOAP endpoint is there already, and he is using WCF, not the WebAPI or any other pure REST-oriented technology.
So if everything is already in place, at this point, it's much easier to just use the SOAP endpoint than deal with web requests from the backend, constructing the POCO objects, handling serialization and all that stuff.

If this was a "normal" REST scenario, meaning HTTP requests from a browser, I would go REST all the way, but as the scenario stands, with the WCF SOAP in place and server calls, SOAP is, IMO, the best choice.
If you're doing a GET, then the parameters go in the URL, within the querystring (e.g.  www.example.com/api/endpoint?param1=value1¶m2=value2). If you're doing a POST (or PUT), then your parameters go in the request body as either a JSON object or an XML tree. Take the DataContract for each endpoint and manually serialize (to either JSON or XML, your preference). This will give you the structure you need to put into the POST body.
If this was...the best choice.
And respectfully, I disagree. I will agree so much as to say that because he's already got WCF in place it makes sense to soldier on with it, but depending on how well-written the service is, I'd personally rewrite the WCF into Web API. My only compassion for WCF these days lies in the ability to use pipes and tcp; for HTTP-related things, I do not like SOAP. It's bulky, and the protocol itself is huge. Let's not forget that it sits atop the already existing HTTP protocol, so you're learning two protocols.

I hazard to say that back-end stuff is moving away from SOAP. It certainly is in our organization.
Sure, but did you notice the method signature?
ClassC GetSomeData(ClassA classA, string sValue, ClassB classB)

Open in new window

Plenty of complex objects there that you have to handle manually in a much more complex way than simple param1, param2.

Another thing that I didn't mention is that SOAP is more complex than REST for a reason; SOAP has a contract and REST doesn't (at least not without a lot of hacking and creativity) :)
What this contract gives us is the possibility to have types and ensure consistency.
If the service contract changes, the application will throw a pretty explicit exception, and if you refresh the service reference you'll get the compilation errors to quickly identify what changed.

With REST this is not at all the case, and probably the best way to ensure quality is to have some integration tests in place.

Well, käµfm³d, we're deviating from the subject but we're certainly having fun here :)

Cheers!!
Avatar of jxbma

ASKER

OK, the discussion was great.
But.., I still do not have an answer to my basic question.

ClassC GetSomeData(ClassA classA, string sValue, ClassB classB)

Open in new window


Yes, I realize all things you have pointed out.
I'm merely trying to test this quickly from an easy winform client.
Yes, there is plenty of complexity in the objects.

How do I make the RESTFul service call from C# client?
I'm looking for direction or someone to point me to an example.

Thanks,
JB
If you want to go the REST way, käµfm³d already gave you a very good link with plenty of examples.

I'll repost it here just as a reference, the original post made by käµfm³d is somewhere up there :)
http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client
Avatar of jxbma

ASKER

I'm still not quite getting the answer I'm looking for here.
I know how to make RESTFul service interface calls from a C# client in the case where I'm passing in 1 parameter.

For example I know how to call this:
ClassC GetSomeData(ClassA classA);

Open in new window



What I am struggling with is the multi-parameter case, where I'm passing several parameters.
What I need to figure is out how to make this call :
[WebInvoke(Method = "POST",
        UriTemplate = "/GetSomeMoreData",
         RequestFormat = WebMessageFormat.Json,
         ResponseFormat = WebMessageFormat.Json,
          BodyStyle = WebMessageBodyStyle.Bare)]
ClassC GetSomeMoreData(ClassA classA, string sValue, ClassB classB);

Open in new window



käµfm³d 👽 Regarding your comment:
If you're doing a POST (or PUT), then your parameters go in the request body as either a JSON object or an XML tree. Take the DataContract for each endpoint and manually serialize (to either JSON or XML, your preference). This will give you the structure you need to put into the POST body.

I am not clear how to do this. Can you point me to a specific example which is similar to what I am trying to accomplish? There are lots of examples out there for service interfaces consuming single parameters.

Thanks
JB
Avatar of jxbma

ASKER

The easiest way I figured out to do this was to create a RESTFul interface that accepts an ArrayList.

On the client side, the desired complex parameters (classes) are serialized to a string and then inserted into the ArrayList.

On the service side :
1) Verify the ArrayList contains the desired number of parameters
2) Deserialize the complex objects from the incoming ArrayList

Thoughts?
Did you try RestSharp already?

There are too many things to handle here, and I'm starting to see you degrading the quality of your service in order to be able to connect to it the way you want. This is not good.

RestSharp will handle all that parsing boilerplate for you. It even accepts placeholders on the URL so that you can do a POST with some arguments on the URL and others on the body (see the main example)