NeilMacMullen
NeilMacMullen

Reputation: 3467

How can I deploy a Blazor server-hosted application from Visual Studio 2019

I am using VS2019 Preview. I have created a "server-hosted" Blazor application using the latest Blazor extension (16.0.19227). This is the variant that contains 3 separate projects...

I can debug this by making MyApp.Server the active project and all works fine but I'm struggling to publish/deploy this to Azure. I have tried the following...

At this point I get an error during deployment...

CSC(0,0): Error CS0006: Metadata file 'D:\work\Applications\Web\MyApp.Client\bin\Release\netstandard2.0\win-x86\MyApp.Client.dll' could not be found

This appears to be because the "Target Runtime" in the web-deploy profile is set to win-x86. The client application is actually being built as

"D:\work\Applications\Web\MyApp.Client\bin\Release\netstandard2.0\MyApp.Client.dll"

(without the additional win-x86 subfolder) so the deployment process seems to be making an incorrect assumption about the paths used by the build process. There's no way in the publish dialog to specify a blank/don't care target runtime.

Is there a workaround for this or perhaps I am using the wrong approach for deployment?

There is some official documentation but it's not very helpful.

Update It seems that the deployment is using the output path of the Client project and then just appending netstandard2.0{Target Runtime} to it so changing the output path in the Client project is not enough to work around the issue.

Update 2 Removing the RuntimeIdentifier tag in the publish profile by editing the xml simply results in deploy-time error stating that an empty RuntimeIdentifier is incompatible with a self-contained deployment. Unfortunately the self-contained deployment is necessary because Azure does not yet host .net core 3 directly.

Upvotes: 3

Views: 4274

Answers (3)

jsakamoto
jsakamoto

Reputation: 186

My answer is:

  • Configure the publish profile to "Self-contain" deployment mode.
  • Edit all .csproj files to change <TargetFramework>...</TargetFramework> node name to <TargetFrameworks>...</TargetFrameworks>. (see also: https://stackoverflow.com/a/42855070 )
  • Fix the web root folder path string at runtime in Startup class like below.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json.Serialization;
using System.IO;
using System.Linq;

namespace BlazorHostedOnAzure.Server
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().AddNewtonsoftJson();
            services.AddResponseCompression(opts =>
            {
                opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
                    new[] { "application/octet-stream" });
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseResponseCompression();

            // ---- APPEND PART.1 BEGIN ----
            var clientBlazorWebRootPath = default(string);
            // ---- APPEND PART.1 END ----

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseBlazorDebugging();
            }

            // ---- APPEND PART.2 BEGIN ----
            else
            {
                if (env.WebRootPath != null)
                {
                    var pathOfIndex = Path.Combine(env.WebRootPath, "index.html");
                    var pathOfContent = Path.Combine(env.WebRootPath, "_content");
                    if (!File.Exists(pathOfIndex) && Directory.Exists(pathOfContent))
                    {
                        clientBlazorWebRootPath = Directory.GetDirectories(pathOfContent).FirstOrDefault();
                        if (clientBlazorWebRootPath != null)
                        {
                            env.WebRootPath = clientBlazorWebRootPath;
                        }
                    }
                }
            }
            // ---- APPEND PART.2 END ----

            app.UseClientSideBlazorFiles<Client.Startup>();

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapDefaultControllerRoute();
                endpoints.MapFallbackToClientSideBlazor<Client.Startup>("index.html");
            });

            // ---- APPEND PART.3 BEGIN ----
            if (clientBlazorWebRootPath != null)
            {
                app.UseStaticFiles(new StaticFileOptions
                {
                    FileProvider = new PhysicalFileProvider(clientBlazorWebRootPath)
                });
            }
            // ---- APPEND PART.3 BEGIN ----
        }
    }
}

I published my sample code and README on the GitHub my repository.

Upvotes: 0

Henk Holterman
Henk Holterman

Reputation: 273284

because Azure does not yet host .net core 3 directly.

But it does.

In the Azure Portal, go to your WebApp after deployment (or create one beforehand).

Go to Extensions and click Add [+] and select ASP.NET Core 3 (x86 for the free hosting).

Also go to Settings, General and enable WebSockets, they're Off by default.


Temporary:

Note that Preview-6 is not available as an extension, so either use Preview-5 or deploy as self-contained.

Upvotes: 4

App Pack
App Pack

Reputation: 1532

Couldnt put a picture in the comment, so I thought i'd show it here. This is my current publish wizard.

enter image description here

Just did it with a brand new project via new project -> Asp.net core web application -> blazor (Asp.net core hosted) built and published fine to azure app service fine.

Upvotes: 2

Related Questions