{"id":287787,"date":"2021-06-30T14:29:30","date_gmt":"2021-06-30T11:29:30","guid":{"rendered":"https:\/\/en.buradabiliyorum.com\/serving-dynamic-files-with-blazor-in-asp-net-cloudsavvy-it\/"},"modified":"2021-06-30T14:29:30","modified_gmt":"2021-06-30T11:29:30","slug":"serving-dynamic-files-with-blazor-in-asp-net-cloudsavvy-it","status":"publish","type":"post","link":"https:\/\/buradabiliyorum.com\/en\/serving-dynamic-files-with-blazor-in-asp-net-cloudsavvy-it\/","title":{"rendered":"#Serving Dynamic Files With Blazor in ASP.NET \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-6a26e72279083\" 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-6a26e72279083\" 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\/serving-dynamic-files-with-blazor-in-asp-net-cloudsavvy-it\/#Why_Serve_Dynamic_Files\" >Why Serve Dynamic Files?<\/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\/serving-dynamic-files-with-blazor-in-asp-net-cloudsavvy-it\/#Setting_It_Up\" >Setting It Up<\/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\/serving-dynamic-files-with-blazor-in-asp-net-cloudsavvy-it\/#Serving_Files_Based_On_Routes_Parameters\" >Serving Files Based On Routes &amp; Parameters<\/a><\/li><\/ul><\/nav><\/div>\n<p><strong>&#8220;#Serving Dynamic Files With Blazor in ASP.NET \u2013 CloudSavvy IT&#8221;<\/strong><\/p>\n<div id=\"article-content-area\">\n<img loading=\"lazy\" decoding=\"async\" class=\"type:primaryImage alignnone size-full wp-image-12309\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/06\/74fb9d73.png?width=1198&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"700\" height=\"350\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>One of the many great features of frameworks like <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/click.linksynergy.com\/deeplink?id=2QzUaswX1as&amp;mid=24542&amp;u1=csit\/12336&amp;murl=https%3A%2F%2Fdotnet.microsoft.com%2Fapps%2Faspnet%2Fweb-apps%2Fblazor\">Blazor<\/a> and ASP.NET (which it runs on) is the ability to serve dynamic content at whatever endpoint your application needs. If you\u2019d like to serve <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\">download<\/a>s of generated files, it\u2019s easy to do with a little configuration.<\/p>\n<h2 role=\"heading\" aria-level=\"2\"><span class=\"ez-toc-section\" id=\"Why_Serve_Dynamic_Files\"><\/span>Why Serve Dynamic Files?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Basically, you have two options as a web server: respond to a request with static content, like an HTML page or JPG file, or generate a custom response to send to the user. <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/click.linksynergy.com\/deeplink?id=2QzUaswX1as&amp;mid=24542&amp;u1=csit\/12336&amp;murl=https%3A%2F%2Fdotnet.microsoft.com%2Fapps%2Faspnet%2Fweb-apps%2Fblazor\">Blazor<\/a> runs on ASP.NET, so the built-in HTTP server supports a wide array of options and allows for great flexibility.<\/p>\n<p>For example, perhaps you want to host an JSON file at <code>\/images\/pathname.json<\/code>. This doesn\u2019t have to be a literal file on disk; the server can interpret this request and respond with any type of content, including something unexpected like a PNG file. You could respond to this request by fetching some results from an API, constructing a response, and sending the string back to the user.<\/p>\n<p>Or perhaps you\u2019d like to generate the actual file on the fly. For example, there are many graphics libraries used for drawing custom images. You could use one of these to generate an image and respond to the user request with the data, all in memory.<\/p>\n<p>In the latter case, it may make sense to cache the response by saving it on disk and replying with a real file most of the time. This can be useful for resource-intensive file generations that don\u2019t change that often.<\/p>\n<h2 role=\"heading\" aria-level=\"2\"><span class=\"ez-toc-section\" id=\"Setting_It_Up\"><\/span>Setting It Up<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Serving files like this is built-in and pretty simple to do. You\u2019ll need to create a new Razor page, which is what <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/click.linksynergy.com\/deeplink?id=2QzUaswX1as&amp;mid=24542&amp;u1=csit\/12336&amp;murl=https%3A%2F%2Fdotnet.microsoft.com%2Fapps%2Faspnet%2Fweb-apps%2Fblazor\">Blazor<\/a> runs on. You can do this by right-clicking in Visual Studio and selecting Add &gt; Razor Page.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-12337\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/06\/c74e70df.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"608\" height=\"238\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Doing this creates two files that are linked with each other in the hierarchy: <code>Name.cshtml<\/code>, which handles the HTML side of things, and <code>Name.cshtml.cs<\/code>, which handles the model and the actual code. Since this isn\u2019t going to be an actual web page, just a file, you can ignore the first one for the most part.<\/p>\n<p>You will however need to set the <code>@page<\/code>\u00a0attribute to match where you\u2019d like this file to be hosted. You\u2019ll probably want to include some wildcards, which you do with brackets.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-12338\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/06\/775cfcb3.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"604\" height=\"159\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>In the <code>Name.cshtml.cs<\/code>\u00a0file, you\u2019ll see some actual code extending <code>PageModel<\/code>. The main function here is <code>OnGet()<\/code>, which you will probably want to change to <code>OnGetAsync()<\/code>\u00a0if you\u2019re doing any asynchronous processing.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-12339\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/06\/3194c7a4.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"484\" height=\"87\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>You have three main options from this function. First, is returning a PhysicalFile, which literally reads a file on disk given a path, and sends it to the user with a type, optionally with a separate download name than the actual path.<\/p>\n<p>While you\u2019re probably here to generate something dynamically, this can be very useful for caching. If you have your processing function save the result to a file, you can check if that file exists before processing it again, and if it does, simply return the cached response.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-12341\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/06\/d0af0dbc.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"684\" height=\"166\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>The next option is returning a virtual file, given a byte array. This is what you\u2019ll want to use for most applications, as it operates entirely in memory and should be very fast.<\/p>\n<p>Depending on what encoding you\u2019re trying to use, you may want to convert a string to a byte array using the <code>Encoding<\/code> helper class.<\/p>\n<pre>Encoding.UTF8.GetBytes(string);<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-12342\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/06\/93db0661.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"492\" height=\"73\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Lastly, you can return a content string directly, which is what you should use if you want to display the content to the user rather than triggering a download in their browser.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-12343\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/06\/1c5e735a.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"561\" height=\"77\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>There are other options than these three, but the rest involve replying with status codes, redirecting, unauthorized responses, and rendering the page itself.<\/p>\n<h2 role=\"heading\" aria-level=\"2\"><span class=\"ez-toc-section\" id=\"Serving_Files_Based_On_Routes_Parameters\"><\/span>Serving Files Based On Routes &amp; Parameters<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Of course, none of this is useful if you can\u2019t respond to requests based on user input. The two forms of input are both in the URL: routing parameters and URL parameters. Routing parameters are what you specified using wildcards in the page itself, and are the actual path to the file. URL parameters are optional.<\/p>\n<p>Figuring this out can be a bit of a pain, but luckily you have a debugger at your side, so you can set a breakpoint in <code>OnGetAsync()<\/code>\u00a0and view the entire local variable tree.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-12344\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/06\/8980c604.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"625\" height=\"415\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>You\u2019ll find, under <code>this.PageContext.RouteData<\/code>, there\u2019s a <code>RouteValueDictionary&lt;string, object&gt;<\/code>\u00a0which stores all the routes. Note that this includes the page route itself, so if you used <code>\/Download\/{param}<\/code>\u00a0as the route, the param will be the second option.<\/p>\n<p>The best way to fetch the parameters is to look them up by key:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-12345\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/06\/f6430fe4.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"530\" height=\"114\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Similarly, the query parameters are also available, though from a different object. You\u2019ll need to access <code>HttpContext.Request.Query<\/code>, which is a <code>QueryValueDictionary<\/code>\u00a0containing the URL parameters, and works in much the same way as the route one.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-12346\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/06\/919529d8.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"609\" height=\"83\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>You are then free to use these parameters to perform lookups or affect logic. Though, if you are caching responses, you will want to make sure your cache conditions and lookups are affected by these parameters as well, or you could run into problems with unexpected caching behaviors.\n<\/p><\/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\/12336\/serving-dynamic-files-with-blazor-in-asp-net\/\" target=\"_blank\" rel=\"noopener\">Source<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;#Serving Dynamic Files With Blazor in ASP.NET \u2013 CloudSavvy IT&#8221; One of the many great features of frameworks like Blazor and ASP.NET (which it runs on) is the ability to serve dynamic content at whatever endpoint your application needs. If you\u2019d like to serve downloads of generated files, it\u2019s easy to do with a little&#8230;<\/p>\n","protected":false},"author":1,"featured_media":287788,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/06\/74fb9d73.png","fifu_image_alt":"","footnotes":""},"categories":[18],"tags":[],"class_list":["post-287787","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\/287787","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=287787"}],"version-history":[{"count":0,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/287787\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media\/287788"}],"wp:attachment":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media?parent=287787"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/categories?post=287787"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/tags?post=287787"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}