diff --git a/docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/POST.md b/docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/POST.md new file mode 100644 index 0000000000..66786ff740 --- /dev/null +++ b/docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/POST.md @@ -0,0 +1,195 @@ +# gRPC - JSON Transcoding + +In this article, I'll show you one of the new features that came with .NET 7: **JSON Transcoding**. + +> I've created a community article to highlight some interesting features (briefly) that are now available with the release of .NET 7. You can check from [here](https://community.abp.io/posts/whats-new-with-.net-7-tlq2g43w). + +## What is gRPC? What are the pros and cons? + +[gRPC](https://grpc.io/) is a high-performance RPC framework and uses HTTP/2 and Protobuf (protocol buffers). + +### gRPC - Advantages + +* **Lightweight messages**: Payload is much smaller than JSON. +* **High performance**: Much faster than REST and JSON communication. +* **Faster serialization/deserialization**: Protobufs are binary encoded. This means that it will use fewer CPU cycles to serialize/deserialize the messages. + +### gRPC - Disadvantages + +* **Lack of maturity** +* **Limited browser support - hard to test (in a way)**: Since gRPC relies on HTTP/2, you can’t call a gRPC service from a web browser directly. This is where JSON Transcoding comes into play. + +## What is JSON Transcoding? + +Despite the benefits that gRPC provides, REST APIs have an important place in modern web applications. We can easily create, expose and test them. + +On the other hand, gRPC services are not easy to test as mentioned above. We can’t access a gRPC service yet through the browser since browsers don’t understand binary protocols. We need to use some tools to access endpoints, such as [gRPCurl](https://github.com/fullstorydev/grpcurl). + +![](grpcurl.png) + +JSON Transcoding is an extension for ASP.NET Core that creates RESTful JSON APIs for gRPC services and overcomes this problem. You can see an illustration down below: + +![](json-transcoding.png) + +By using JSON Transcoding, we can expose our gRPC services and access them via HTTP call. Let's see it in action. + +## Creating & Exposing gRPC Services in ABP Based Applications + +### Creating the Application + +Create an empty folder, open a command-line terminal and type the following command in the terminal window to create a new ABP solution using the ABP CLI: + +```csharp +abp new BookStore -t app --ui angular --preview +``` + +I've created an application with the Angular UI, but the UI is not important for this tutorial, you can select your favorite UI. + +> **Note:** Your application should be ABP 7.0+. + +### Configuring gRPC & JSON Transcoding + +In this solution, `*.HttpApi.Host` is the project that configures and runs the server-side application. So, we will make changes in that project. + +First, we need to add two packages ([Grpc.AspNetCore](https://www.nuget.org/packages/Grpc.AspNetCore) and [Microsoft.AspNetCore.Grpc.JsonTranscoding](https://www.nuget.org/packages/Microsoft.AspNetCore.Grpc.JsonTranscoding)) into this project with the following commands: + +```bash +dotnet add package Grpc.AspNetCore +dotnet add package Microsoft.AspNetCore.Grpc.JsonTranscoding +``` + +Then, add [*google/api/http.proto*](https://github.com/dotnet/aspnetcore/blob/main/src/Grpc/JsonTranscoding/test/testassets/Sandbox/google/api/http.proto) and [*google/api/annotations.proto*](https://github.com/dotnet/aspnetcore/blob/main/src/Grpc/JsonTranscoding/test/testassets/Sandbox/google/api/annotations.proto) files under to the **google/api** folder. These files are required for JSON Transcoding and contain all related stuff related to that. + +![](google-api-folders.png) + +Then, open the module class (`BookStoreHttpApiHostModule.cs`) and update it as below: + +```csharp +public class BookStoreHttpApiHostModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + // other configurations... + + context.Services.AddGrpc().AddJsonTranscoding(); //add this line + + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var app = context.GetApplicationBuilder(); + + // other middlewares... + + app.UseConfiguredEndpoints(builder => + { + builder.MapGrpcService(); //add this line + }); + } +} +``` + +* Here, we've registered the related gRPC services into the DI container by calling the `AddGdpr()` and `AddJsonTranscoding()` methods. +* Also, we've defined our gRPC service: `BookAppService`. We have not created this service yet and will create it in the next section. + +So far, we've added the required packages to our project and made the related configurations. Now we can start to create our gRPC services. + +### Implementing gRPC Services + +Create a **Protos** folder and define a `bookstore.proto` file in it. Then fill it with the below content: + +```proto +syntax = "proto3"; + +import "google/api/annotations.proto"; //import related Google APIs + +option csharp_namespace = "BookStore"; + +message Book { + string title = 1; + string author = 2; + int32 page_count = 3; + optional string language = 4; +} + +message GetBookListRequest {} + +message GetBookListResponse { repeated Book books = 1; } + +service BookApp { + rpc GetBookList(GetBookListRequest) returns (GetBookListResponse) { + option (google.api.http) = { + get: "/v1/book-store/books" //expose from this url + }; + } +} +``` + +* Here, we've defined the `bookstore.proto` file. You can thought this file as a contract that the server and client agreed on. +* An important point here, we've imported the `google/api/annotations.proto` (we added this file under the **google/api** folder in the previous section) and by using the `google.api.http` we are exposing this gRPC service (with the specified URL). +* So, when we run the application we can send a request to that endpoint and see the result. +* Thanks to JSON Transcoding, we don't need to use any other tools to test our gRPC services anymore! + +Let's mark the `bookstore.proto` file as our protobuf file in the `*.HttpApi.Host.csproj` file: + +```xml + + + +``` + +For the final step, we just need to define a service that corresponds to the service that we defined in the `bookstore.proto` file. Voilà 🎉! + +So, create a new class named `BookAppService` under the `Services` folder: + +```csharp +using System.Threading.Tasks; +using Grpc.Core; + +namespace BookStore.Services; + +public class BookAppService : BookApp.BookAppBase +{ + //notice: we did not create GetBookListResponse and GetBookListRequest classes + //Grpc.AspNetCore package did behalf of us + public override Task GetBookList(GetBookListRequest request, ServerCallContext context) + { + var response = new GetBookListResponse(); + response.Books.Add(new Book + { + Title = "The Hitchhiker's Guide to the Galaxy", + Author = "Douglas Adams", + PageCount = 42 + }); + response.Books.Add(new Book + { + Title = "The Lord of the Rings", + Author = "J.R.R. Tolkien", + PageCount = 1234 + }); + + return Task.FromResult(response); + } +} +``` + +* Here, as you notice we've inherited our service from the `BookAppBase` class. You might wonder where it came from. +* **Grpc.AspNetCore** package creates auto-generated classes from our protobuf file (`bookstore.proto`). We just need to inherit from `BookAppService` class, override the `GetBookList` method and implement it. That's it. +* Also, notice we did not create the other classes such as `Book`, `GetBookListRequest` and `GetBookListResponse`. These are all auto-generated from our protobuf file. + +We created a gRPC service and now let's run our application (before running the application run the `*DbMigrator` project to create the database and seed the initial data) and see it in action. + +![](grpc-result.png) + +## Conclusion + +In this article, I've briefly introduced the JSON Transcoding feature that shipped with .NET 7 and show it in an ABP Based application. + +> See the [gRPC JSON transcoding in ASP.NET Core gRPC apps](https://learn.microsoft.com/en-us/aspnet/core/grpc/json-transcoding?view=aspnetcore-7.0) documentation for more information. + +## References + +* https://devblogs.microsoft.com/dotnet/announcing-grpc-json-transcoding-for-dotnet/ +* https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-7.0?view=aspnetcore-7.0#json-transcoding +* https://learn.microsoft.com/en-us/aspnet/core/grpc/json-transcoding?view=aspnetcore-7.0 +* https://sahansera.dev/building-grpc-server-dotnet/ diff --git a/docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/google-api-folders.png b/docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/google-api-folders.png new file mode 100644 index 0000000000..7719dc3915 Binary files /dev/null and b/docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/google-api-folders.png differ diff --git a/docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/grpc-result.png b/docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/grpc-result.png new file mode 100644 index 0000000000..e43d06e745 Binary files /dev/null and b/docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/grpc-result.png differ diff --git a/docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/grpcurl.png b/docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/grpcurl.png new file mode 100644 index 0000000000..053629d04d Binary files /dev/null and b/docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/grpcurl.png differ diff --git a/docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/json-transcoding.png b/docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/json-transcoding.png new file mode 100644 index 0000000000..a80c7e3bb1 Binary files /dev/null and b/docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/json-transcoding.png differ