Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Introduction to Rest.API.Translator

4.69/5 (4 votes)
27 Apr 2020CPOL2 min read 16.8K  
Communicate with REST API using interface and expression instead of URL
The point of this library is to make things easier and also add structure to our code when we communicate with REST API. In this article we look at: How you could convert those URL calls to Methods, build an interface, and how to control which parameter gets posted in the body and which parameter gets posted in the query.

Introduction

When you work with REST API, the biggest issue is the unstructured URLs and HttpClient calls.

Rest.API.Translator make things much easier for you to communicate with the REST API.

Changes

Added FromQueryAttribute to control how the parameter gets processed.

Background

Back in the old days before REST API, we used WCF. Some still prefer WCF because of the structor and the auto generated classes.

REST API made things much easier and more flexible but with every + there is a -.

With REST API, there are no auto generated classes.

So with the help of the URLs and HttpClient, you could communicate with the API.

Now Rest.API.Translator does all that job for you, you only need to build an interface and configure it, and all the URL buildings, HttpClient calls and json handler will be done automatically.

Nuget

Using the Code

Now imagine that you have a mobile application and you want to get some data from a REST API.

Let's say here that those APIs exist in the following URLs:

C#
// It's an HttpGet Method with two parameters [string]firstName and [string]lastName
http://go.com/api/db/GetName?firstName=alen&lastName=toma

// It's an HttpPost Method with parameter object [User]user
// the parameter object have to be  posted as json
http://go.com/api/db/SaveUser

// It's an HttpPost with parameter [string]musicId which is the value test
http://go.com/api/y/GetMusic/test

HttpGet Get the HTML from the site
http://google.com

With the normal way, we would use HttpClient. Read here to know how it's normally done.

And let's see how Rest.API.Translator works, and how you could convert those URL calls to Methods.

If we look at the URL http://go.com/api/db/GetName, we know that the baseaddress is http://go.com followed by a key or identifier which is api there after we have the controller name which is db and lastly the method name which is GetName.

Let's put what we explain above into code and let's build an interface that presents those urls.

C#
// When you have fullUrl:false, the library will then join the interface name with relativeUrl
// so the result will be api/db.
// The library removes I and <code>Controller from the Name. You could still override how 
// Name extraction work if you override ControllerNameResolver()
// fullUrl:true will mean that the value of relativeUrl won't be changed. 
// there are other settings you could read about route attributes down below
[Route(relativeUrl:"api", fullUrl: false)]
public interface IDbController
{
 // httpMethod by default is MethodType.GET
 [Route(httpMethod: MethodType.GET)]
 string GetName(string firstName, string lastName);
 
 // Se here we override the method name which Saved and changed it to SaveUser
 [Route(relativeUrl: "SaveUser", httpMethod: MethodType.JSONPOST)]
 Task Save(User user);
 
 // See here what we did with relativeUrl. GetMusic exists in 
 // a different controller and it does not exist in Db but it exist in "y"
 // so we know that the start url will baseUrl/api/db and with ../ 
 // we got baseUrl/api/ and we appended it with y/GetMusic 
 // Now you could build an interface for YController or otherwise, 
 // you have to override the relativeUrl
 // When you normally have a query string, it always follows by ?musicId=value
 // but you could override this setting with parameterIntendFormat:true
 // and build a querystring by / eg /value
 [Route(httpMethod:MethodType.Post,relativeUrl: "../y/GetMusic", parameterIntendFormat:true)]
 Music GetMusic(string musicId)
 
 // with GoogleCall, we have a whole different URL that's why we specified 
 // fullUrl:true and added the full path for the site
 [Route(relativeUrl:"http://google.com", fullUrl: true)]
 string GoogleCall();
} 

Ok, now that we have built the interface, we are ready to begin communicating with our API using Rest.API.Translator

C#
// Now APIController controller need a baseUrl to work with and that is http://go.com
using(var client = new APIController<IDbController>("http://go.com"))
{
 string name= client.Execute(x=> x.GetName("alen", "toma"));

 string html = client.Execute(x=> x.GoogleCall());

 Music music = await client.ExecuteAsync(x=> x.GetMusic("1152_test"));

 // you could also use and AsyncExtension .Await(); and make it none async method.
 await client.Execute(x=> x.Save(user));
}

Now for those that want to add some header to the HttpClient or simply want to use your own HttpClient, you could simply do it like below:

C#
using(var client = new APIController<IDbController>(new HttpClient(), "http://go.com")){

}

// Or Simple make changes to the already created <code>HttpClient</code>
// client.HttpHandler.Client

Sometimes, we don't like to use Attributes in the class and would like to be able to somehow add those attribute settings dynamically.

Well, you could do that still by using AddInterfaceRoute() and AddMethodRoute.

C#
// When your application start, You could add those settings dynamically.
// Those settings are saved in a static variable, so you only add them once.
 using(var client = new APIController<IDbController>()){
    client.AddInterfaceRoute(relativeUrl:"api");
    client.AddMethodRoute(nameof(IDbController.GoogleCall),
                          relativeUrl:"http://google.com", fullUrl: true);
  }

FromQuery

Now there is sometime we want to be able to control which parameter gets posted in the body and which parameter get posted in the query.

The HTTPPost and JsonPost by default it post all the parameters to the body. We could control this behavior by using the attribute FromQueryAttribute. Here is an example:

C#
    // Now if we look at this method then our quary will be like 
    // http://test.com/GetSetting/?key=xxx and the user will be posted as json body   
    [Route(httpMethod: MethodType.JSONPOST)]
    ApplicationSettings GetSetting([FromQuery]string key, User user);

Attributes

C#
    /// <summary>
    /// Add this to your parameter so you could tell restapi to add it as a query eg?test=value
    /// this is only applied to HttpPost and httpjsonpost
    /// </summary>
    [FromQuery]

    // Add header to specific method eg [Header("User-Agen","???")]
    [Header]

    /// <summary>
    /// Empty relativeUrl mean the method name is the relativeUrl
    /// </summary>
    /// <param name="relativeUrl">api/ or ../api its a relative path to the baseUrl</param>
    /// <param name="httpMethod"> Default Get</param>
    /// <param name="fullUrl"> 
    ///  As full path , will ignore the baseUri and use the 
    ///  relativeUrl as full path. fullUrl above the interface will mean that 
    ///  it will ignore the interface name and only use the relativeurl </param>
    /// <param name="parameterIntendFormat">Instead of ?Name=test it will be /test</param>
    [Route]

Points of Interest

The point of this library is to make things easier and also add structure to our code when we communicate with REST API.

If you have any ideas or suggestions for improvements which you think are a must, then please let me know.

The code exists here if you are interested in downloading it or maybe helping me to improve the library.

History

  • 15th August, 2019: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)