Click here to Skip to main content
15,867,568 members
Articles / Web Development / HTML

.NET Web API 2.0 Service with a Java Client

Rate me:
Please Sign up or sign in to vote.
5.00/5 (9 votes)
9 Oct 2014MIT8 min read 54.5K   786   16   12
Web API was introduced and was recently streamlined into Web API 2.0. This framework is heaven for C#/.NET services developers. It allows you to get a RESTful API in .NET up and running in less than an hour. As you'll see it's also just as easy to consume that API in another programming language.

Web API RESTful File Server and Java Client.

Writing APIs that are cross-platform and cross-language has not always been an easy thing to do and certainly hasn't always been lightweight stuff. However, with JSON taking over the world thanks to JavaScript, RESTful APIs seem to be emerging as one of the best ways to do this sort of thing. Being resource driven, the RESTful API certainly has its limitations, e.g. when streaming lots of data, but for most use cases this type of API is more than adequate. If you don't believe me, then believe Google as they use them all over the place.

Up until recently in .NET, building a RESTful API required lots of work and was anything but light weight. It entailed setting up lots of configuration end points, dealing with service contracts, and setting up interfaces through WCF.

All of that has since changed; Web API was introduced and was recently streamlined into Web API 2.0. This framework is heaven for C#/.NET services developers. It allows you to get a RESTful API in .NET hosted inside IIS or as a Windows Service (Sometimes referred to as self hosted via OWIN) in less than an hour.

I am going to build a simple API that serves up files from the file system using ASP.NET Web API 2.0 and consume that same API via a client in Java. It will look something similar to this.

Image 1

Web API end points can be consumed via any language that has a HTTP Client implementation, which is basically almost all programming langugaes.

So you may be asking, "Why Java?" The answer is simple in that this is a very common use case. Java is a very popular language and widely used in the enterprise. Since enterprises have lots of services; Java will be one of the most common ways to consume these end points. Although this is not very difficult to do very few examples showing how to do it actually exist. Obviously the most common use cases are consuming Web API via JavaScript and .NET on the client side but Microsoft has plenty of great tutorials on how to do that.

Now let's get to work!

We will build a Web API Service that will serve up files from a folder on the server side. Normally in a real scenario these files will come from some document store, in some cases a database, or even another API.

Image 2

Image 3

Let's add some unit tests as well!

Now we should have a fully functional Web API Service. Visual Studio gave us a free ValuesController which we aren't going to use but is a nice stub for you to add your functionality to.

Let us rename the auto-created ValueController to FileServerController and delete all of the stub functions created for us in there as we will write our own. Let us also declare the location where we will store our files on the server side.

It is also really great practice to inject in any external objects into our controller rather than instantiate them directly inside. For that we will use the Unity dependency injection framework. Create a constructor for the controller that takes in a single object of type IFileServer as follows:

public class FileServerController : ApiController
{
    private readonly IFileServer _fileServer;

    public FileServerController(IFileServer fileServer)
    {
        _fileServer = fileServer
    }
}

Next let's create the IFileServer interface by right clicking on the main project and going to "Add new item" and under code adding the interface as follows:

public interface IFileServer
{
    IList<FileInformation> GetFiles();

    FileInformation GetFileInfo(int id);

    Stream GetFileData(int id);
}

Our interface now has some very simple functions. Visual Studio may be throwing an error regarding the "FileInformation" object which does not yet exist.

Next let us go to our models and create that. Under the models folder right click and add a new Class and name it FileInformation and it should look like the following:

public class FileInformation
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    public string Extension { get; set; }
    public string FullFilePath { get; set; }
    public string Description { get; set; }
    public DateTime CreatedTimestamp { get; set; }
    public DateTime UpdatedTimestamp { get; set; }
    public string ContentType { get; set; }
}

Now let us implement the IFileServer interface we created earlier by adding a New Class to our project called FileServer. Normally if we were talking to a database or some document store we may want some more abstraction here by having a Context Class etc. but we will keep things really simple.

Initially our class looks really simple:

