DotVVM CRUD application with Cloud Firestore
Tags: dotnet, csharp, dotvvm, firebase
Published: 2020-03-05 23:57:59

In  [previous post](https://dev.to/dotvvm/dotvvm-crud-application-with-entity-framework-and-cosmos-db-4oah)  we demonstrated how to use DotVVM to create CRUD application with Azure Cosmos DB as your data store.

  

In this post we will demonstrate how to do the same with Cloud Firestore by Google.

To know more about DotVVM Framework you can check its  [official website](https://www.dotvvm.com/)

  

**What is Cloud Firestore?**

  
Cloud Firestore is a flexible, scalable database for mobile, web, and server development from Firebase and Google Cloud Platform. It keeps your data in sync across client apps through realtime listener and offers offline support for mobile and web apps.

  
You can know more about Cloud Firebase  [here](https://firebase.google.com/docs/firestore).

  

**Install DotVVM extension**

  

refer to [previous post](https://dev.to/dotvvm/dotvvm-crud-application-with-entity-framework-and-cosmos-db-4oah) and follow the steps.

  

To know more about the DotVVM extension visit its page on visual studio marketplace:[https://marketplace.visualstudio.com/items?itemName=TomasHerceg.DotVVM-VSExtension2019](https://marketplace.visualstudio.com/items?itemName=TomasHerceg.DotVVM-VSExtension2019)

  

Now you are ready to start coding with DotVVM framework. DotVVM extension installs DotVVM sample project which we will use to demonstrate how it is easy to connect to Cloud Firestore database from DotVVM application.

  
**Create Cloud Firestore Project**

To use cloud Firestore as your database you need to create a project on Firestore.

1.  Go to [https://console.firebase.google.com/](https://console.firebase.google.com/) and login with your google account or create new one.
2.  Click on Add Project
    
3.  Enter "**dotvvm**" as project name.
    
4.  In next step, Disable Google Analytics for this project. It is recommended to enable it for real project.
    
5.  Click on Create Project. it will take one or two mins to create your project. When it is ready click on continue.
    
    [![](https://1.bp.blogspot.com/-WV3ZiYPDAOg/Xgr5qckOqcI/AAAAAAAACiw/p2NuISo9axItYAdVnu7O9w8_CtaAQtDFwCLcBGAsYHQ/s200/project%2Bcreated.png)](https://1.bp.blogspot.com/-WV3ZiYPDAOg/Xgr5qckOqcI/AAAAAAAACiw/p2NuISo9axItYAdVnu7O9w8_CtaAQtDFwCLcBGAsYHQ/s1600/project%2Bcreated.png)
    
6.  From the left navigation pan, open database then click on Create database
    
    [![](https://1.bp.blogspot.com/-vgO5StdFNBU/Xgr7UQ6gWeI/AAAAAAAACjE/kIt1SZ3IyQ8PuzY-HtEuXEr0uyorXfEKgCLcBGAsYHQ/s320/database.png)](https://1.bp.blogspot.com/-vgO5StdFNBU/Xgr7UQ6gWeI/AAAAAAAACjE/kIt1SZ3IyQ8PuzY-HtEuXEr0uyorXfEKgCLcBGAsYHQ/s1600/database.png)
    
7.  In the popup window, select  **_Start in test mode_** then click next.
    
8.  Select the location of your database(you can keep the default selection) then Click Done.
    
9.  Congratulation, your Cloud Firestore database is created and ready.
    

  

To be able to connect to your Firestore database from your application(server) you need to set the GOOGLE_APPLICATION_CREDENTIALS environment variable to point to JSON service account key file.

  

To setup your service account, go to [https://cloud.google.com/docs/authentication/getting-started](https://cloud.google.com/docs/authentication/getting-started) and follow the instructions.

  

**DotVVM Web Application**

  

In [previous post](https://miroprocessordev.blogspot.com/2019/12/dotvvm-crud-application-with-entity.html) you can find the complete steps for creating DotVVM web application. In this post we focus on code changes required to connect to Firestore database.

-   Uninstall entity framework Sql Server related nuget package  
    `Microsoft.EntityFrameworkCore.SqlServer`  and  `Microsoft.EntityFrameworkCore`
    As we will connect to Cloud Firestore database not Sql Server database
-   Install  `Google.Cloud.Firestore`  nuget package. This package is required to run CRUD operations against your firestore database from your web application.
-   Open  _appsettings.json_  file and remove the connection string. keeping it will not harm but we need our code to be clean.
-   Delete  _DAL/StudentDbContext.cs_  file.
-   Open  _Startup.cs_  file and delete the following lines
    
    `services.AddEntityFrameworkSqlServer()
                    .AddDbContext<Studentdbcontext>(options =>
                    {
                        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
                    });`
    
-   Open  _DAL/Entities/Student.cs_  file and add the following using statement
    
    `using Google.Cloud.Firestore;`
    
-   Decorate the Student class with `[FirestoreData]`  attribute and each property with `[FirestoreProperty]`  attribute. Also change the type of `EnrollmentDate`  property to  Timestamp  instead of  `DateTime`. The complete code of Student class will be

`[FirestoreData]
 public class Student
 {
     [FirestoreProperty]
     public int Id { get; set; }
     [FirestoreProperty]
     public string FirstName { get; set; }
     [FirestoreProperty]
     public string LastName { get; set; }    
     [FirestoreProperty]
     public string About { get; set; }    
     [FirestoreProperty]
     public Timestamp EnrollmentDate { get; set; }
 }`
    
Those attributes are required and used to serialize/deserialize your entities from and to json objects. `Timestamp`  is the Firestore datatype used to represent date/time values.
-   Open  _Services/StudentService.cs_  file and add the following private properties to  `StudentService`  class
    
    `private const string project = "dotvvm";
    private const string collection = "students";`
    
    where  project  is the name of your Firestore project and collection  is the name of your database collection where you will insert/retrieve records
-   Replace the `GetAllStudentsAsync`  method with the following
    
    `public async Task<List<StudentListModel>> GetAllStudentsAsync()
    {
         var studentsList = new List<Student>();
         FirestoreDb db = FirestoreDb.Create(Project);
         Query allStudentsQuery = db.Collection(Collection);    
         QuerySnapshot allStudentsQuerySnapshot = await allStudentsQuery.GetSnapshotAsync();
         foreach (DocumentSnapshot documentSnapshot in allStudentsQuerySnapshot.Documents)
         {
             studentsList.Add(documentSnapshot.ConvertTo<Student>());
         }    
         return studentsList.Select(
                s => new StudentListModel
                    {
                        Id = s.Id,
                        FirstName = s.FirstName,
                        LastName = s.LastName
                    }
                ).ToList();
    }`
    
-   Replace the `GetStudentByIdAsync`  method with the following
    
    `public async Task<StudentListModel> GetStudentByIdAsync()
    {
         FirestoreDb db = FirestoreDb.Create(Project);
         Query docRef = db.Collection(Collection).WhereEqualTo("Id", studentId).Limit(1);
         QuerySnapshot snapshot = await docRef.GetSnapshotAsync();
         if (snapshot.Count > 0)
         {
              Student student = snapshot.ElementAt(0).ConvertTo<Student>();
              return new StudentDetailModel()
              {
                  About = student.About,
                  EnrollmentDate = student.EnrollmentDate.ToDateTime(),
                  FirstName = student.FirstName,
                  Id = student.Id,
                  LastName = student.LastName
              };
          }
          else
          {
               return null;
          }
    }`
    
-   Replace the  `UpdateStudentAsync` method with the following
    
    `public async Task UpdateStudentAsync(StudentDetailModel student)
    {
         FirestoreDb db = FirestoreDb.Create(Project);
         Query docRef = db.Collection(Collection).WhereEqualTo("Id", student.Id).Limit(1);
         QuerySnapshot snapshot = await docRef.GetSnapshotAsync();
         if (snapshot.Count > 0)
         {
               DocumentReference studentRef = db.Collection(Collection).Document(snapshot.ElementAt(0).Id);
               Dictionary<string, object> updates = new Dictionary<string, object>
               {
                   { nameof(student.About), student.About},
                   { nameof(student.EnrollmentDate), Timestamp.FromDateTime(student.EnrollmentDate.ToUniversalTime())},
                   { nameof(student.FirstName), student.FirstName},
                   { nameof(student.LastName), student.LastName}
               };
               await studentRef.UpdateAsync(updates);
         }
    }`
    
-   Replace the  `InsertStudentAsync`  method with the following
    
    `public async Task InsertStudentAsync(StudentDetailModel student)
    {
         var entity = new Student()
         {
              Id = new Random().Next(1, int.MaxValue),
              FirstName = student.FirstName,
              LastName = student.LastName,
              About = student.About,
              //create Timestamp from DateTime value
              EnrollmentDate = Timestamp.FromDateTime(student.EnrollmentDate.ToUniversalTime())
         };    
         FirestoreDb db = FirestoreDb.Create(Project);
         var Id = Guid.NewGuid().ToString();
         DocumentReference docRef = db.Collection(Collection).Document(Id);
         await docRef.SetAsync(entity);
    }`
    
-   Replace the  `DeleteStudentAsync`  method with the following
    
    `public async Task DeleteStudentAsync(int studentId)
    {
         FirestoreDb db = FirestoreDb.Create(Project);
         Query docRef = db.Collection(Collection).WhereEqualTo("Id", studentId).Limit(1);
         QuerySnapshot snapshot = await docRef.GetSnapshotAsync();
         if (snapshot.Count > 0)
         {
             DocumentReference studentRef = db.Collection(Collection).Document(snapshot.ElementAt(0).Id);
             await studentRef.DeleteAsync();
         }
    }`
    
-   Run your application and if there is no error you will see the following page in your browser  
    
    [![](https://2.bp.blogspot.com/-1Eh0uXFVoy0/XfpUxFkLovI/AAAAAAAACeo/Oq5IcD_t8No9Bh4BwRwYwxNdODqgFTwVgCLcBGAsYHQ/s400/home-page.png)](https://2.bp.blogspot.com/-1Eh0uXFVoy0/XfpUxFkLovI/AAAAAAAACeo/Oq5IcD_t8No9Bh4BwRwYwxNdODqgFTwVgCLcBGAsYHQ/s1600/home-page.png)
    
-   Click on New Item and fill the form then click Add
    
    [![](https://1.bp.blogspot.com/-cNa1jdHipZQ/Xg3QfXks5VI/AAAAAAAACjg/pkLHgcyPyJUCJnrANLVnIY67XDS1e8EqACLcBGAsYHQ/s320/Create.png)](https://1.bp.blogspot.com/-cNa1jdHipZQ/Xg3QfXks5VI/AAAAAAAACjg/pkLHgcyPyJUCJnrANLVnIY67XDS1e8EqACLcBGAsYHQ/s1600/Create.png)
    
      
    
-   Congratulation, you added your student to students Firestore collection
    
    [![](https://1.bp.blogspot.com/-d2NYpRR0zDg/Xg3QyBaVW3I/AAAAAAAACjo/mWoWfW46nO0oUEPn-tv3t_cYa5D8T1lsACLcBGAsYHQ/s320/List.png)](https://1.bp.blogspot.com/-d2NYpRR0zDg/Xg3QyBaVW3I/AAAAAAAACjo/mWoWfW46nO0oUEPn-tv3t_cYa5D8T1lsACLcBGAsYHQ/s1600/List.png)
    
      
    
-   Go to your Firestore database, it should look like
    
    [![](https://1.bp.blogspot.com/-3QXY5yUIzCg/Xg3RCFfkqII/AAAAAAAACjw/_ePZNiLXXTUB01XUZT82umzhiAYW21Z4gCLcBGAsYHQ/s320/record.png)](https://1.bp.blogspot.com/-3QXY5yUIzCg/Xg3RCFfkqII/AAAAAAAACjw/_ePZNiLXXTUB01XUZT82umzhiAYW21Z4gCLcBGAsYHQ/s1600/record.png)
    
      
    
    notice that, Firestore is created a student collection and inserted your student entity as  `JSON`  document and also notice how it represents the  `EnrollmentDate` value as timestamp.

  

**Summary**

In this article we demonstrated how to create a sample DotVVM web application, Cloud Firestore database and perform CRUD operations as we used to do with SQL Server database or any other relational database. We have done changes in the sample project code to twist it from using Entity Framework Code First approach (SQL Server) to use Google Cloud FireStore .Net SDK.

  

You can find the complete source code on  [github](https://github.com/miroprocessor/dotvvm-firestore)