Here we will see how to create a wrapper around Firebase REST API with C#, so .Net devlopers can consume it quickly.

Section 1 Create App in Firebase Console

Log into your Firebase account and click on "GO TO CONSOLE" to access the console.

C#

Click on "Add Project" to add a new Firebase project.

C#

Give "Project Name" of your choice, then select your Country/Region and hit "CREATE PROJECT".

C#

Now, you will be navigated to your newly created App Dashboard with all the Firebase features listed. Click on "Database" from the left pane.

C#

You can see your service plan as Spark which is Free. All the data stored is represented as JSON tree. You have database URL along with the root of JSON tree, which is null as of now. This database URL will be used to make HTTP request later in the article.

Section 2 Explore Firebase REST API with Postman

Before making wrapper, let’s get comfortable with Firebase REST API with Postman. You can get postman from here (https://www.getpostman.com/apps).

Firebase read/write access is secured by default as you can see in RULES.

C#

For the sake of simplicity in making HTTP requests, we will remove authentication for this article. In upcoming articles, we will continue with authentication.

Make auth==null; and hit "PUBLISH" to remove authentication.

C#

If you are already familiar with Firebase REST API, you can directly jump to Section 3.

Writing Data with PUT

I have some data about a team and its members as follows. We are writing this data to root node of our database JSON tree.

  1. {
  2. "Team-Awesome": {
  3. "Members": {
  4. "M1": {
  5. "City": "Hyderabad",
  6. "Name": "Ashish"
  7. },
  8. "M2": {
  9. "City": "Cyberabad",
  10. "Name": "Vivek"
  11. },
  12. "M3": {
  13. "City": "Secunderabad",
  14. "Name": "Pradeep"
  15. }
  16. }
  17. }
  18. }

In Postman window, set method as PUT; in URL, enter your database URL appended with .json as we are writing to root node.
The .json suffix is always required if we are making REST calls. In Body, select raw and paste your JSON data there, hit "Send" now to make the request.

C#

You can see response code "200 OK" in Postman instead of 201 Created, but this is how Firebase returns it. Every request will return "200 OK" if successful, irrespective of the Request method.

C#

Created data will immediately be reflected to your app console. You can verify it.

C#

Reading Data with GET

To read data, we can give path to specific node which we wish to read. Here, I just want the details of Member M1 so I have given specific path in URL. Set method as GET and hit "Send" to retrieve the data.

C#

It would return the details of a specific member.

C#

Pushing Data with POST

In Firebase, POST pushes data to the specific node with auto-generated key; it never replaces existing data.

Here, we are adding scores for all team members, so our node is Scores here which is not already available in JSON tree. Firebase will automatically create it.

C#

You can see in console Scores node is created and data is added along with random keys.

C#

Updating Data with PATCH

To update data in a node we have to use PATCH, it can be used to add new fields also. Here we will update city of a member.

C#

You can observe in console whether value is updated.

C#

Removing Data with DELETE

To remove a resource DELETE is used. Let’s delete Member M3.

C#

Member M3 is removed, can be seen in console.

C#

Section 3 Building C# wrapper

Add new project of type Class Library with name FirebaseNet, or name of your choice.

I have taken .Net Standard here for broader compatibility, you can take .Net framework class library if it’s not available.

C#

Create folder Database and add 4 classes as follows.

  1. FirebaseDB.cs
  2. FirebaseRequest.cs
  3. FirebaseResponse.cs
  4. UtilityHelper.cs

Let’s look into each file one by one.

FirebaseDB.cs

  1. namespace FirebaseNet.Database
  2. {
  3. using System;
  4. using System.Net.Http;
  5. /// <summary>
  6. /// FirebasDB Class is reference of a Firebase Database
  7. /// </summary>
  8. public class FirebaseDB
  9. {
  10. /// <summary>
  11. /// Initializes a new instance of the <see cref="FirebaseDB"/> class with base url of Firebase Database
  12. /// </summary>
  13. /// <param name="baseURL">Firebase Database URL</param>
  14. public FirebaseDB(string baseURL)
  15. {
  16. this.RootNode = baseURL;
  17. }
  18. /// <summary>
  19. /// Gets or sets Represents current full path of a Firebase Database resource
  20. /// </summary>
  21. private string RootNode { get; set; }
  22. /// <summary>
  23. /// Adds more node to base URL
  24. /// </summary>
  25. /// <param name="node">Single node of Firebase DB</param>
  26. /// <returns>Instance of FirebaseDB</returns>
  27. public FirebaseDB Node(string node)
  28. {
  29. if (node.Contains("/"))
  30. {
  31. throw new FormatException("Node must not contain '/', use NodePath instead.");
  32. }
  33. return new FirebaseDB(this.RootNode + '/' + node);
  34. }
  35. /// <summary>
  36. /// Adds more nodes to base URL
  37. /// </summary>
  38. /// <param name="nodePath">Nodepath of Firebase DB</param>
  39. /// <returns>Instance of FirebaseDB</returns>
  40. public FirebaseDB NodePath(string nodePath)
  41. {
  42. return new FirebaseDB(this.RootNode + '/' + nodePath);
  43. }
  44. /// <summary>
  45. /// Make Get request
  46. /// </summary>
  47. /// <returns>Firebase Response</returns>
  48. public FirebaseResponse Get()
  49. {
  50. return new FirebaseRequest(HttpMethod.Get, this.RootNode).Execute();
  51. }
  52. /// <summary>
  53. /// Make Put request
  54. /// </summary>
  55. /// <param name="jsonData">JSON string to PUT</param>
  56. /// <returns>Firebase Response</returns>
  57. public FirebaseResponse Put(string jsonData)
  58. {
  59. return new FirebaseRequest(HttpMethod.Put, this.RootNode, jsonData).Execute();
  60. }
  61. /// <summary>
  62. /// Make Post request
  63. /// </summary>
  64. /// <param name="jsonData">JSON string to POST</param>
  65. /// <returns>Firebase Response</returns>
  66. public FirebaseResponse Post(string jsonData)
  67. {
  68. return new FirebaseRequest(HttpMethod.Post, this.RootNode, jsonData).Execute();
  69. }
  70. /// <summary>
  71. /// Make Patch request
  72. /// </summary>
  73. /// <param name="jsonData">JSON sting to PATCH</param>
  74. /// <returns>Firebase Response</returns>
  75. public FirebaseResponse Patch(string jsonData)
  76. {
  77. return new FirebaseRequest(new HttpMethod("PATCH"), this.RootNode, jsonData).Execute();
  78. }
  79. /// <summary>
  80. /// Make Delete request
  81. /// </summary>
  82. /// <returns>Firebase Response</returns>
  83. public FirebaseResponse Delete()
  84. {
  85. return new FirebaseRequest(HttpMethod.Delete, this.RootNode).Execute();
  86. }
  87. /// <summary>
  88. /// To String
  89. /// </summary>
  90. /// <returns>Current resource URL as string</returns>
  91. public override string ToString()
  92. {
  93. return this.RootNode;
  94. }
  95. }
  96. }

FirebaseRequest.cs

  1. namespace FirebaseNet.Database
  2. {
  3. using System;
  4. using System.Net.Http;
  5. /// <summary>
  6. /// Firebase Request
  7. /// </summary>
  8. class FirebaseRequest
  9. {
  10. /// <summary>
  11. /// Suffix to be added in each resource URI
  12. /// </summary>
  13. private const string JSON_SUFFIX = ".json";
  14. /// <summary>
  15. /// Initializes a new instance of the <see cref="FirebaseRequest"/> class
  16. /// </summary>
  17. /// <param name="method">HTTP Method</param>
  18. /// <param name="uri">URI of resource</param>
  19. /// <param name="jsonString">JSON string</param>
  20. public FirebaseRequest(HttpMethod method, string uri, string jsonString = null)
  21. {
  22. this.Method = method;
  23. this.JSON = jsonString;
  24. if (uri.Replace("/", string.Empty).EndsWith("firebaseio.com"))
  25. {
  26. this.Uri = uri + '/' + JSON_SUFFIX;
  27. }
  28. else
  29. {
  30. this.Uri = uri + JSON_SUFFIX;
  31. }
  32. }
  33. /// <summary>
  34. /// Gets or sets HTTP Method
  35. /// </summary>
  36. private HttpMethod Method { get; set; }
  37. /// <summary>
  38. /// Gets or sets JSON string
  39. /// </summary>
  40. private string JSON { get; set; }
  41. /// <summary>
  42. /// Gets or sets URI
  43. /// </summary>
  44. private string Uri { get; set; }
  45. /// <summary>
  46. /// Executes a HTTP requests
  47. /// </summary>
  48. /// <returns>Firebase Response</returns>
  49. public FirebaseResponse Execute()
  50. {
  51. Uri requestURI;
  52. if (UtilityHelper.ValidateURI(this.Uri))
  53. {
  54. requestURI = new Uri(this.Uri);
  55. }
  56. else
  57. {
  58. return new FirebaseResponse(false, "Proided Firebase path is not a valid HTTP/S URL");
  59. }
  60. string json = null;
  61. if (this.JSON != null)
  62. {
  63. if (!UtilityHelper.TryParseJSON(this.JSON, out json))
  64. {
  65. return new FirebaseResponse(false, string.Format("Invalid JSON : {0}", json));
  66. }
  67. }
  68. var response = UtilityHelper.RequestHelper(this.Method, requestURI, json);
  69. response.Wait();
  70. var result = response.Result;
  71. var firebaseResponse = new FirebaseResponse()
  72. {
  73. HttpResponse = result,
  74. ErrorMessage = result.StatusCode.ToString() + " : " + result.ReasonPhrase,
  75. Success = response.Result.IsSuccessStatusCode
  76. };
  77. if (this.Method.Equals(HttpMethod.Get))
  78. {
  79. var content = result.Content.ReadAsStringAsync();
  80. content.Wait();
  81. firebaseResponse.JSONContent = content.Result;
  82. }
  83. return firebaseResponse;
  84. }
  85. }
  86. }

FirebaseResponse.cs

  1. namespace FirebaseNet.Database
  2. {
  3. using System.Net.Http;
  4. /// <summary>
  5. /// Firebase Response
  6. /// </summary>
  7. public class FirebaseResponse
  8. {
  9. /// <summary>
  10. /// Initializes a new instance of the <see cref="FirebaseResponse"/> class
  11. /// </summary>
  12. public FirebaseResponse()
  13. {
  14. }
  15. /// <summary>
  16. /// Initializes a new instance of the <see cref="FirebaseResponse"/> class
  17. /// </summary>
  18. /// <param name="success">If Success</param>
  19. /// <param name="errorMessage">Error Message</param>
  20. /// <param name="httpResponse">HTTP Response</param>
  21. /// <param name="jsonContent">JSON Content</param>
  22. public FirebaseResponse(bool success, string errorMessage, HttpResponseMessage httpResponse = null, string jsonContent = null)
  23. {
  24. this.Success = success;
  25. this.JSONContent = jsonContent;
  26. this.ErrorMessage = errorMessage;
  27. this.HttpResponse = httpResponse;
  28. }
  29. /// <summary>
  30. /// Gets or sets Boolean status of Success
  31. /// </summary>
  32. public bool Success { get; set; }
  33. /// <summary>
  34. /// Gets or sets JSON content returned by the Request
  35. /// </summary>
  36. public string JSONContent { get; set; }
  37. /// <summary>
  38. /// Gets or sets Error Message if Any
  39. /// </summary>
  40. public string ErrorMessage { get; set; }
  41. /// <summary>
  42. /// Gets or sets full Http Response
  43. /// </summary>
  44. public HttpResponseMessage HttpResponse { get; set; }
  45. }
  46. }

FirebaseResponse represents output of API calls against FirebaseDB. It contains 4 public properties as follows.

  1. Success
  2. JSONContent
  3. ErrorMessage
  4. HttpResponse

UtilityHelper.cs

  1. namespace FirebaseNet.Database
  2. {
  3. using System;
  4. using System.Net.Http;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using Newtonsoft.Json.Linq;
  8. /// <summary>
  9. /// Utility Helper Class
  10. /// </summary>
  11. class UtilityHelper
  12. {
  13. /// <summary>
  14. /// User Agent Header in HTTP Request
  15. /// </summary>
  16. private const string USER_AGENT = "firebase-net/1.0";
  17. /// <summary>
  18. /// Validates a URI
  19. /// </summary>
  20. /// <param name="url">URI as string</param>
  21. /// <returns>True if valid</returns>
  22. public static bool ValidateURI(string url)
  23. {
  24. Uri locurl;
  25. if (System.Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out locurl))
  26. {
  27. if (
  28. !(locurl.IsAbsoluteUri &&
  29. (locurl.Scheme == "http" || locurl.Scheme == "https")) ||
  30. !locurl.IsAbsoluteUri)
  31. {
  32. return false;
  33. }
  34. }
  35. else
  36. {
  37. return false;
  38. }
  39. return true;
  40. }
  41. /// <summary>
  42. /// Validates JSON string
  43. /// </summary>
  44. /// <param name="inJSON">JSON to be validatedd</param>
  45. /// <param name="output">Valid JSON or Error Message</param>
  46. /// <returns>True if valid</returns>
  47. public static bool TryParseJSON(string inJSON, out string output)
  48. {
  49. try
  50. {
  51. JToken parsedJSON = JToken.Parse(inJSON);
  52. output = parsedJSON.ToString();
  53. return true;
  54. }
  55. catch (Exception ex)
  56. {
  57. output = ex.Message;
  58. return false;
  59. }
  60. }
  61. /// <summary>
  62. /// Makes Asynchronus HTTP requests
  63. /// </summary>
  64. /// <param name="method">HTTP method</param>
  65. /// <param name="uri">URI of resource</param>
  66. /// <param name="json">JSON string</param>
  67. /// <returns>HTTP Responce as Task</returns>
  68. public static Task<HttpResponseMessage> RequestHelper(HttpMethod method, Uri uri, string json = null)
  69. {
  70. var client = new HttpClient();
  71. var msg = new HttpRequestMessage(method, uri);
  72. msg.Headers.Add("user-agent", USER_AGENT);
  73. if (json != null)
  74. {
  75. msg.Content = new StringContent(
  76. json,
  77. UnicodeEncoding.UTF8,
  78. "application/json");
  79. }
  80. return client.SendAsync(msg);
  81. }
  82. }
  83. }