public class FileServer : IFileServer
{
    public IList<FileInformation> GetFiles()
    {
        throw new NotImplementedException();
    }

    public FileInformation GetFileInfo(int id)
    {
        throw new NotImplementedException();
    }

    public byte[] GetFileData(int id)
    {
        throw new NotImplementedException();
    }
}

Let us add some real functionality now. Such as the location where we will look for the files (Again this would normally not be a hard coded value but either a document store or a setting in our "App.Config or Web.Config").

private static readonly string ServerFolder = "C:\\Temp\\WebApi";

private Dictionary<int, FileInformation> _fileDescriptions;

A constructor that will fill our internal dictionary:

public FileServer()
{
    _fileDesc = new Dictionary<int, FileInformation>();
    FillDictionary();
}

A function which will fill our dictionary called FillDictionary().

private void FillDictionary()
{
    //We are going directly to the file system
    //To fill our internal dictionary but
    //Ideally we would get these somewhere else.

    FileInfo fi;
    int id = 0;

    var files = Directory.GetFiles(ServerFolder).ToList();

    foreach (String file in files)
    {
        fi = new System.IO.FileInfo(file);
        _fileDesc.Add(id,
            new FileInformation
            {
                Id = id,
                Name = Path.GetFileName(file),
                Extension = fi.Extension,
                FullFilePath = fi.FullName,
                Description = "temp image",
                ContentType = "application/png",
                CreatedTimestamp = fi.CreationTime,
                UpdatedTimestamp = fi.LastWriteTime
                });
            id++;
        }
    }

Next up let us implement our functions from our interface.

Getting the file list is really easy since all the files will be inside of our dictionary when we create the FileServer.

public IList<FileInformation> GetFiles()
{
    return _fileDesc.Values.ToList();
}

The GetFileInfo() function is also very easy to implement.

public FileInformation GetFileInfo(int id)
{
    FileInformation fileInfo;
    if (_fileDesc.TryGetValue(id, out fileInfo))
        return fileInfo;
    else
        return null;
}

Getting the File Data is also very straight forward and using standard .NET APIs works great for this.

public Stream GetFileData(int id)
{
    FileInformation fileInfo;
    bool ok = _fileDesc.TryGetValue(id, out fileInfo);

    if (ok)
        return new FileStream(fileInfo.FullFilePath, FileMode.Open);
    else
        return null; 
}

When we build or run our solution we may get an error about our controller not being accessible. This is because we are injecting in our FileServer. We will need to create some boilerplate code which basically allows Dependency Injection to work with Web API.

Again if we wanted to simply remove the dependency injection we would change our controllers constructor to the following:

public FileServerController()
{
    _fileServer = new FileServer();
}

(If you skipped the Dependency Injection by creating your object inline then you can skip this section and go right to the the Web API Controller Service)

Web API Dependency Injection

If you chose not to skip then we will do things the right way here and inject our FileServer. We will need to add Unity via Nuget.

Image 4

Next we will add a required class which is basically right from Microsoft and allows you to use Unity as your DI framework. I added this to a folder called DI but you can add it in the main project and that will work fine.

public class UnityIoC : IDependencyResolver
{
    protected IUnityContainer container;

    public UnityIoC(IUnityContainer container)
    {
        if (container == null)
        {
            throw new ArgumentNullException("container");
        }
        this.container = container;
    }


    public object GetService(Type serviceType)
    {
        if (!container.IsRegistered(serviceType))
        {

            if (serviceType.IsAbstract || serviceType.IsInterface)
            {
                return null;
            }
        }
        return container.Resolve(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        try
        {
            return container.ResolveAll(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return new List<object>();
        }
    }

    public IDependencyScope BeginScope()
    {
        var child = container.CreateChildContainer();
    return new UnityIoC(child);
    }

    public void Dispose()
    {
        container.Dispose();
    }
}

After adding that class we then need to go to our App_Start folder and find the WebApiConfig class. This class is where our Web API routes are configured and where our API comes to life.

In here we need add to the configuration object our DependencyResolver as follows:

var container = new UnityContainer();

container.RegisterType<IFileServer, FileServer>(new HierarchicalLifetimeManager());

config.DependencyResolver = new UnityIoC(container);

The whole WebApiConfig class looks as follows:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services

