{"id":1886,"date":"2021-01-26T12:47:49","date_gmt":"2021-01-26T12:47:49","guid":{"rendered":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/?p=1886"},"modified":"2021-01-28T10:56:16","modified_gmt":"2021-01-28T10:56:16","slug":"wcf-alternativen-teil-2","status":"publish","type":"post","link":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wcf-alternativen-teil-2\/","title":{"rendered":"WCF-Alternativen (Teil 2) \u2013 Eine Anleitung zur Migration von WCF zu Web API"},"content":{"rendered":"\n<p>In diesem Blogpost der <a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/topic\/wcf-alternativen\/\">Artikelreihe zu den Alternativen der Windows Communication Foundation (WCF)<\/a> werden die Besonderheiten und Herausforderungen einer WCF-Migration als Vorbereitung zu einer sp\u00e4teren Portierung der Anwendung auf .NET Core beschrieben.<\/p>\n\n\n\n<p>In diesem Beitrag wird dabei zun\u00e4chst auf ASP.NET Core Web-API als eine m\u00f6gliche Alternative eingegangen und Schritt f\u00fcr Schritt beschrieben, wie eine m\u00f6gliche Migration von WCF zu ASP.NET Core Web API aussehen kann. Wie dies dagegen bei der Migration zu gRPC funktioniert, lest ihr im n\u00e4chsten Blogartikel.<\/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\" id=\"vorgehen-bei-der-migration-9a6a2230-2400-477d-89b7-3e1549ef6210\"><strong>Vorgehen bei der Migration<\/strong><\/h2>\n\n\n\n<p>In der Regel existiert ein separates WCF-Projekt in der Solution. Da eine direkte Umstellung nicht m\u00f6glich ist, kann dieses Projekt zun\u00e4chst unver\u00e4ndert in der Solution verbleiben.<\/p>\n\n\n\n<p>Zun\u00e4chst sollte ein neues Class-Library-Projekt f\u00fcr Shared-Objekte zwischen Server und Client angelegt werden. In dieses Projekt werden die ServiceContract Interfaces sowie die DataContract-Klassen aus dem WCF-Projekt kopiert und die WCF-spezifischen Attribute wie &#8222;ServiceContract&#8220;, &#8222;OperationContract&#8220;, &#8222;DataContract&#8220;, &#8222;DataMember&#8220; usw. entfernt.<\/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\" id=\"client-projekt-236d5945-79de-4574-8abe-4b93f45af705\"><strong>Client Projekt<\/strong><\/h3>\n\n\n\n<p>Im WCF Service konsumierenden Projekt wird als erstes die WCF-Service-Referenz entfernt. Auch k\u00f6nnen die WCF-spezifischen Attribute wie &#8222;CallbackBehavior&#8220; o. \u00c4. entfernt werden.<\/p>\n\n\n\n<p>Eine neue Referenz zum zuvor angelegten Class-Library-Projekt f\u00fcr die Shared-Objekte wird hinzugef\u00fcgt. Als n\u00e4chstes kann im Client-Projekt eine leere Implementierung des jetzt im Class-Library-Projekt abgelegten ServiceContract Interfaces erstellt werden. Die \u201ealte\u201c Initialisierung des WCF Service wird jetzt auf die noch leere Implementierung des ServiceContract ge\u00e4ndert.<\/p>\n\n\n\n<p>Abschlie\u00dfend m\u00fcssen noch die Usings f\u00fcr die zuvor verwendeten DataContract-Klassen aus dem WCF Service auf das neue Class-Library-Projekt ge\u00e4ndert werden. Damit sollte sich das Client-Projekt wieder kompilieren lassen. Um das Projekt auch wieder starten zu k\u00f6nnen, ist der &lt;system.serviceModel&gt; aus der *.config zu entfernen.<\/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\" id=\"webapiprojekt-a90411bd-81db-422c-84cc-2536c56aac91\"><strong>Web-API-Projekt<\/strong><\/h3>\n\n\n\n<p>F\u00fcr den neuen Server wird ein &#8222;Standard&#8220; ASP.NET Core Web-API-Projekt angelegt und eine Referenz auf das neue Class-Library-Projekt hinzugef\u00fcgt. Dies ist n\u00f6tig, damit der Server dieselben Austauschklassen (vorher DataContract) wie der Client verwenden kann.<\/p>\n\n\n\n<p>F\u00fcr jeden bisherigen WCF ServiceContract wird nun in der Web-API ein Controller angelegt. Die Implementierung kann zum Einstieg aus dem &#8222;alten&#8220; WCF Service \u00fcbernommen werden. Danach m\u00fcssen die R\u00fcckgabewerte auf ActionResult bzw. ActionResult&lt;T&gt; ge\u00e4ndert werden. Es m\u00fcssen die [Http..] Verb Attribute sowie eine Route f\u00fcr jede Methode angegeben werden. Auch sollte das [ProducesResponseType]-Attribut bei jeder Methode angegeben werden \u2013 dieses beschreibt den zu erwartenden R\u00fcckgabewert und wird sp\u00e4ter f\u00fcr die Generierung des Clients verwendet.<\/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(CallbackContract = typeof(IDataCallback))]\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> GetTimes(int userId);\n\n    [OperationContract]\n    void AddTime(Time time, int userId);\n\n    [OperationContract]\n    List&lt;string> Projects();\n}<\/pre>\n\n\n\n<p><em>Beispiel eines zu migrierenden WCF Service Contract<\/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=\"\">[Route(\"api\/zeitservice\")]\n[ApiController]\npublic class ZeitServiceController : ControllerBase\n{    \n    [HttpPost(\"CreateUser\")]\n    [ProducesResponseType(typeof(int), 200)]\n    public ActionResult&lt;int> CreateUser(User user)\n    {\n \n    }\n\n    [HttpPost(\"Login\")]\n    [ProducesResponseType(typeof(int), 200)]\n    public ActionResult&lt;int> Login(User user)\n    {\n\t\t\n    }\n\n    [HttpGet(\"Times\")]\n    [ProducesResponseType(typeof(List&lt;Time>), 200)]\n    public ActionResult&lt;List&lt;Time>> GetTimes(int userId)\n    {\n        \n    }\n\n    [HttpPost(\"AddTime\")]\n    [ProducesResponseType(200)]\n    public ActionResult AddTime(Time time, int userId)\n    {\n        \n    }\n\n    [HttpGet(\"Projects\")]\n    [ProducesResponseType(typeof(List&lt;string>), 200)]\n    public ActionResult&lt;List&lt;string>> Projects()\n    {\n        \n    }\n}<\/pre>\n\n\n\n<p><em>Beispiel des erstellten Web-API-Controllers<\/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><strong>Hinweis:<\/strong> Der auf diese Weise erstellte Web API Controller entspricht vermutlich nicht einer ressourcenorientierten REST API. Die API ist eher actionbasiert und spiegelt den \u201ealten\u201c Service wider \u2013 was f\u00fcr die Umstellung aber zun\u00e4chst in Ordnung ist.<\/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-Generierung<\/strong><\/h3>\n\n\n\n<p>Um f\u00fcr den Aufruf und die Verwendung der Web API m\u00f6glichst wenig Code schreiben zu m\u00fcssen, kann dieser generiert werden. Hierzu kann die OpenAPI-Spezifikation (vormals Swagger) verwendet werden.<\/p>\n\n\n\n<p>Um die OpenAPI-Spezifikation und darauf basierend den Client Code zu generieren, gibt es verschiedene M\u00f6glichkeiten. Nachfolgend wird eine der Optionen beispielhaft beschrieben.<\/p>\n\n\n\n<p>Damit die OpenAPI-Spezifikation automatisch generiert werden kann, wird zun\u00e4chst das NuGet-Paket &#8222;NSwag.AspNetCore&#8220; eingebunden und nach der Anleitung <a href=\"https:\/\/docs.microsoft.com\/de-de\/aspnet\/core\/tutorials\/getting-started-with-nswag\" target=\"_blank\" rel=\"noreferrer noopener\">Getting started with NSwag<\/a> im Web-API-Projekt konfiguriert. Danach kann durch den Aufruf der URL \/swagger\/ bei gestartetem Web-API-Projekt die API-Schnittstelle bereits im Browser getestet werden.<\/p>\n\n\n\n<figure class=\"wp-block-image size-medium is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/12\/202012_Swagger_Overview-526x600.jpg\" alt=\"\u00dcbersicht Swagger\" class=\"wp-image-1887\" width=\"395\" height=\"450\" srcset=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/12\/202012_Swagger_Overview-526x600.jpg 526w, https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/12\/202012_Swagger_Overview-640x730.jpg 640w, https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/12\/202012_Swagger_Overview.jpg 702w\" sizes=\"auto, (max-width: 639px) 98vw, (max-width: 1199px) 64vw, 395px\" \/><figcaption><em>Abbildung 1: \u00dcbersicht Swagger<\/em><\/figcaption><\/figure>\n\n\n\n<div style=\"height:29px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<figure class=\"wp-block-image size-medium is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/12\/202012_Swagger_Detail-583x600.jpg\" alt=\"Detailansicht Swagger\" class=\"wp-image-1888\" width=\"437\" height=\"450\" srcset=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/12\/202012_Swagger_Detail-583x600.jpg 583w, https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/12\/202012_Swagger_Detail-640x659.jpg 640w, https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/12\/202012_Swagger_Detail.jpg 689w\" sizes=\"auto, (max-width: 639px) 98vw, (max-width: 1199px) 64vw, 437px\" \/><figcaption><em>Abbildung 2: Detailansicht Swagger<\/em><\/figcaption><\/figure>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Der Client Code f\u00fcr den Zugriff auf die neue Web-API kann mit dem <a href=\"https:\/\/github.com\/RicoSuter\/NSwag\/wiki\/NSwagStudio\" target=\"_blank\" rel=\"noreferrer noopener\">NSwagStudio<\/a> generiert werden. In den Einstellungen des Generators sollte dabei auf die korrekte Angabe des Namespace f\u00fcr die Generierung des Clients geachtet werden. Eventuell sind projektspezifisch weitere Einstellungen n\u00f6tig, bis das gew\u00fcnschte Ergebnis generiert wird. Der vom Generator erstellte Client sowie die im Generator vorgenommen Einstellungen (*.nswag-Datei) sollten im Projekt abgelegt werden.<\/p>\n\n\n\n<figure class=\"wp-block-image size-medium\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"418\" src=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/12\/202012_NSwag_Studio-600x418.jpg\" alt=\"NSwag-Studio-Generator\" class=\"wp-image-1889\" srcset=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/12\/202012_NSwag_Studio-600x418.jpg 600w, https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/12\/202012_NSwag_Studio-1024x714.jpg 1024w, https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/12\/202012_NSwag_Studio-768x535.jpg 768w, https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/12\/202012_NSwag_Studio-640x446.jpg 640w, https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/12\/202012_NSwag_Studio-1200x837.jpg 1200w, https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/12\/202012_NSwag_Studio.jpg 1245w\" sizes=\"auto, (max-width: 639px) 98vw, (max-width: 1199px) 64vw, 600px\" \/><figcaption><em>Abbildung 3: NSwag-Studio-Generator<\/em><\/figcaption><\/figure>\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-Verwendung<\/strong><\/h3>\n\n\n\n<p>Wird vom Generator das gew\u00fcnschte Ergebnis generiert, ist zur Einbindung des neuen Clients nur noch eine \u00c4nderung n\u00f6tig. Es muss lediglich die zuvor erstellte, noch leere Dummy-Implementierung des ServiceContract vom neu generierten Client erben und die leere Implementierung entfernt werden. Dabei muss jedoch sichergestellt werden, dass der neu generierte Client das ServiceContract Interface erf\u00fcllt.<\/p>\n\n\n\n<p>Damit ist die Migration von WCF zu Web API bereits abgeschlossen und sollte nun getestet werden.<\/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>Bidirektionale Kommunikation<\/strong><\/h3>\n\n\n\n<p>Wurde im WCF Service bidirektionale Kommunikation genutzt, muss diese jetzt \u00fcber die Verwendung von SignalR realisiert werden.<\/p>\n\n\n\n<p>Hierzu wird im Web-API-Projekt f\u00fcr jeden WCF CallbackContract eine Hub-Klasse angelegt, welche von Microsoft.AspNetCore.SignalR.Hub erbt. In der Startup.cs des Web-API-Projekts muss in der Methode ConfigureServices die Zeile &#8222;services.AddSignalR();&#8220; hinzugef\u00fcgt werden. Bei der Methode Configure wird bei der Definition von UseEndpoints je Hub ein Mapping hinterlegt &#8222;endpoints.MapHub&lt;EarningsHub&gt;(&#8222;\/Earnings&#8220;);&#8220;.<\/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 Startup\n{    \n    public void ConfigureServices(IServiceCollection services)\n    {\n        services.AddSignalR();\n    }\n\n    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n    {       \n        app.UseEndpoints(endpoints =>\n        {            \n            endpoints.MapHub&lt;EarningsHub>(\"\/Earnings\");\n        });\n    }\n}\n\npublic class EarningsHub : Microsoft.AspNetCore.SignalR.Hub\n{\n\t\n}<\/pre>\n\n\n\n<p><em>\u00c4nderungen an der Web-API-Startup Klasse und Definition des SignalR Hub<\/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>Durch Injection von IHubContext&lt;EarningsHub&gt; kann mit nur einer Zeile das Senden von Daten an alle oder nur spezifische Clients ausgel\u00f6st werden.<\/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=\"\">[Route(\"api\/zeitservice\")]\n[ApiController]\npublic class ZeitServiceController : ControllerBase\n{\n    private readonly IHubContext&lt;EarningsHub> earningsHubContext;\n    public ZeitServiceController(IHubContext&lt;EarningsHub> earningsHubContext)\n    {\n        this.earningsHubContext = earningsHubContext;\n    }\n\n    [HttpPost(\"AddTime\")]\n    [ProducesResponseType(200)]\n    public ActionResult AddTime(Time time, int userId)\n    {\n        Task.Run(async () => await earningsHubContext.Clients.All.SendAsync(\"EarningsCalculated\", result)).GetAwaiter().GetResult();\n    }\n}<\/pre>\n\n\n\n<p><em>Verwendung des SignalR Hub im API-Controller<\/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>Anschlie\u00dfend wird im konsumierenden Projekt zun\u00e4chst das NuGet-Paket &#8222;Microsoft.AspNetCore.SignalR.Client&#8220; hinzugef\u00fcgt. Wie im nachfolgenden Beispiel zu sehen ist, muss die bisher vom Server aufgerufene Methode gar nicht ge\u00e4ndert werden. Bei WCF wurde die Methode durch Verwendung des Callback Interface und deren Zuweisung bei der Initialisierung des Clients durch &#8222;new InstanceContext(this)&#8220; ausgel\u00f6st. Bei der SignalR Implementierung wird eine Verbindung zum Hub aufgebaut und das ausl\u00f6sende Server Event an die bestehende Methode gebunden.<\/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=\"\">[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Single, UseSynchronizationContext = false)]\npublic partial class Zeiterfassung : Page, IDataInputServiceCallback\n{\n    private DataInputServiceClient client;\n    \n    public Zeiterfassung()\n    { \n        client = new DataInputServiceClient(new InstanceContext(this));\n    }\n\n    public void EarningsCalculated(Dictionary&lt;int, decimal> earnings)\n    {\n        \/\/ Client Methode welche vom Server aufgerufen wird\n    }\n}\n\n[ServiceContract(CallbackContract = typeof(IDataCallback))]\npublic interface IDataInputService\n{\n    \n}\n\npublic interface IDataCallback\n{\n    [OperationContract(IsOneWay = true)]\n    void EarningsCalculated(IDictionary&lt;int, decimal> earnings);\n}<\/pre>\n\n\n\n<p><em>Client Beispiel Verwendung des WCF CallbackContract<\/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=\"\">public partial class Zeiterfassung : Page\n{\n    private HubConnection connection;\n    \n    public Zeiterfassung()\n    {    \n        connection = new HubConnectionBuilder().WithUrl(\"http:\/\/localhost:52841\/Earnings\").Build();\n        connection.On&lt;Dictionary&lt;int, decimal>>(\"EarningsCalculated\", EarningsCalculated);\n        connection.StartAsync();\n    }\n\t\n    public void EarningsCalculated(Dictionary&lt;int, decimal> earnings)\n    {\n        \/\/ Client Methode welche vom Server aufgerufen wird\n    }\n}<\/pre>\n\n\n\n<p><em>Client Beispiel nach Umstellung auf SignalR<\/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>Die hier beispielhafte Verwendung von SignalR ist sehr einfach gehalten. F\u00fcr einen produktiven Einsatz sollte eine robuste Implementierung mit automatischem Reconnect usw. sichergestellt werden \u2013 siehe dazu auch: <a href=\"https:\/\/docs.microsoft.com\/de-de\/aspnet\/core\/signalr\/dotnet-client?view=aspnetcore-3.1&amp;tabs=visual-studio\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/docs.microsoft.com\/de-de\/aspnet\/core\/signalr\/dotnet-client?view=aspnetcore-3.1&amp;tabs=visual-studio<\/a><\/p>\n\n\n\n<p>Nicht betrachtet wurden bei der Migration <strong>Querschnittsfunktionen<\/strong> wie Authentifizierung, Autorisierung, Logging und Fehlerbehandlung der Web-API-Aufrufe \u2013 diese Punkte sollten im Einzelfall gepr\u00fcft und ebenfalls angepasst werden.<\/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>Fazit<\/strong><\/h2>\n\n\n\n<p>Die Umstellung von WCF auf ASP.NET Core Web API ist mit \u00fcberschaubarem Aufwand m\u00f6glich. Die Implementierung der WCF Services kann mit kleinen Anpassungen an R\u00fcckgabewerten und Attributen direkt in die neuen Web API Controller \u00fcbernommen werden. Durch die Verwendung der OpenAPI-Spezifikation kann ein Client f\u00fcr den Zugriff auf die Web API generiert werden, welcher das bisherige WCF ServiceContract Interface unterst\u00fctzt. So m\u00fcssen in der konsumierenden Anwendung lediglich ein paar Usings und die Initialisierung des Clients angepasst werden.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In diesem Beitrag wird auf ASP.NET Core Web API als eine m\u00f6gliche Alternative zu WCF eingegangen und Schritt f\u00fcr Schritt beschrieben, wie eine Migration aussehen kann.<\/p>\n","protected":false},"author":104,"featured_media":1980,"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":[16,11],"tags":[522,556,557,558,559,521],"topics":[560],"class_list":["post-1886","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dot-net","category-web","tag-windows-communication-foundation","tag-web-api","tag-asp-net-core","tag-grpc","tag-migration","tag-wcf","topics-wcf-alternativen"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.0 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>WCF Alternativen (Teil 2) - Eine Anleitung ... - ZEISS Digital Innovation Blog<\/title>\n<meta name=\"description\" content=\"In diesem Beitrag wird ASP.NET Core Web API als m\u00f6gliche Alternative zu WCF vorgestellt und beschrieben, wie eine Migration aussehen kann.\" \/>\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\/de\/wcf-alternativen-teil-2\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"WCF Alternativen (Teil 2) - Eine Anleitung ... - ZEISS Digital Innovation Blog\" \/>\n<meta property=\"og:description\" content=\"In diesem Beitrag wird ASP.NET Core Web API als m\u00f6gliche Alternative zu WCF vorgestellt und beschrieben, wie eine Migration aussehen kann.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wcf-alternativen-teil-2\/\" \/>\n<meta property=\"og:site_name\" content=\"Digital Innovation Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/ZEISSDigitalInnovation\/\" \/>\n<meta property=\"article:published_time\" content=\"2021-01-26T12:47:49+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-01-28T10:56:16+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2021\/01\/202101_WCF_communication_technologies.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:image\" content=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2021\/01\/202101_WCF_communication_technologies.png\" \/>\n<meta name=\"twitter:creator\" content=\"@ZEISS_di\" \/>\n<meta name=\"twitter:site\" content=\"@ZEISS_di\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"David Siebert\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"7\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wcf-alternativen-teil-2\/\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wcf-alternativen-teil-2\/\",\"name\":\"WCF Alternativen (Teil 2) - Eine Anleitung ... - ZEISS Digital Innovation Blog\",\"isPartOf\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wcf-alternativen-teil-2\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wcf-alternativen-teil-2\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2021\/01\/202101_WCF_communication_technologies.png\",\"datePublished\":\"2021-01-26T12:47:49+00:00\",\"dateModified\":\"2021-01-28T10:56:16+00:00\",\"author\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#\/schema\/person\/25b5da9fd04d962532d448cb581c1912\"},\"description\":\"In diesem Beitrag wird ASP.NET Core Web API als m\u00f6gliche Alternative zu WCF vorgestellt und beschrieben, wie eine Migration aussehen kann.\",\"breadcrumb\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wcf-alternativen-teil-2\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wcf-alternativen-teil-2\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wcf-alternativen-teil-2\/#primaryimage\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2021\/01\/202101_WCF_communication_technologies.png\",\"contentUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2021\/01\/202101_WCF_communication_technologies.png\",\"width\":1404,\"height\":791},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wcf-alternativen-teil-2\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"WCF-Alternativen (Teil 2) \u2013 Eine Anleitung zur Migration von WCF zu Web API\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#website\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/\",\"name\":\"Digital Innovation Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#\/schema\/person\/25b5da9fd04d962532d448cb581c1912\",\"name\":\"David Siebert\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/12\/siebert_david-e1607418301577-150x150.jpg\",\"contentUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/12\/siebert_david-e1607418301577-150x150.jpg\",\"caption\":\"David Siebert\"},\"description\":\"David Siebert ist Senior Consultant Softwareentwicklung bei der ZEISS Digital Innovation. Sein Schwerpunkt liegt vor allem in der .NET-Entwicklung. Dar\u00fcber hinaus besch\u00e4ftigt er sich besonders mit Webtechnologien und Clean Code.\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/author\/davidsiebert\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"WCF Alternativen (Teil 2) - Eine Anleitung ... - ZEISS Digital Innovation Blog","description":"In diesem Beitrag wird ASP.NET Core Web API als m\u00f6gliche Alternative zu WCF vorgestellt und beschrieben, wie eine Migration aussehen kann.","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\/de\/wcf-alternativen-teil-2\/","og_locale":"de_DE","og_type":"article","og_title":"WCF Alternativen (Teil 2) - Eine Anleitung ... - ZEISS Digital Innovation Blog","og_description":"In diesem Beitrag wird ASP.NET Core Web API als m\u00f6gliche Alternative zu WCF vorgestellt und beschrieben, wie eine Migration aussehen kann.","og_url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wcf-alternativen-teil-2\/","og_site_name":"Digital Innovation Blog","article_publisher":"https:\/\/www.facebook.com\/ZEISSDigitalInnovation\/","article_published_time":"2021-01-26T12:47:49+00:00","article_modified_time":"2021-01-28T10:56:16+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_communication_technologies.png","type":"image\/png"}],"author":"David Siebert","twitter_card":"summary_large_image","twitter_image":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2021\/01\/202101_WCF_communication_technologies.png","twitter_creator":"@ZEISS_di","twitter_site":"@ZEISS_di","twitter_misc":{"Verfasst von":"David Siebert","Gesch\u00e4tzte Lesezeit":"7\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wcf-alternativen-teil-2\/","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wcf-alternativen-teil-2\/","name":"WCF Alternativen (Teil 2) - Eine Anleitung ... - ZEISS Digital Innovation Blog","isPartOf":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wcf-alternativen-teil-2\/#primaryimage"},"image":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wcf-alternativen-teil-2\/#primaryimage"},"thumbnailUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2021\/01\/202101_WCF_communication_technologies.png","datePublished":"2021-01-26T12:47:49+00:00","dateModified":"2021-01-28T10:56:16+00:00","author":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#\/schema\/person\/25b5da9fd04d962532d448cb581c1912"},"description":"In diesem Beitrag wird ASP.NET Core Web API als m\u00f6gliche Alternative zu WCF vorgestellt und beschrieben, wie eine Migration aussehen kann.","breadcrumb":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wcf-alternativen-teil-2\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wcf-alternativen-teil-2\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wcf-alternativen-teil-2\/#primaryimage","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2021\/01\/202101_WCF_communication_technologies.png","contentUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2021\/01\/202101_WCF_communication_technologies.png","width":1404,"height":791},{"@type":"BreadcrumbList","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wcf-alternativen-teil-2\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/"},{"@type":"ListItem","position":2,"name":"WCF-Alternativen (Teil 2) \u2013 Eine Anleitung zur Migration von WCF zu Web API"}]},{"@type":"WebSite","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#website","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/","name":"Digital Innovation Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Person","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#\/schema\/person\/25b5da9fd04d962532d448cb581c1912","name":"David Siebert","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/#\/schema\/person\/image\/","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/12\/siebert_david-e1607418301577-150x150.jpg","contentUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2020\/12\/siebert_david-e1607418301577-150x150.jpg","caption":"David Siebert"},"description":"David Siebert ist Senior Consultant Softwareentwicklung bei der ZEISS Digital Innovation. Sein Schwerpunkt liegt vor allem in der .NET-Entwicklung. Dar\u00fcber hinaus besch\u00e4ftigt er sich besonders mit Webtechnologien und Clean Code.","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/author\/davidsiebert\/"}]}},"author_meta":{"display_name":"David Siebert","author_link":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/author\/davidsiebert\/"},"featured_img":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-content\/uploads\/sites\/2\/2021\/01\/202101_WCF_communication_technologies-600x338.png","coauthors":[],"tax_additional":{"categories":{"linked":["<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/dot-net\/\" class=\"advgb-post-tax-term\">.NET<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">Web<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">.NET<\/span>","<span class=\"advgb-post-tax-term\">Web<\/span>"]},"tags":{"linked":["<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">Windows Communication Foundation<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">Web API<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">ASP.NET Core<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">gRPC<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">Migration<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/category\/web\/\" class=\"advgb-post-tax-term\">WCF<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">Windows Communication Foundation<\/span>","<span class=\"advgb-post-tax-term\">Web API<\/span>","<span class=\"advgb-post-tax-term\">ASP.NET Core<\/span>","<span class=\"advgb-post-tax-term\">gRPC<\/span>","<span class=\"advgb-post-tax-term\">Migration<\/span>","<span class=\"advgb-post-tax-term\">WCF<\/span>"]}},"comment_count":"0","relative_dates":{"created":"Posted 5\u00a0Jahren ago","modified":"Updated 5\u00a0Jahren ago"},"absolute_dates":{"created":"Posted on Januar 26, 2021","modified":"Updated on Januar 28, 2021"},"absolute_dates_time":{"created":"Posted on Januar 26, 2021 12:47 p.m.","modified":"Updated on Januar 28, 2021 10:56 a.m."},"featured_img_caption":"","series_order":"","_links":{"self":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/posts\/1886","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/users\/104"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/comments?post=1886"}],"version-history":[{"count":10,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/posts\/1886\/revisions"}],"predecessor-version":[{"id":2065,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/posts\/1886\/revisions\/2065"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/media\/1980"}],"wp:attachment":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/media?parent=1886"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/categories?post=1886"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/tags?post=1886"},{"taxonomy":"topics","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/de\/wp-json\/wp\/v2\/topics?post=1886"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}