Section 4 Library in Action

Let’s consume our newly created library and see how it works. Create New Console App and give name of your choice.

C#

Now update your Program.cs with following code.

Program.cs

  1. namespace Examples.NetCore
  2. {
  3. using FirebaseNet.Database;
  4. using static System.Console;
  5. /// <summary>
  6. /// Examples
  7. /// </summary>
  8. public class Program
  9. {
  10. /// <summary>
  11. /// Main Method
  12. /// </summary>
  13. public static void Main()
  14. {
  15. // Instanciating with base URL
  16. FirebaseDB firebaseDB = new FirebaseDB("https://c-sharpcorner-2d7ae.firebaseio.com");
  17. // Referring to Node with name "Teams"
  18. FirebaseDB firebaseDBTeams = firebaseDB.Node("Teams");
  19. var data = @"{
  20. 'Team-Awesome': {
  21. 'Members': {
  22. 'M1': {
  23. 'City': 'Hyderabad',
  24. 'Name': 'Ashish'
  25. },
  26. 'M2': {
  27. 'City': 'Cyberabad',
  28. 'Name': 'Vivek'
  29. },
  30. 'M3': {
  31. 'City': 'Secunderabad',
  32. 'Name': 'Pradeep'
  33. }
  34. }
  35. }
  36. }";
  37. WriteLine("GET Request");
  38. FirebaseResponse getResponse = firebaseDBTeams.Get();
  39. WriteLine(getResponse.Success);
  40. if(getResponse.Success)
  41. WriteLine(getResponse.JSONContent);
  42. WriteLine();
  43. WriteLine("PUT Request");
  44. FirebaseResponse putResponse = firebaseDBTeams.Put(data);
  45. WriteLine(putResponse.Success);
  46. WriteLine();
  47. WriteLine("POST Request");
  48. FirebaseResponse postResponse = firebaseDBTeams.Post(data);
  49. WriteLine(postResponse.Success);
  50. WriteLine();
  51. WriteLine("PATCH Request");
  52. FirebaseResponse patchResponse = firebaseDBTeams
  53. // Use of NodePath to refer path lnager than a single Node
  54. .NodePath("Team-Awesome/Members/M1")
  55. .Patch("{\"Designation\":\"CRM Consultant\"}");
  56. WriteLine(patchResponse.Success);
  57. WriteLine();
  58. WriteLine("DELETE Request");
  59. FirebaseResponse deleteResponse = firebaseDBTeams.Delete();
  60. WriteLine(deleteResponse.Success);
  61. WriteLine();
  62. WriteLine(firebaseDBTeams.ToString());
  63. ReadLine();
  64. }
  65. }
  66. }

Execution

C#

I will keep adding new features to this library, you can track in further articles and repository. You can also contribute here.

Current stage of code can be found here.