        // Web API routes
        config.MapHttpAttributeRoutes();

        var container = new UnityContainer();
        container.RegisterType<IFileServer, FileServer>(new HierarchicalLifetimeManager());
        config.DependencyResolver = new UnityIoC(container);

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

To find out more on Web API Dependency Injection and how it works go to Microsoft at Dependency Injection for Web API Controllers

The End Points.

Let us now wire up our application logic with our end points. We go back to our FileServerController class and add our end point functions.

[RoutePrefix("fileserver")]
public class FileServerController : ApiController
{
    private readonly IFileServer _fileServer;

    public FileServerController(IFileServer fileServer)
    {
        _fileServer = fileServer;
    }

    [Route("allfiles")]
    [HttpGet]
    public IEnumerable<FileInformation> GetAllFiles()
    {
        return null;
    }

    [Route("download/{id}")]
    [HttpGet]
    public HttpResponseMessage DownloadFile(int id)
    {
        return null;
    }
}

A few things to point out in the above code. The routes to our API from the URL can be fixed via the WebApiConfig or they can be hard coded via data annotation as done above. The above is usually not a good idea for a really large service but for something small it helps highlight where you will land by following the route.

Next let us wire up our application logic which is in our FileServer class to our end points.

We can see that to get all files from our file server will be really easy.

[Route("allfiles")]
[HttpGet]
public IEnumerable<FileInformation> GetAllFiles()
{
    return _fileServer.GetFiles();
}

To actually download one of the files through our API is also fairly straight forward as shown below.

[Route("downloadfile/{id}")]
[HttpGet]
public HttpResponseMessage DownloadFile(int id)
{
    var fileInformation = _fileServer.GetFileInfo(id);

    var path = fileInformation.Name;
    var result = new HttpResponseMessage(HttpStatusCode.OK);
    var stream = _fileServer.GetFileData(id);
    result.Content = new StreamContent(stream);
    result.Content.Headers.ContentType = new MediaTypeHeaderValue(fileInformation.ContentType);

    return result;
}

We are creating a HttpResponseMessage and we are embedding our stream of data from the file system to that.

We are now officially done with the Web API Service! If we right click and run that under debug we should be able to see our APIs.

Java Client for the Web Api Service.

Next up let us create our Java project using Eclipse or your favorite Java IDE. I am using Eclipse but any Java IDE will be just fine.

Image 5

Image 6

Let's add a few JAR files that will allow us to communicate with our Web API RESTful Service. These JARs are fairly standard one is from Google called GSON and the others are from Apache. Since we built a standard RESTful service we simply need an HTTP client to consume the end points and we use Google GSON to map the JSON that is returned to an internal Object (Or Bean as they say in Java).

Image 7

Those JARs can be found by searching for Google GSON and Apache HTTP Client to get the latest or follow the below links.

Obviously you can use Maven or any other mechanism to get these as well.

Let us add a new main class that will consume the Web API endpoints.

Image 8

public class JavaWebApiApp {

