0

I am doing a Xamarin Forms project that requires connection to a WCF service. I must use Rest to access it, so I opted to use a PCL-compatible build of RestSharp. I have done many SOAP based web services, but this is my first dive into Rest, and I feel like I am missing something very basic. I have confirmed that my web service functions correctly when I make SOAP calls, so I believe I have set something up incorrectly.

Here is sample code for my web service:

Imports System.IO
Imports System.Net
Imports System.ServiceModel
Imports System.ServiceModel.Description
Imports System.ServiceModel.Web

<ServiceContract()>
Public Interface Iapi
    <WebInvoke(Method:="PUT",
           UriTemplate:="Login/Email/{Email}/Password/{Password}",
           RequestFormat:=WebMessageFormat.Json,
           ResponseFormat:=WebMessageFormat.Json)>
    <OperationContract(AsyncPattern:=True)>
    Function Login(email As String, password As String) As String
End Interface

Here is sample code for my attempt to call the service:

public void Login(string email, string password)
    {
        RestClient client = new RestClient("http://www.example.com/service.svc/");
        RestRequest request = new RestRequest
        {
            Method = Method.PUT,
            Resource = "Login/Email/{Email}/Password/{Password}",            
            RequestFormat = DataFormat.Json
        };

        request.AddParameter("Email", email, ParameterType.UrlSegment);
        request.AddParameter("Password", password,ParameterType.UrlSegment);

        client.ExecuteAsync(request, response => {
            session = response.Content;
            ActionCompleted(this, new System.EventArgs());
        });            
    }

When I make the call above, I get no exceptions, just an empty string return value. The same thing happens in the browser. I suspect my service definition. I have several questions that are probably a bit basic, but I hope will also help other WCF/Rest beginners in the future.

1. What, if anything, is wrong with my UriTemplate in the definition of my service? What would a proper UriTemplate look like?

2. Should I be using the PUT method for this kind of service call, or is GET or POST more appropriate?

3. Is anything else obviously missing from my web service definition?

4. Am I correct in passing the full service uri (http://www.example.com/service.svc/) to the Rest client?

5. Any additional suggestions for a Rest beginner, specifically in relation to the WCF-Rest combination?

vbnet3d
  • 1,151
  • 1
  • 19
  • 37

1 Answers1

1
  1. A proper URI-template could look something like this if you're using a GET:

C#

[OperationContract]
[WebGet(UriTemplate  = "Book/{id}")]
Book GetBookById(string id);

VB:

<OperationContract()> _ 
<WebGet(UriTemplate:="Book/{id}")> _ 
Function GetBookById(ByVal id As String) As Book

Then you can call it using http://example.com/Book/1 for the book with ID==1.

  1. In the Microsoft-world PUT is often used for creating or updating data, such as a new task, order etc. However, you CAN use it for login even if I personally think a POST or GET would be the more accurate approach. But that's just my oppinion.

See this question for more information: PUT vs POST in REST

  1. There's nothing that seems to be missing in you declaration.

  2. If you cannot reach it with a browser, it's probably not the usage of RestSharp that's wrong. However, here's some notes. When using async methods you will often want to try using .NET's async/await-pattern. Then the request doesn't lock the main thread.

Example: http://www.dosomethinghere.com/2014/08/23/vb-net-simpler-async-await-example/

Here's a little piece of code that I use in my Xamarin-projects for invoking services:

protected static async Task<T> ExecuteRequestAsync<T>(string resource,
    HttpMethod method,
    object body = null,
    IEnumerable<Parameter> parameters = null) where T : new()
{
    var client = new RestClient("http://example.com/rest/service.svc/");
    var req = new RestRequest(resource, method);
    AddRequestKeys(req);

    if (body != null)
        req.AddBody(body);

    if (parameters != null)
    {
        foreach (var p in parameters)
        {
            req.AddParameter(p);
        }
    }

    Func<Task<T>> result = async () =>
    {
        var response = await client.Execute<T>(req);
        if (response.StatusCode == HttpStatusCode.Unauthorized)
            throw new Exception(response.Data.ToString());
        if (response.StatusCode != HttpStatusCode.OK)
            throw new Exception("Error");

        return response.Data;
    };

    return await result();
}
  1. Yes, that's correct.

  2. How do you host your WCF? If using IIS, what does your web.config look like? Here's an example:

As a side note, I noticed you mentioned that you require access to a WCF-service. Have you considered using .NET Web API instead? It provides a more straight-forward approach for creating RESTful endpoints, without the need for configs. It's more simple to implement and to use, however it does not provide the same flexibility as a WCF-service does.

For debugging a WCF-service I strongly recommend "WCF Test client": https://msdn.microsoft.com/en-us/library/bb552364(v=vs.110).aspx

Where can I find WcfTestClient.exe (part of Visual Studio)

With metadata-enabled in your web.config, you will be able to see all available methods. Example-configuration below:

<configuration>
  <system.serviceModel>
    <services>
      <service name="Metadata.Example.SimpleService">
        <endpoint address=""
                  binding="basicHttpBinding"
                  contract="Metadata.Example.ISimpleService" />
      </service>
    </services>
    <behaviors>

    </behaviors>
  </system.serviceModel>
</configuration>

Source: https://msdn.microsoft.com/en-us/library/ms734765(v=vs.110).aspx

If it doesn't help, could you provide your web.config and implementation of your service as well?

Community
  • 1
  • 1
smoksnes
  • 10,509
  • 4
  • 49
  • 74
  • That is extremely helpful, and by far the best explanation I have seen of this topic. Thank you very much! I will look into WebAPI also. I have been doing desktop and server software for more than a decade, but Web/Mobile is a new world for me. Your answer here gives me those pieces I was missing! – vbnet3d Sep 04 '15 at 13:05
  • Glad to help. What was the problem/solution in your case? – smoksnes Sep 04 '15 at 19:47
  • I actually switched to a pure JSON approach, a la ServiceStack just because of time constraints with this project - I had to make the call before your answer came. The basic problem was that I did not understand WCF and Rest well enough to make a sound implementation. – vbnet3d Sep 04 '15 at 20:38
  • @smoksnes, i'm trying to consume a rest over wcf, but i'm not getting. The service is a POST and went to developed by other company. I need to send two parameters json(`{"iduser:1","idindicador:2"}`) and i receive a json response like this(`{"real:235.00","projetado:250.00"}`). How do i send the json file as parameter? – pnet Jan 11 '18 at 11:48