{"id":1284,"date":"2021-02-10T15:13:02","date_gmt":"2021-02-10T15:13:02","guid":{"rendered":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/?p=1284"},"modified":"2021-02-10T15:18:54","modified_gmt":"2021-02-10T15:18:54","slug":"wcf-alternatives-part-3","status":"publish","type":"post","link":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/","title":{"rendered":"WCF Alternatives (Part 3) \u2013 Instructions for the Migration from WCF to gRPC"},"content":{"rendered":"\n<p>This blog post in the series on <a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/topic\/wcf-alternatives\/\">alternatives for the Windows Communication Foundation (WCF)<\/a> describes the particularities and challenges regarding a WCF migration in preparation of the subsequent porting of the application to .NET Core.<\/p>\n\n\n\n<p>The previous post described ASP.NET Core Web API as an alternative, and this article will address another option: gRPC. Again, we will describe a possible step-by-step procedure for the migration from WCF to gRPC.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Migration procedure<\/strong><\/h2>\n\n\n\n<p>Usually, a separate WCF project is in the solution. As a direct conversion is not possible, this project can remain unchanged in the solution for the time being.<\/p>\n\n\n\n<p>You should first create a new class library project for shared objects between the server and the client. Then copy the ServiceContract interfaces and the DataContract classes from the WCF project to this project, and remove the WCF-specific attributes such as \u201cServiceContract\u201d, \u201cOperationContract\u201d, \u201cDataContract\u201d, \u201cDataMember\u201d, etc.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Client project<\/strong><\/h3>\n\n\n\n<p>First of all, remove the WCF Service reference in the project that consumes the WCF Service. The WCF-specific attributes such as \u201cCallbackBehavior\u201d and the like can be removed as well.<\/p>\n\n\n\n<p>Add a new reference to the previously created class library project for the shared objects. Next, you can create an empty implementation of the ServiceContract interface, which is now located in the class library project, in the client project. Now change the \u201cold\u201d initialization of the WCF Service to the, as-yet empty, implementation of the ServiceContract.<\/p>\n\n\n\n<p>Lastly, you have to change the usings for the previously used DataContract classes from the WCF Service to the new class library project. It should now be possible to compile the client project again. In order to be able to start the project again, you have to remove the &lt;system.serviceModel&gt; element from the *.config.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Creating the interface description with Protocol Buffers<\/strong><\/h3>\n\n\n\n<p>With gRPC, the interface is described in *.proto files using the Protocol Buffer language. The *.proto file should preferably be added to the newly created class library project. In order to be able to generate server and client classes from it later, you also have to add the \u201cGoogle.Protobuf\u201d, \u201cGrpc.Core\u201d and \u201cGrpc.Tools\u201d NuGet packages.<\/p>\n\n\n\n<p>Once the *.proto file has been created, it has to be announced in the \u201cItemGroup\u201d node in the *.csproj file by means of the following line.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;Project Sdk=\"Microsoft.NET.Sdk\"&gt;\n \n  &lt;ItemGroup&gt;\n    &lt;Protobuf Include=\"ProtoTimeService.proto\" GrpcServices=\"Both\" \/&gt;\n \n  &lt;\/ItemGroup&gt;\n \n&lt;\/Project&gt;<\/pre>\n\n\n\n<p><em>Definition of *.proto in the *.config file<\/em><\/p>\n\n\n\n<hr class=\"wp-block-separator\" \/>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Structure of the *.proto file<\/strong><\/h3>\n\n\n\n<p>Below is an example of how to transfer a WCF Service description into a *.proto file.<\/p>\n\n\n\n<p>The [ServiceContract] attributes become \u201cService\u201d, and [OperationContract] become \u201crpc\u201d calls. The classes labeled [DataContract] become \u201cmessage\u201d objects.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">[ServiceContract]\npublic interface IDataInputService\n{\n    [OperationContract]\n    int CreateUser(User user);\n \n    [OperationContract]\n    int Login(User user);\n \n    [OperationContract]\n    List&lt;Time&gt; GetTimes(int userId);\n \n    [OperationContract]\n    void AddTime(Time time, int userId);\n \n    [OperationContract]\n    List&lt;string&gt; Projects();\n}\n \n[DataContract]\npublic class User\n{\n    [DataMember]\n    public string Name { get; set; }\n \n    [DataMember]\n    public string Passwort { get; set; }\n}\n \n[DataContract]\npublic class Time\n{\n    [DataMember]\n    public DateTime Start { get; set; }\n \n    [DataMember]\n    public DateTime End { get; set; }\n \n    [DataMember]\n    public string Project { get; set; }\n \n    [DataMember]\n    public int uId { get; set; }\n \n    [DataMember]\n    public int Id { get; set; }\n}<\/pre>\n\n\n\n<p><em>Example of a WCF ServiceContract and DataContract to be migrated<\/em><\/p>\n\n\n\n<hr class=\"wp-block-separator\" \/>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">syntax = \"proto3\";\n \nimport \"google\/protobuf\/timestamp.proto\";\nimport \"google\/protobuf\/Empty.proto\";\n \noption csharp_namespace = \"DataInputt.TimeService.Api\";\n \nservice DataInputService {\n    rpc CreateUser (UserDto) returns (UserResponse) {}\n    rpc Login (UserDto) returns (UserResponse) {}\n    rpc GetTimes (GetTimesRequest) returns (TimeCollection) {}\n    rpc AddTime (AddTimeRequest) returns (google.protobuf.Empty) {}\n    rpc Projects (google.protobuf.Empty) returns (ProjectCollection) {}\n}\n \n \nmessage UserDto {\n    string name = 1;\n    string passwort = 2;\n}\n \nmessage TimeDto {\n    google.protobuf.Timestamp start = 1;\n    google.protobuf.Timestamp end = 2;\n    string project = 3;\n    int32 uid = 4;\n    int32 id = 5;\n}\n \nmessage UserResponse {\n    int32 id = 1;\n}\n \nmessage GetTimesRequest {\n    int32 userId = 1;\n}\n \nmessage TimeCollection {\n    repeated TimeDto times = 1;\n}\n \nmessage AddTimeRequest {\n    TimeDto time = 1;\n    int32 userId = 2;\n}\n \nmessage ProjectCollection {\n    repeated string projects = 1;\n}<\/pre>\n\n\n\n<p><em>Example of the created gRPC *.proto file<\/em><\/p>\n\n\n\n<hr class=\"wp-block-separator\" \/>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>When you create the *.proto file, you should observe the following points.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Indicate the namespace<\/strong><\/h3>\n\n\n\n<p>To ensure that the generated server and client implementation is given the correct namespace, it should be indicated in the *.proto file.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Definition of input parameters \/ return values<\/strong><\/h3>\n\n\n\n<p>gRPC interfaces only allow for calls with a single parameter. If you work with several input parameters in the WCF Service, they have to be combined into a new message object.<\/p>\n\n\n\n<p>Every call of a gRPC interface needs a return value as well. If there were void methods in the WCF Service, they have to return the specific \u201cgoogle.protobuf.Empty\u201d type in gRPC now.<\/p>\n\n\n\n<p>Furthermore, using a single primitive data type (int, bool, string) for the input and return is not allowed. If only an <em>int<\/em> or <em>string <\/em>is to be used for the return value, another message object has to be created for this purpose.<\/p>\n\n\n\n<p>If methods call up one another in the WCF Service, this was very simple if a primitive data type was used. If you want this to be possible in the gRPC interface as well, you have to ensure that the respective methods use the same message objects. This way, you can avoid unnecessary mapping.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Names of the message objects<\/strong><\/h3>\n\n\n\n<p>When you name the message objects, you should not use the exact same names as the DataContract classes of the WCF Service. This is important because some of the C# classes that will later be generated from the definition use different data types and need to be mapped before they can be used. In order to distinguish them more clearly from the DataContract classes, it is advisable to use distinctive names.<\/p>\n\n\n\n<p>Furthermore, the properties within the message objects have to be numbered sequentially.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Data types in message objects<\/strong><\/h3>\n\n\n\n<p>C# classes are automatically generated from the message objects of the *.proto file. You should be aware that the standard C# data types are not always used for the generation.<\/p>\n\n\n\n<p>For example, the google.protobuf.Timestamp type specified in the *.proto file becomes the Google.Protobuf.WellKnownTypes.Timestamp type in the C# class and has to be converted into a DateTime first whenever it is to be used.<\/p>\n\n\n\n<p>If the *.proto file contains \u201crepeated\u201d, this does not become a List&lt;T&gt;, but a Google.Protobuf.Collections.RepeatedField&lt;T&gt;, which needs to be mapped accordingly as well.<\/p>\n\n\n\n<p>Other types such as Dictionary&lt;K, V&gt; also have different types in the *.proto file and the C# class generated later. The C# type \u201cdecimal\u201d is currently not supported by the *.proto file at all because of insufficient rounding accuracy. As a workaround, creating your own decimal message object that specifies the pre-decimal and the decimal places as separate int values is recommended.<\/p>\n\n\n\n<div style=\"height:29px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Creating the gRPC server project<\/strong><\/h3>\n\n\n\n<p>The gRPC server project can be created as a simple console application, and it should contain a reference to the previously newly created class library project with the *.proto file.<\/p>\n\n\n\n<p>To start the server, you only need a few lines of code:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">static void Main(string[] args)\n{\n    const int port = 9000;\n    const string host = \"0.0.0.0\";\n\n    Grpc.Core.Server server = new Grpc.Core.Server\n    {\n        Services = { DataInputt.TimeService.Api.TimeService.BindService(new TimeService()) },\n        Ports = { new Grpc.Core.ServerPort(host, port, Grpc.Core.ServerCredentials.Insecure) }\n    };\n    server.Start();\n\n    Console.WriteLine($\"Starting server {host}:{port}\");\n    Console.WriteLine(\"Press any key to stop...\");\n    Console.ReadKey();\n}<\/pre>\n\n\n\n<p><em>Example for starting a gRPC server<\/em><\/p>\n\n\n\n<hr class=\"wp-block-separator\" \/>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>You only have to define the host and port and assign an implementation to the service generated with the *.proto file in the class library project. The implementation should be located in the gRPC server project.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Implementation of the gRPC service<\/strong><\/h3>\n\n\n\n<p>The gRPC service is implemented by way of the inheritance of the ServiceBase generated with the *.proto file in the class library project. The individual service calls can then be implemented by means of an override.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public class TimeService : DataInputt.TimeService.Api.TimeService.TimeServiceBase\n{\n    public override Task&lt;UserResponse&gt; CreateUser(UserDto request, ServerCallContext context)\n    {\n         \n    }\n \n    public override Task&lt;UserResponse&gt; Login(UserDto request, ServerCallContext context)\n    {\n         \n    }\n \n    public override Task&lt;TimeCollection&gt; GetTimes(GetTimesRequest request, ServerCallContext context)\n    {\n         \n    }\n \n    public override Task&lt;Empty&gt; AddTime(AddTimeRequest request, ServerCallContext context)\n    {\n         \n    }\n \n    public override Task&lt;ProjectCollection&gt; Projects(Empty request, ServerCallContext context)\n    {\n         \n    }   \n}<\/pre>\n\n\n\n<p><em>Example of the server implementation of a gRPC service<\/em><\/p>\n\n\n\n<hr class=\"wp-block-separator\" \/>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>If the service implementation uses the \u201cold\u201d WCF code, it may be necessary to map the parameters if the data types do not match the \u201cold\u201d DataContract classes.<\/p>\n\n\n\n<p>Furthermore, it is important to know that the lifecycle of the service implementation extends over the entire runtime of the gRPC service (singleton). Contrary to a Web API Controller, gRPC does not create a new instance of the service implementation for each request. Consequently, the state of the gRPC service is preserved between the calls. Therefore, class variables and resources created in the constructor or injected should preferably be avoided because it may not be possible to secure their state in between calls.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Implementation of the gRPC client<\/strong><\/h3>\n\n\n\n<p>You can use the empty implementation of the ServiceContract interface created in the consuming project for the implementation of the gRPC client. First, you have to establish a connection to the gRPC server.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">const int port = 9000;\nstring host = Environment.MachineName;\n \nvar channel = new Channel(host, port, ChannelCredentials.Insecure);\nvar grpcClient = new TimeService.Api.TimeService.TimeServiceClient(channel);<\/pre>\n\n\n\n<p><em>Example of a client for establishing the connection to the gRPC server<\/em><\/p>\n\n\n\n<hr class=\"wp-block-separator\" \/>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Again, a client class generated with the *.proto file in the class library project is used for this purpose. It provides the calls defined in the *.proto file.<\/p>\n\n\n\n<p>Now the corresponding calls of the gRPC client class have to be added to the empty implementation of the ServiceContract interface. It may be necessary to map the input parameters and return values used by the gRPC service to the previous DataContract classes.<\/p>\n\n\n\n<p>Because of the use and implementation of the \u201cold\u201d WCF Service interface, there is no need to adjust or change anything else in the consuming project.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Bidirectional communication<\/strong><\/h3>\n\n\n\n<p>The concept of bidirectional communication in gRPC is very different from WCF Duplex Services.<\/p>\n\n\n\n<p>With WCF, the server can easily call up various methods on the client side via callback interfaces. With gRPC, on the other hand, a server method is called by the client, which then returns data to the client by way of a stream.<\/p>\n\n\n\n<p>For this purpose, the gRPC server method has to be implemented in such a way that it is not terminated, maintaining the connection. The transmission of data to the client can then be triggered e.g. by events.<\/p>\n\n\n\n<p>After calling the server method, the client also has to maintain the connection and respond to the receipt of new data.<\/p>\n\n\n\n<p>Consequently, the conversion to gRPC streaming requires some very fundamental, conceptual adjustments.<\/p>\n\n\n\n<p><strong>Cross-cutting concerns<\/strong> such as authentication, authorization, logging and error handling of the gRPC calls have not been considered. These issues should be checked and adjusted as required in each individual case.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Conclusion<\/strong><\/h2>\n\n\n\n<p>Compared to ASP.NET Core Web API, the conversion from WCF to gRPC requires much more work and more adjustments in the code. Firstly, you have to create a *.proto file. Because of the requirement that each service call must have a return value and that only a single input parameter is permitted, some adjustments of the method signatures are necessary. As some of the generated classes do not use .NET standard types, each server and client method has to be completed with the respective mapping code.<\/p>\n\n\n\n<p>Furthermore, when you use gRPC, it is imperative to know that the lifecycle of the service instance extends over the entire runtime of the gRPC server (singleton).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This post will address gRPC as a possible alternative, and describe, step by step, how a migration from WCF to gRPC can be done.<\/p>\n","protected":false},"author":105,"featured_media":1260,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"advgb_blocks_editor_width":"","advgb_blocks_columns_visual_guide":"","footnotes":""},"categories":[8,13],"tags":[22,24,27,629,630,641],"topics":[642],"class_list":["post-1284","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-web","category-dot-net","tag-net-core","tag-microsoft","tag-asp-net-core","tag-wcf","tag-windows-communication-foundation","tag-grpc","topics-wcf-alternatives"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.0 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>WCF Alternatives (Part 3) \u2013 Instructions for the Migration from WCF to gRPC - ZEISS Digital Innovation Blog<\/title>\n<meta name=\"description\" content=\"This post will address gRPC as a possible alternative, and describe, step by step, how a migration from WCF to gRPC can be done.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"WCF Alternatives (Part 3) \u2013 Instructions for the Migration from WCF to gRPC - ZEISS Digital Innovation Blog\" \/>\n<meta property=\"og:description\" content=\"This post will address gRPC as a possible alternative, and describe, step by step, how a migration from WCF to gRPC can be done.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/\" \/>\n<meta property=\"og:site_name\" content=\"Digital Innovation Blog\" \/>\n<meta property=\"article:published_time\" content=\"2021-02-10T15:13:02+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-02-10T15:18:54+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2021\/01\/202101_WCF.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1404\" \/>\n\t<meta property=\"og:image:height\" content=\"791\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"David Siebert\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"David Siebert\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/\",\"name\":\"WCF Alternatives (Part 3) \u2013 Instructions for the Migration from WCF to gRPC - ZEISS Digital Innovation Blog\",\"isPartOf\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2021\/01\/202101_WCF.png\",\"datePublished\":\"2021-02-10T15:13:02+00:00\",\"dateModified\":\"2021-02-10T15:18:54+00:00\",\"author\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#\/schema\/person\/6b51a72db3cce2762c3e7ba935cf25bf\"},\"description\":\"This post will address gRPC as a possible alternative, and describe, step by step, how a migration from WCF to gRPC can be done.\",\"breadcrumb\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/#primaryimage\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2021\/01\/202101_WCF.png\",\"contentUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2021\/01\/202101_WCF.png\",\"width\":1404,\"height\":791},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"WCF Alternatives (Part 3) \u2013 Instructions for the Migration from WCF to gRPC\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#website\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/\",\"name\":\"Digital Innovation Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#\/schema\/person\/6b51a72db3cce2762c3e7ba935cf25bf\",\"name\":\"David Siebert\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2020\/12\/siebert_david-e1607418544482-150x150.jpg\",\"contentUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2020\/12\/siebert_david-e1607418544482-150x150.jpg\",\"caption\":\"David Siebert\"},\"description\":\"David Siebert is Senior Consultant Software Development at ZEISS Digital Innovation. His focus is primarily on .NET development. In addition, he is particularly involved with web technologies and clean code.\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/author\/endavidsiebert\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"WCF Alternatives (Part 3) \u2013 Instructions for the Migration from WCF to gRPC - ZEISS Digital Innovation Blog","description":"This post will address gRPC as a possible alternative, and describe, step by step, how a migration from WCF to gRPC can be done.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/","og_locale":"en_US","og_type":"article","og_title":"WCF Alternatives (Part 3) \u2013 Instructions for the Migration from WCF to gRPC - ZEISS Digital Innovation Blog","og_description":"This post will address gRPC as a possible alternative, and describe, step by step, how a migration from WCF to gRPC can be done.","og_url":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/","og_site_name":"Digital Innovation Blog","article_published_time":"2021-02-10T15:13:02+00:00","article_modified_time":"2021-02-10T15:18:54+00:00","og_image":[{"width":1404,"height":791,"url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2021\/01\/202101_WCF.png","type":"image\/png"}],"author":"David Siebert","twitter_card":"summary_large_image","twitter_misc":{"Written by":"David Siebert","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/","name":"WCF Alternatives (Part 3) \u2013 Instructions for the Migration from WCF to gRPC - ZEISS Digital Innovation Blog","isPartOf":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/#primaryimage"},"image":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/#primaryimage"},"thumbnailUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2021\/01\/202101_WCF.png","datePublished":"2021-02-10T15:13:02+00:00","dateModified":"2021-02-10T15:18:54+00:00","author":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#\/schema\/person\/6b51a72db3cce2762c3e7ba935cf25bf"},"description":"This post will address gRPC as a possible alternative, and describe, step by step, how a migration from WCF to gRPC can be done.","breadcrumb":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/#primaryimage","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2021\/01\/202101_WCF.png","contentUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2021\/01\/202101_WCF.png","width":1404,"height":791},{"@type":"BreadcrumbList","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wcf-alternatives-part-3\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/"},{"@type":"ListItem","position":2,"name":"WCF Alternatives (Part 3) \u2013 Instructions for the Migration from WCF to gRPC"}]},{"@type":"WebSite","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#website","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/","name":"Digital Innovation Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#\/schema\/person\/6b51a72db3cce2762c3e7ba935cf25bf","name":"David Siebert","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#\/schema\/person\/image\/","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2020\/12\/siebert_david-e1607418544482-150x150.jpg","contentUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2020\/12\/siebert_david-e1607418544482-150x150.jpg","caption":"David Siebert"},"description":"David Siebert is Senior Consultant Software Development at ZEISS Digital Innovation. His focus is primarily on .NET development. In addition, he is particularly involved with web technologies and clean code.","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/author\/endavidsiebert\/"}]}},"author_meta":{"display_name":"David Siebert","author_link":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/author\/endavidsiebert\/"},"featured_img":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2021\/01\/202101_WCF-600x338.png","coauthors":[],"tax_additional":{"categories":{"linked":["<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/web\/\" class=\"advgb-post-tax-term\">Web<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/dot-net\/\" class=\"advgb-post-tax-term\">.NET<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">Web<\/span>","<span class=\"advgb-post-tax-term\">.NET<\/span>"]},"tags":{"linked":["<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/dot-net\/\" class=\"advgb-post-tax-term\">.NET Core<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/dot-net\/\" class=\"advgb-post-tax-term\">Microsoft<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/dot-net\/\" class=\"advgb-post-tax-term\">ASP.NET Core<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/dot-net\/\" class=\"advgb-post-tax-term\">WCF<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/dot-net\/\" class=\"advgb-post-tax-term\">Windows Communication Foundation<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/dot-net\/\" class=\"advgb-post-tax-term\">gRPC<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">.NET Core<\/span>","<span class=\"advgb-post-tax-term\">Microsoft<\/span>","<span class=\"advgb-post-tax-term\">ASP.NET Core<\/span>","<span class=\"advgb-post-tax-term\">WCF<\/span>","<span class=\"advgb-post-tax-term\">Windows Communication Foundation<\/span>","<span class=\"advgb-post-tax-term\">gRPC<\/span>"]}},"comment_count":"0","relative_dates":{"created":"Posted 5 years ago","modified":"Updated 5 years ago"},"absolute_dates":{"created":"Posted on February 10, 2021","modified":"Updated on February 10, 2021"},"absolute_dates_time":{"created":"Posted on February 10, 2021 3:13 pm","modified":"Updated on February 10, 2021 3:18 pm"},"featured_img_caption":"","series_order":"","_links":{"self":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/posts\/1284","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/users\/105"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/comments?post=1284"}],"version-history":[{"count":7,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/posts\/1284\/revisions"}],"predecessor-version":[{"id":1312,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/posts\/1284\/revisions\/1312"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/media\/1260"}],"wp:attachment":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/media?parent=1284"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/categories?post=1284"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/tags?post=1284"},{"taxonomy":"topics","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/topics?post=1284"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}