    public static void main(String[] args) {
       // TODO Auto-generated method stub
    }
}

We create our bean which really maps one to one with our Object in C#. Except I will map the DateTime items to Strings in Java.

public class FileInformation {

private int Id; 
private String Name;
private String Extension;
private String FullFilePath;
private String Description;
private String CreatedTimestamp;
private String UpdatedTimestamp;
private String ContentType;

//Getters setters etc.
//...
}

Next up let us write the code in Java that will consume the end point and grab the objects from our RESTful API.

public static ArrayList<FileInformation> httpGet(String url, String function) {

    ArrayList<FileInformation> dataFromService = new ArrayList<FileInformation>();
    try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
        HttpGet request = new HttpGet(url+function);   
        request.addHeader("content-type", "application/json");
        HttpResponse result = httpClient.execute(request);
        String json = EntityUtils.toString(result.getEntity(), "UTF-8");  

        com.google.gson.Gson gson = new com.google.gson.Gson();                       
        FileInformation[] response = gson.fromJson(json, FileInformation[].class);

        System.out.println(response.length);   
        for(FileInformation file : response)
        {
            dataFromService.add(file);
             System.out.println(file.toString());
        }

    } catch (IOException ex) {
    }
    return dataFromService;
}

What we have there is just some basic use of the Apache HTTP Client. We are going to the end point and consuming the returned JSON and binding it to our Bean using Google GSON.

If we call that from our main function:

public static void main(String[] args){

    String url = "http://localhost:53667/fileserver/";

    httpGet(url, "getallfiles");
}

We will now get the following:
Image 9

Next let us add the ability to download the file.

Add the following to our main:

OutputStream downloadedDoc0 = httpDownloadFile(url,"downloadfile",0);
System.out.println(downloadedDoc0.toString());

Then the following code to download the stream:

public static OutputStream httpDownloadFile(String url, String function, int fileId) 
{

    ByteArrayOutputStream byteOutPutStream = new ByteArrayOutputStream();

    try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) 
    {
        HttpGet httpRequest = new HttpGet(url+function+"/"+fileId);
        HttpResponse result = httpClient.execute(httpRequest);
        HttpEntity resEntity = result.getEntity(); 
        resEntity.writeTo(byteOutPutStream);

        EntityUtils.consume(resEntity);
   }
   catch (Exception e) 
   {
        System.out.println(e);
   }

    return byteOutPutStream;
}

Image 10

If you get all of that, that means it worked and you have the data in your Java app!

That is it! We now know how to make a Web API Service and then consume that via Java!

Let's see what the finished API Service looks like.

Image 11

Image 12

Image 13

Image 14

If you like these tutorials feel free to come by the blog at http://louiebacaj.com.

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Software Developer (Senior)
United States United States
Louie Bacaj is a Senior Software Engineer with an M.S. in computer science; experienced scaling multi-million dollar software projects to several tier 1 financial institutions. Passionate about technology, fitness, and an active blogger over at http://louiebacaj.com

Comments and Discussions

 
QuestionMessage Closed Pin
30-Apr-21 0:14
Bollywood Reflexon30-Apr-21 0:14 
QuestionMessage Closed Pin
26-Apr-21 21:10
fincher david26-Apr-21 21:10 
QuestionMessage Closed Pin
26-Aug-20 22:48
Member 1492417126-Aug-20 22:48 
QuestionNET Web API 2.0 Service with a Java Client Pin
aali zzim24-Dec-19 9:37
aali zzim24-Dec-19 9:37 
QuestionRunning code coverage for the .Net web API from the java client/TestNG Pin
Member 1290666529-Dec-16 7:58
Member 1290666529-Dec-16 7:58 
PraisePost json object Pin
Member 1235511026-Feb-16 20:56
Member 1235511026-Feb-16 20:56 
QuestionSource files Pin
avecchi197313-Oct-14 4:53
avecchi197313-Oct-14 4:53 
AnswerRe: Source files Pin
Louie Bacaj13-Oct-14 5:25
Louie Bacaj13-Oct-14 5:25 
GeneralRe: Source files Pin
avecchi197313-Oct-14 5:45
avecchi197313-Oct-14 5:45 
GeneralRe: Source files Pin
Louie Bacaj13-Oct-14 6:05
Louie Bacaj13-Oct-14 6:05 
GeneralMessage Closed Pin
7-Dec-20 21:14
Member 150151057-Dec-20 21:14 
GeneralRe: Source files Pin
Member 154603608-Dec-21 6:39
Member 154603608-Dec-21 6:39 
GeneralRe: Source files Pin
Member 1489661722-Jul-20 18:35
Member 1489661722-Jul-20 18:35 
QuestionDitto Pin
Member 111420139-Oct-14 10:50
Member 111420139-Oct-14 10:50 
AnswerRe: Ditto Pin
Louie Bacaj9-Oct-14 12:40
Louie Bacaj9-Oct-14 12:40 
GeneralMessage Closed Pin
7-Dec-20 21:13
Member 150151057-Dec-20 21:13 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.