{"id":321531,"date":"2021-08-11T14:00:36","date_gmt":"2021-08-11T11:00:36","guid":{"rendered":"https:\/\/en.buradabiliyorum.com\/how-to-create-c-client-web-apps-with-microsofts-blazor-web-framework-cloudsavvy-it\/"},"modified":"2021-08-11T14:00:36","modified_gmt":"2021-08-11T11:00:36","slug":"how-to-create-c-client-web-apps-with-microsofts-blazor-web-framework-cloudsavvy-it","status":"publish","type":"post","link":"https:\/\/buradabiliyorum.com\/en\/how-to-create-c-client-web-apps-with-microsofts-blazor-web-framework-cloudsavvy-it\/","title":{"rendered":"#How to Create C# Client Web Apps With Microsoft\u2019s Blazor Web Framework \u2013 CloudSavvy IT"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_84 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6a2d4c6004fc5\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #dd3333;color:#dd3333\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #dd3333;color:#dd3333\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6a2d4c6004fc5\" checked aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-c-client-web-apps-with-microsofts-blazor-web-framework-cloudsavvy-it\/#What_Is_Blazor\" >What Is Blazor?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-c-client-web-apps-with-microsofts-blazor-web-framework-cloudsavvy-it\/#Hybrid_Mode\" >Hybrid Mode<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-c-client-web-apps-with-microsofts-blazor-web-framework-cloudsavvy-it\/#Setting_Up_Blazor\" >Setting Up Blazor<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-c-client-web-apps-with-microsofts-blazor-web-framework-cloudsavvy-it\/#A_Tour_Of_The_Blazor_Environment\" >A Tour Of The Blazor Environment<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-c-client-web-apps-with-microsofts-blazor-web-framework-cloudsavvy-it\/#Fixing_Microsofts_Awful_Color_Choices\" >Fixing Microsoft\u2019s Awful Color Choices<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-c-client-web-apps-with-microsofts-blazor-web-framework-cloudsavvy-it\/#Serving_Dynamic_Content\" >Serving Dynamic Content<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-c-client-web-apps-with-microsofts-blazor-web-framework-cloudsavvy-it\/#How_Does_Styling_Work\" >How Does Styling Work?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-c-client-web-apps-with-microsofts-blazor-web-framework-cloudsavvy-it\/#Blazor_Component_Lifecycle\" >Blazor Component Lifecycle<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-c-client-web-apps-with-microsofts-blazor-web-framework-cloudsavvy-it\/#How_Does_Blazor_Work_with_JavaScript\" >How Does Blazor Work with JavaScript?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-c-client-web-apps-with-microsofts-blazor-web-framework-cloudsavvy-it\/#Navigating_The_User_Around\" >Navigating The User Around<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-c-client-web-apps-with-microsofts-blazor-web-framework-cloudsavvy-it\/#Manually_Updating_The_Page_On_URL_Change\" >Manually Updating The Page On URL Change<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-c-client-web-apps-with-microsofts-blazor-web-framework-cloudsavvy-it\/#Blazor_Libraries\" >Blazor Libraries<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-create-c-client-web-apps-with-microsofts-blazor-web-framework-cloudsavvy-it\/#The_Future_Of_Blazor\" >The Future Of Blazor<\/a><\/li><\/ul><\/nav><\/div>\n<p><strong>&#8220;#How to Create C# Client Web <a href=\"https:\/\/buradabiliyorum.com\/en\/category\/download-scripts-themes-apps\/\" data-internallinksmanager029f6b8e52c=\"9\" title=\"Download Scripts &amp; Themes &amp; Apps\" target=\"_blank\" rel=\"noopener\">App<\/a>s With Microsoft\u2019s Blazor Web Framework \u2013 CloudSavvy IT&#8221;<\/strong><\/p>\n<div id=\"article-content-area\">\n<img loading=\"lazy\" decoding=\"async\" class=\"type:primaryImage alignnone wp-image-13185 size-full\" srcset=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/bca5f5f6-1.png?width=398&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1 400w, https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/bca5f5f6-1.png?width=1198&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1 1200w\" sizes=\"auto, 400w, 1200w\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/bca5f5f6-1.png?width=1198&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"Blazor logo\" width=\"1200\" height=\"675\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Blazor is a new web framework that allows you to create fully interactive web apps using C#. Using the magic of a .NET runtime compiled for WebAssembly, you can even run Blazor entirely on the client\u2014you don\u2019t have to use JavaScript frameworks to create your applications anymore.<\/p>\n<h2 role=\"heading\" aria-level=\"2\"><span class=\"ez-toc-section\" id=\"What_Is_Blazor\"><\/span><a rel=\"nofollow noopener\" target=\"_blank\" name=\"autotoc_anchor_0\">What Is Blazor?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Blazor is the latest feature of ASP.NET Core, Microsoft\u2019s 20 year old web framework. Despite being old, Microsoft still maintains it, and ASP.NET has been consistently improving along with C# and the .NET runtime as a whole.<\/p>\n<p>Razor pages, and ASP.NET\u2019s old MVC model, both allow you to generate data-driven HTML pages using C#. That\u2019s been around forever, but what it\u2019s always lacked is <em>interactivity<\/em>. It\u2019s pretty hard to make a web app when you have to reload the page to view changes.<\/p>\n<p>So, Blazor solves that by directly linking the server and client with a library that can modify the DOM at runtime, and brings in many of the component lifecycle methods and update handlers that you\u2019d expect out of a framework intended to compete with React.<\/p>\n<p>And, with Razor page\u2019s minimalist syntax, it makes coding in Blazor a breeze:<\/p>\n<p>Blazor has two main modes of operation, the coolest of which is <strong>Blazor Client<\/strong>, which packages .NET itself into a framework that can be run entirely on WebAssembly. WASM is basically MSIL for the web; it\u2019s a lightweight binary instruction format that any language can compile to, even \u201cdesktop\u201d languages like C++ and Rust.<\/p>\n<p>So how is performance with this? Well, currently it\u2019s using an interpreter, as <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/github.com\/dotnet\/runtime\/issues\/44316\">native AOT compilation for .NET is still being worked on<\/a>. But that will improve eventually; the main downside of Blazor Client is longer download times\u2014DLLs can be big files by web standards, and they all need to be loaded to get the application up and running. However, large JS frameworks also have this problem, and is a big reason why server-side rendering is popular.<\/p>\n<p>It makes up for that download time by being very fast to refresh pages and navigate around the app, considering it doesn\u2019t have to wait for the server to do so.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-13176 size-full\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/f1f009bb.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"Instead of talking to the server over SignalR, Blazor WebAssembly directly talks to the DOM.\" width=\"533\" height=\"395\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>If you want to use a more traditional hosting model similar to React\u2019s Server Side Rendering (SSR), that option is also available to you. It\u2019s more performant, and comes with the benefit of running code on a trusted server.<\/p>\n<p>To achieve this, <strong>Blazor Server<\/strong> can connect to the client using a SignalR connection, which is just a fancy wrapper over WebSockets that can also fall back to HTTP if it needs to. This does put more stress on the ASP.NET server than traditional web hosting, as it needs to re-render and re-send every single HTML change to all connected clients. If you have thousands of people connected, this can be an issue when scaling up.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-13175 size-full\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/f502d4cf.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"Blazor Server uses a SignalR connection\u00a0to communicate between the client and server. \" width=\"699\" height=\"406\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>While Blazor is currently a web framework, Microsoft is also making Blazor Desktop, which functions a lot like Electron does by packaging web UIs into desktop applications, as well as Blazor Native, which will be able to render native UIs on mobile operating systems. Microsoft seems to think of it as their next application programming model for making interactive frontends on any platform.<\/p>\n<h2 role=\"heading\" aria-level=\"2\"><span class=\"ez-toc-section\" id=\"Hybrid_Mode\"><\/span><a rel=\"nofollow noopener\" target=\"_blank\" name=\"autotoc_anchor_1\">Hybrid Mode<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Blazor can also be used in a \u201chybrid mode\u201d using <em>prerendering<\/em>. Blazor WASM can display raw HTML while the framework loads, usually used for a loading bar or spinner wheel. But, if you host the app from ASP.NET, you can render the Razor pages from the server before you even send the app to the client.<\/p>\n<p>This works perfectly, with the catch that the page will not become interactive until Blazor actually loads. It usually only takes a second though so this isn\u2019t really an issue, besides some quirks with reloading data twice.<\/p>\n<p>With this setup, you get the best of both worlds\u2014 your app loads quickly, with no loading screen, and it\u2019s lightning fast to navigate around. This feature is still being worked on, and comes with a lot of quirks, but as of .NET 6 preview 6, it is working, and you can read more at <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/jonhilton.net\/tags\/prerendering\/\">Jon Hilton\u2019s guides<\/a>, parts\u00a0<a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/jonhilton.net\/blazor-wasm-prerendering\/\">one<\/a> and <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/jonhilton.net\/blazor-wasm-prerendering-missing-http-client\/\">two<\/a>.<\/p>\n<p>One of the quirks is that WASM apps relying on an API will have to have two implementations of each service, on the client and server, so that the server can talk to itself to fetch the information when it pre-renders.\u00a0This results in some flashing when WASM loads and does its own data fetching, but this can be fixed in\u00a0.NET 6\u2014<a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/jonhilton.net\/blazor-prerendering-net6\/\">this guide shows how to persist component state<\/a>\u00a0so that your app will seamlessly transition from the fake \u201cloading page\u201d to the real application.<\/p>\n<h2 role=\"heading\" aria-level=\"2\"><span class=\"ez-toc-section\" id=\"Setting_Up_Blazor\"><\/span><a rel=\"nofollow noopener\" target=\"_blank\" name=\"autotoc_anchor_2\">Setting Up Blazor<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Luckily <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/click.linksynergy.com\/deeplink?id=2QzUaswX1as&amp;mid=24542&amp;u1=csit\/11962&amp;murl=https%3A%2F%2Fvisualstudio.microsoft.com%2F\">Visual Studio<\/a> provides generators and you don\u2019t have to set this all up yourself. Open Visual Studio, and create a new project. Search for \u201cBlazor\u201d and select either Blazor WebAssembly or Blazor Server.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13622\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/bd0035f1.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"990\" height=\"420\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>We\u2019ll go with Blazor WebAssembly here, as Blazor Server is simpler and just includes both the client and server in the same project.<\/p>\n<p>Give it a name and select your framework. One thing to note is that Blazor WebAssembly technically doesn\u2019t even need a server at all; you can just host it as a static website on NGINX or even an AWS S3 bucket. But, if you\u2019re connecting to an API to talk to a database, you might as well make that API bundled with the client, as you can share code between them and of course use the same language.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13623\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/3608f23b.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"787\" height=\"441\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>You solution will be set up with three projects, a client application, an ASP.NET server API and web host for the client, and a shared library between them.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13624\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/ba9aed0c.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"550\" height=\"462\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>If you click launch, you\u2019ll see ASP.NET boot up and serve the web page. If you\u2019re using Blazor Server, it will connect to ASP.NET over SignalR to handle interactions.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13625\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/a0eb7ccd.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"1033\" height=\"400\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Of course, Blazor WebAssembly will only send requests to the server when made explicitly by the application.<\/p>\n<h2 role=\"heading\" aria-level=\"2\"><span class=\"ez-toc-section\" id=\"A_Tour_Of_The_Blazor_Environment\"><\/span><a rel=\"nofollow noopener\" target=\"_blank\" name=\"autotoc_anchor_3\">A Tour Of The Blazor Environment<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Let\u2019s take a tour of the application. Starting with the client, the main entry point is\u00a0<code>Program.cs<\/code>, which creates the WebAssemblyHost, adds the root <code>App.razor<\/code>\u00a0component, then builds and runs the app.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13626\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/1dc01c14.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"850\" height=\"280\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Technically, the entry point is <code>wwwroot\/index.html<\/code>, which loads Blazor\u2019s JavaScript file, shows a loading page while Blazor initializes, and shows an error message if it doesn\u2019t.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13627\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/18851307.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"849\" height=\"403\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p><code>App.razor<\/code>\u00a0handles routing of pages using a <code>Router<\/code>\u00a0component. This takes in the assembly and loads all pages marked with the <code>@page name<\/code>\u00a0attribute. You can learn more about <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/www.learnrazorpages.com\/razor-pages\/routing\">routing in Razor pages here<\/a>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13628\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/8b9ba8b8.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"589\" height=\"170\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>The router loads the <code>MainLayout.razor<\/code>\u00a0component, which extends LayoutComponentBase. That loads the <code>NavMenu.razor<\/code>\u00a0component alongside the body, and displays your application.<\/p>\n<p>Great! As for the server, it\u2019s a standard ASP.NET application. It creates a host builder, and adds services configured in <code>Startup.cs<\/code>. Notably, it configures it for WASM debugging, serves the Blazor Framework files, and configures its own Razor pages and controllers to serve JSON content.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13629\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/241f8d7c.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"1046\" height=\"737\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>If this was just a Blazor Server app, it wouldn\u2019t need this separate API, and could just fetch data from an internal service. But since it isn\u2019t, it needs to expose that service over the wire, in the form of a ASP.NET ApiController that specifies handler methods for different HTTP actions.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13630\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/875389e2.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"786\" height=\"442\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>The models for this are shared between client and server, in the shared project.<\/p>\n<h2 role=\"heading\" aria-level=\"2\"><span class=\"ez-toc-section\" id=\"Fixing_Microsofts_Awful_Color_Choices\"><\/span><a rel=\"nofollow noopener\" target=\"_blank\" name=\"autotoc_anchor_4\">Fixing Microsoft\u2019s Awful Color Choices<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Before sitting down to code, we need to fix something. For some reason, Microsoft\u2019s default color choice for C# HTML directives in Razor pages is using what is perhaps the worst color combination imaginable\u2014light purple text on a light tan background.<\/p>\n<p>Luckily you can change it from Tools &gt; Options:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13634\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/bed056a2.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"304\" height=\"129\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Under Environment &gt; Fonts and Colors, select \u201cRazor Directive\u201d and change the background color to something more reasonable. You probably still want it to stand out, so I just chose pure black, which will be noticeable but non-intrusive.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13633\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/c5e609d1.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"701\" height=\"337\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>You\u2019ll also need to change \u201cHTML Server-Side Script,\u201d (which is technically now an outdated name considering Blazor WebAssembly\u2019s existence).<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13635\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/9b6d12b6.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"722\" height=\"157\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>And with that simple fix, you can save your eyeballs hours of pain.<\/p>\n<h2 role=\"heading\" aria-level=\"2\"><span class=\"ez-toc-section\" id=\"Serving_Dynamic_Content\"><\/span><a rel=\"nofollow noopener\" target=\"_blank\" name=\"autotoc_anchor_5\">Serving Dynamic Content<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The last file you\u2019ll want to check out is on the client, <code>FetchData.razor<\/code>. This is where the client actually consumes the server-side API, with the following data-driven page:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13631\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/6c4fa370.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"732\" height=\"655\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>This is a fairly complex Razor page, so it\u2019s a good example for us to break down here.<\/p>\n<p>To start, it specifies a manual override for the page route with <code>@page \"\/fetchdata\"<\/code>. It then imports the shared models from the shared project, and also uses dependency injection to give it an HttpClient, which was set up in <code>Program.cs<\/code>.<\/p>\n<p>We\u2019ll skip down to the bottom to explain this first\u2014the <code>@code<\/code>\u00a0block contains the actual C# code for this page. In it, there\u2019s a private variable called <code>forecasts<\/code>. This is initially null, but when the page is initialized, it makes a web request to grab the data from the API and deserialize it.<\/p>\n<p>When that variable is updated, Blazor detects the change and re-renders the page. The page itself is everything in between, which starts with a header and description, but then contains an <code>@if<\/code>\u00a0statement. This is C# conditional HTML, and in this case is used to show loading text while Blazor is making the request to the API. Then, once it finishes and re-renders, <code>forecasts<\/code>\u00a0won\u2019t be null, and it will render the table that will do <code>@foreach<\/code>\u00a0element in the list, and render a table row.<\/p>\n<p>Using this, you can render dynamic content from your models. To support more advanced CRUD operations, and more dynamic UIs, you will need to use buttons and inputs. You can use <code>&lt;button&gt;<\/code>\u00a0tags with an <code>@onclick<\/code>\u00a0attribute, which takes a method reference.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13640\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/37049d77.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"596\" height=\"531\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>You <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/docs.microsoft.com\/en-us\/aspnet\/core\/blazor\/components\/event-handling?view=aspnetcore-5.0#eventcallback\">can use EventCallbacks<\/a> to pass the event up to parent components. You can also use Lambda expressions to handle events inline, if the method is short:<\/p>\n<pre>&lt;button @onclick=\"@(e =&gt; heading = \"New heading!!!\")\"&gt;&#13;\n    Update heading&#13;\n&lt;\/button&gt;<\/pre>\n<p>There are <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/docs.microsoft.com\/en-us\/aspnet\/core\/blazor\/components\/event-handling?view=aspnetcore-5.0#event-arguments\">multiple additional event arguments<\/a> that you can pass to these handler functions, including mouse location, keyboard events, and touch events.<\/p>\n<p>If you want to implement a search box, Blazor has binds for that. However, if you want it to search automatically when you press enter, and not on every keypress, you\u2019ll need to bind the @onkeydown event to a function, which takes a KeyboardEventArgs object, and manually check if Enter was pressed.<\/p>\n<p>You can\u2019t get the input value from the\u00a0KeyboardEventArgs though, so it results in this messy input box where you must bind onkeydown and oninput, set a string value, and then use that string in onkeydown.<\/p>\n<pre>&lt;input type=\"text\" @onkeydown=\"@Enter\" @oninput=\"@(ui =&gt; { searchValue = (string) ui.Value;})\" \/&gt;&#13;\n&#13;\n@code {&#13;\n    public void Enter(KeyboardEventArgs e)&#13;\n    {&#13;\n        if (e.Code == \"Enter\" || e.Code == \"NumpadEnter\")&#13;\n        { &#13;\n             \/\/do stuff&#13;\n        }&#13;\n    } &#13;\n}<\/pre>\n<h2 role=\"heading\" aria-level=\"2\"><span class=\"ez-toc-section\" id=\"How_Does_Styling_Work\"><\/span>How Does Styling Work?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13645\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/4d348f03.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"1093\" height=\"477\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Extremely simple. There\u2019s a <code>site.css<\/code>\u00a0master file, but for component level styling, just create a <code>.razor.css<\/code>\u00a0file for each Razor page:<\/p>\n<pre>index.razor&#13;\nindex.razor.css<\/pre>\n<p>Blazor will automatically create a scoped CSS file that applies the settings from each Razor page to only that Razor page:<\/p>\n<pre>&lt;link href=\"https:\/\/www.cloudsavvyit.com\/11962\/how-to-create-c-client-web-apps-with-microsofts-blazor-web-framework\/BlazorWebAssemblyTest.Client.styles.css\" rel=\"stylesheet\" \/&gt;&#13;\n&#13;\n\/* \/Pages\/Counter.razor.rz.scp.css *\/&#13;\nh1[b-3xxtam6d07] {&#13;\n    color: brown;&#13;\n}<\/pre>\n<p>Getting pre-processors like SASS to work <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/chrissainty.com\/get-some-sass-into-your-blazor-app\/\">is a little more complicated, but completely doable.<\/p>\n<h2 role=\"heading\" aria-level=\"2\"><span class=\"ez-toc-section\" id=\"Blazor_Component_Lifecycle\"><\/span><a rel=\"nofollow noopener\" target=\"_blank\" name=\"autotoc_anchor_7\">Blazor Component Lifecycle<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Like React, Blazor also has component lifecycle bindings. As per this diagram from <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/blazor-university.com\/components\/component-lifecycles\/\">Blazor University<\/a>, a fantastic resource for learning Blazor, the Blazor runtime calls them in the following order:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13648\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/82e77dad.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"1200\" height=\"951\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>SetParametersAsync and OnParametersSet are called whenever the component\u2019s parent renders. OnInitializedAsync is also called here if it\u2019s the first time. Then, for each user interaction, the event can call StateHasChanged, which checks if it should render, and triggers this update process all over again.<\/p>\n<p>There are too many details to list here, so you should <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/blazor-university.com\/components\/component-lifecycles\/\">read the guide from Blazor University<\/a>, which explains all of them, as well as weird interactions with async\/await methods. To render as much content as fast as possible, Blazor may run StateHasChanged and render twice, once right when the Task awaiter object is returned, and once when it\u2019s finished.<\/p>\n<h2 role=\"heading\" aria-level=\"2\"><span class=\"ez-toc-section\" id=\"How_Does_Blazor_Work_with_JavaScript\"><\/span><a rel=\"nofollow noopener\" target=\"_blank\" name=\"autotoc_anchor_8\">How Does Blazor Work with JavaScript?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Regardless of whether you go with Blazor Server or Blazor Desktop, you have full JavaScript interoperability, such as calling JS functions from managed code:<\/p>\n<pre>private async Task ConvertArray()&#13;\n{&#13;\n    text = new(await JS.InvokeAsync&lt;string&gt;(\"convertArray\", quoteArray));&#13;\n}<\/pre>\n<p>And calling .NET from JS:<\/p>\n<pre>DotNet.invokeMethodAsync('{ASSEMBLY NAME}', '{.NET METHOD ID}', {ARGUMENTS});<\/pre>\n<p>You can actually use all NPM packages with Blazor, though you should prefer a NuGet package most of the time if it\u2019s an option.<\/p>\n<h2 role=\"heading\" aria-level=\"2\"><span class=\"ez-toc-section\" id=\"Navigating_The_User_Around\"><\/span><a rel=\"nofollow noopener\" target=\"_blank\" name=\"autotoc_anchor_9\">Navigating The User Around<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>One of the most important problems with web apps, especially single page web apps (SPWAs), is routing. Each Razor page has a default route according to its name, but you can override this, and you can also add multiple page routes to each Razor page.\u00a0The router will match each one separately and still serve the same file.<\/p>\n<p>However, if you want to serve different content depending on what URL you\u2019re on, things get a little complicated. The simplest solution would just be define a @page route for each string you want to add. This works the first time, but because of the way Blazor handles updates, it won\u2019t refresh the page when navigating to a new URL because the\u00a0<em>parameters<\/em> haven\u2019t changed. You can still use this to define multiple spellings of the same page, as long as those pages don\u2019t link to each other.<\/p>\n<p>The solution to the SPWA problem is to use <em>parameter based routes<\/em> whenever you want to catch multiple options and link between them. Parameters can be defined in brackets:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-12255\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/06\/e93b44e5.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"255\" height=\"81\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>This particular setup is for the root page. If you\u2019re concerned that it\u2019s going to match other pages like <code>\/error<\/code> since it\u2019s configured to match anything after root, don\u2019t worry, Blazor will match other pages that are strictly defined before falling back to using parameter-based routes. However, you can\u2019t have multiple parameter routes on the same root route without getting an ambiguous route error.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-12254\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/06\/37258abf.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"700\" height=\"119\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>In my case, I wanted to navigate the user to a new page with an argument. You can do this by accessing the NavigationManager and calling NavigateTo:<\/p>\n<pre>NavManager.NavigateTo(\"\/search\/\" + searchValue);<\/pre>\n<p>If you want more advanced routing, you\u2019ll need to look into <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/chrissainty.com\/working-with-query-strings-in-blazor\/\">Query Parameters<\/a>.<\/p>\n<h4><span class=\"ez-toc-section\" id=\"Manually_Updating_The_Page_On_URL_Change\"><\/span>Manually Updating The Page On URL Change<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>One of the quirks of Blazor is that it doesn\u2019t trigger an update when your URL changes, even if you have stateful code that depends on it, so you\u2019ll need to manually update. Luckily, the NavigationManager has a delegate for when the location changes, and you can bind a function to that.<\/p>\n<pre>NavigationManager.LocationChanged += HandleLocationChanged;<\/pre>\n<p>You\u2019ll want to use InvokeAsync with a function that updates whatever state object your app depends on. Then, you\u2019ll need to call StateHasChanged afterwards to trigger a refresh.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-12263\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/06\/6b26fa7a.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"648\" height=\"194\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>You can also call\u00a0OnParametersSetAsync from here, if your code also depends on other URL parameters and you don\u2019t want to copy\/paste.<\/p>\n<h2 role=\"heading\" aria-level=\"2\"><span class=\"ez-toc-section\" id=\"Blazor_Libraries\"><\/span><a rel=\"nofollow noopener\" target=\"_blank\" name=\"autotoc_anchor_10\">Blazor Libraries<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13644\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/20eb7d81.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"1200\" height=\"614\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>One of the benefits of Blazor is that it\u2019s not a brand new thing\u2014it\u2019s built on the 20 year backbone of ASP.NET, and so it already comes with a diverse ecosystem of libraries. We won\u2019t get into a list of them here, because there\u2019s already the <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/github.com\/AdrienTorris\/awesome-blazor\">awesome-blazor list on GitHub<\/a> that covers everything.<\/p>\n<p>However, one thing you should definitely be using is a pre-made component library. There are a couple free ones, but <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/blazor.radzen.com\/\">RadZen<\/a> is one of the most popular ones, and it\u2019s completely open source.\u00a0<a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/blazorise.com\/\">Blazorise<\/a>\u00a0is another great one, though it\u2019s only free for non-commercial products.<\/p>\n<p>In either case, using pre-made component layouts and hand-styling them later will allow for rapid prototyping, and speed up your development time drastically. We highly recommend them.<\/p>\n<h2 role=\"heading\" aria-level=\"2\"><span class=\"ez-toc-section\" id=\"The_Future_Of_Blazor\"><\/span><a rel=\"nofollow noopener\" target=\"_blank\" name=\"autotoc_anchor_11\">The Future Of Blazor<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-13180 size-full\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/07bbf33a.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"You can use Blazor on desktop.\" width=\"1200\" height=\"483\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Blazor is a truly unique framework among an ocean of JavaScript-based React clones, and with Microsoft behind it, it has a bright future. We mentioned earlier that Microsoft had plans for Blazor Desktop, which is coming in late 2021.<\/p>\n<p>Blazor Desktop will function a lot like Electron does, where it launches your app in a Chromium container with some bindings for desktop functionality. Except, instead of using Chromium, Blazor Desktop is going to use native based WebViews, and run the .NET code directly on the machine.<\/p>\n<p>In the meantime, you can actually get Blazor on the desktop\u00a0now with\u00a0<a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/github.com\/ElectronNET\/Electron.NET\">Electron.NET<\/a>, and it works surprisingly well. All you have to do is install it and add Electron as an ASP.NET service. You can also call Electron native functions from C#.\n<\/div>\n<blockquote><p><strong><span style=\"color: #ff6600;\">If you liked the article, do not forget to share it with your friends. Follow us on\u00a0<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/news.google.com\/publications\/CAAqBwgKMLG0nwswvr63Aw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Google News<\/a><\/span>\u00a0too, click on the star and choose us from your favorites.<\/span><\/strong><\/p><\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\">For forums sites go to <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/forum.buradabiliyorum.com\/\" target=\"_blank\" rel=\"noopener\">Forum.BuradaBiliyorum.Com<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\"><strong>If you want to read more like this article, you can visit our <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/en.buradabiliyorum.com\/technology\/\" target=\"_blank\" rel=\"noopener\">Technology category.<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<p><span style=\"color: black;\"><a style=\"color: #ff9900;\" href=\"https:\/\/www.cloudsavvyit.com\/11962\/how-to-create-c-client-web-apps-with-microsofts-blazor-web-framework\/\" target=\"_blank\" rel=\"noopener\">Source<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;#How to Create C# Client Web Apps With Microsoft\u2019s Blazor Web Framework \u2013 CloudSavvy IT&#8221; Blazor is a new web framework that allows you to create fully interactive web apps using C#. Using the magic of a .NET runtime compiled for WebAssembly, you can even run Blazor entirely on the client\u2014you don\u2019t have to use&#8230;<\/p>\n","protected":false},"author":1,"featured_media":321532,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/08\/bca5f5f6-1.png","fifu_image_alt":"","footnotes":""},"categories":[18],"tags":[],"class_list":["post-321531","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology"],"_links":{"self":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/321531","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/comments?post=321531"}],"version-history":[{"count":0,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/321531\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media\/321532"}],"wp:attachment":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media?parent=321531"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/categories?post=321531"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/tags?post=321531"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}