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

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...
MyApp.Client
MyApp.Server
MyApp.Shared
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...
Right-click on MyApp.Server in Solution-Explorer
Choose "Publish"
Go through the wizard to create a new publish profile
Change the deployment mode to "self-contained"
Hit publish
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.

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.

Couldnt put a picture in the comment, so I thought i'd show it here. This is my current publish wizard.
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.

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.
https://github.com/sample-by-jsakamoto/BlazorHostedV3Preview6OnAzureWebApp#how-to-configure-client-side-blazor-v300-preview-6-that-is-hosted-on-an-aspnet-core-server-to-deploy-it-to-azure-at-13-jul-2019

Related

Does Visual Studio Publish to App Service feature deploys items in appsettings.json to the configuration blade in the Azure portal

I am using Visual Studio 2022 to build an ASP .NET Core (v6) application.
I need to deploy and run my application on an Azure App Services instance.
I have many settings in my application's appsettings.json file. The file is included in the deployment package as shown here:
I use Visual Studio 2022 Publish feature to deploy my asp.net core application to an Azure App Services instance:
After a successful Visual Studio Publish, none of appsettings.json file settings show in the configuration blade:
Questions:
1- Is there any way Visual Studio publish feature deploy appsettings.json settings to the App Services' configuration blade?
2- Even after a successful deployment, my application does not read the settings in the appsettings.json. It seems that all ignored. I checked and on my local visual studio developer environment, my app reads appsettings.json, but not when it is deployed to App Services. Why the deployed app ignores the appsettings.json settings?
Update 1: program.cs and appsettings.json
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
builder.Logging.AddAzureWebAppDiagnostics();
// Add services to the container.
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddApplicationInsightsTelemetry();
builder.Services.AddScoped<Framework>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
appsettings.json could be anything. Just need to read its content with a ConfigurationManager instance like how I read them when the site is running locally in Visual Studio.
Is there any way Visual Studio publish feature deploy appsettings.json` settings to the App Services' configuration blade?
The deployed appsettings.json file will be available in KUDU Debug Console.
In your Azure App Service => Advanced Tools => Go => Debug Console => cmd => site => wwwroot.
Or even you can open the KUDU with the below URL
https://YourAppServiceName.scm.azurewebsites.net/
Configuration section will not display the setting which are in appsettings.json file. It is used to override the available settings from appsettings.jsonfile.
The values which you want to override and the new values which you want to add after deployment must be set in the Application Settings in portal.
The key name must be same in both appsettings.json and Configuration => Application Settings.
My sample appsettings.json :
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MyVal": "Local Connection"
},
"AppSettings": {
"MySettings": "Local Settings"
}
}
Code to retrieve values from appsettings.json
var MyAppSettings = builder.Configuration.GetSection("AppSettings");
var LocalAppset = MyAppSettings.GetValue<string>("MySettings");
OR
var MyAppSettings1 = builder.Configuration.GetValue<string>("AppSettings:MySettings");
Index.cshtml
#page
#model IndexModel
#using Microsoft.Extensions.Configuration
#inject IConfiguration Configuration
<h2>Configuration value for 'AppSettings': #Configuration["AppSettings:MySettings"]</h2>
I have deployed the app and able to read the values from the deployed code.
Initial Values
Overridden Values

SSRS reports with .Net Core 3.1 MVC application

I am trying to display the SSRS report in a .Net Core 3.1 MVC application.
I tried to implement the approach mentioned in
https://alanjuden.com/2016/11/10/mvc-net-core-report-viewer/?unapproved=58532&moderation-hash=321d5350c96d2fcf83baa4c939bbdf53#comment-58532
public class ReportsController : AlanJuden.MvcReportViewer.ReportController
{
protected override ICredentials NetworkCredentials
{
get
{
//Custom Domain authentication (be sure to pull the info from a config file)
return new System.Net.NetworkCredential("username", "password");
//Default domain credentials (windows authentication)
//return System.Net.CredentialCache.DefaultNetworkCredentials;
}
}
protected override string ReportServerUrl
{
get
{
//You don't want to put the full API path here, just the path to the report server's ReportServer directory that it creates (you should be able to access this path from your browser:
return "https://YourReportServerUrl.com/ReportServer/ReportExecution2005.asmx";
}
}
public IActionResult ProcessReport()
{
var model = this.GetReportViewerModel(Request);
model.ReportPath = "reportPath";
return RedirectToAction("ReportViewer", model);
}}
but it is not working with the latest framework.
I am getting following error while running the project - Error screenshot
Any help is appreciated.
Thanks!
The same thing happened to me, in my case I needed to install the same package that tells you to install
Install-Package System.ServiceModel.Http -Version 4.1.0
or in the nuget look for the package System.ServiceModel.Http
I tried different workarounds with latest .NET Core including the one you mentioned from Alan Juden. However the easiest thing that worked for me is to create a plain .NET WebForms site using the Report Viewer control from Microsoft. It was still a lot of code but this is solid because the Report Viewer control has been around for many years.
In my case it is showing SSRS Report from Angular UI, but the same will work with MVC or any other Web UI because you will actually redirect/navigate to another url (WebForms aspx page).
More details here.

Azure (C#) System.IO.FileNotFoundException: Could not find file

I've created a ML model with Visual Studio. I uploaded the web app to Azure with Visual Studio too. However, when I fill the fields for my ML model and click "run" on the website, I get this error which I copied directly from Azure App Service Editor.
I only get this error while trying to run the ML model on Azure website, if I run the web app on my computer I have no errors at all.
Thank you :)
The error:
2020-07-18 01:12:59.138 +00:00 [Error] Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware: An unhandled exception has occurred while executing the request.
System.IO.FileNotFoundException: Could not find file 'C:\Users\X\X\X\fileML.Model\MLModel.zip'.
File name: 'C:\Users\X\X\X\fileML.Model\MLModel.zip'
____________________
My code:
// This file was auto-generated by ML.NET Model Builder.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.ML;
using fileML.Model;
namespace fileML.Model
{
public class ConsumeModel
{
private static readonly Lazy<PredictionEngine<ModelInput, ModelOutput>> PredictionEngine = new Lazy<PredictionEngine<ModelInput, ModelOutput>>(CreatePredictionEngine);
// For more info on consuming ML.NET models, visit https://aka.ms/mlnet-consume
// Method for consuming model in your app
public static ModelOutput Predict(ModelInput input)
{
ModelOutput result = PredictionEngine.Value.Predict(input);
return result;
}
public static PredictionEngine<ModelInput, ModelOutput> CreatePredictionEngine()
{
// Create new MLContext
MLContext mlContext = new MLContext();
// Load model & create prediction engine
string modelPath = #"C:\Users\X\X\X\fileML.Model\MLModel.zip";
ITransformer mlModel = mlContext.Model.Load(modelPath, out _);
var predEngine = mlContext.Model.CreatePredictionEngine<ModelInput, ModelOutput>(mlModel);
return predEngine;
}
}
}
Nathan, welcome to the stackoverflow. Here is thing you are missing:
You are trying to access local path from your computer but on Azure there is no local machine so whenever you code tries to access the same path which you have hard coded it's resulting in error.
My recommendation would be to add your zip file to your project, once added right click on that file and mark Copy to Output Directory - Copy always. Please see below
This will help to get the local file path from output directory.
Now it's time to change your code to get file dynamically.
You can use
string directoryPath = Directory.GetCurrentDirectory();
string modelPath= Path.Combine(directoryPath ,"MLModel.zip");
This will get you the file path. Just do a test your code on your local and deploy the app.
The good thing is now your model file will get deployed along with your code. Every time you change your model just replace the file and deploy code again.
Hint to make it more dynamic:- You can also use Azure Blob Storage to keep your zip file, by using this you do not need to deploy your code again and again . Just need to replace the file in side blob.
you are trying to load file MLModel.zip from C:\Users\X\X\X\fileML.Model. Now that's your local computer path. That path not exists into Azure Web App.
There are 2 ways you can do if you really want to store in local directory:
HOMe environment variable in your Azure Web App that resolves to the
equivalent of inetpub for your site. Your app data folder is located
at %HOME%\site\wwwroot\AppData.
TEMP environment both on Azure Web Apps and on your local machine.
public static PredictionEngine<ModelInput, ModelOutput> CreatePredictionEngine()
{
// Create new MLContext
MLContext mlContext = new MLContext();
// Load model & create prediction engine
string directoryPath = Directory.GetCurrentDirectory();
string modelPath = Path.Combine(#"C:\Users\Admin\source\repos\ShanuASPMLNETML.Model\MLModel.zip","MLModel.zip");
ITransformer mlModel = mlContext.Model.Load(modelPath, out _);
var predEngine = mlContext.Model.CreatePredictionEngine<ModelInput, ModelOutput>(mlModel);
return predEngine;
}
}

Aspose - The invoked member is not supported in a dynamic assembly. in mscrm

My case : I am running a job combining dynamics crm that uses aspose to create pdf files, everything was working fine suddenly I got the error - The invoked member is not supported in a dynamic assembly. At the current moment In my dev environment everything works fine only In my qa environment I get that exception. I checked the path I use it is correct. I tried to put the licence near the dll file in a specific file etc'... still I get this msg, what is the solution in my case ?
my function:
public void EnsureAsposeLicenseIsSet()
{
if (!AsposeLicenseWasSet)
{
lock ("EnsureAsposeLicenseIsSet")
{
if (!AsposeLicenseWasSet)
{
License wordLicense = new License();
wordLicense.SetLicense(GetConfigByKey("Asposelicence"));
AsposeLicenseWasSet = true;
}
}
}
}
Include the Aspose license file as an Embedded resource instead, and it will work.

How to make a new Perfect Project from scratch (Swift server) in xcode?

Perfect is a new Swift Framework for creating a web/http server in swift. The documentation is not there yet and I find trouble with building a new project from scratch. I don't know which frameworks are necessary to import and which one is the entry point of the app. main.swift etc...
I'd like to make a new xcworkspace that will have my project, "a hello world server".
Problems I'm trying to tackle:
Which frameworks must be included?
How should I create a Perfect server, what's the entry point of the app?
How to create a "hello" root which responds with a "Hello World message"?
How should I make the target for the server and eventually run the server?
I managed to write a "Hello World" guide about this. http://code-me-dirty.blogspot.co.uk/2016/02/creating-perfect-swift-server.html
In a nutshell you need to proceed like this:
clone the original project
Create a new Workspace
Create a new Project
Import PerfectLib.xcodeproject & Import PerfectServer.xcodeproject but do not copy
Setup your project scheme to launch the PerfectServer HTTP App
Link the PerfectLib onn the "Linked Frameworks and Libraries" section
setup Build settings for your framework target*
Create PerfectHandlers.swift and paste(better write to get the feeling) the following code
import PerfectLib
//public method that is being called by the server framework to initialise your module.
public func PerfectServerModuleInit() {
// Install the built-in routing handler.
// Using this system is optional and you could install your own system if desired.
Routing.Handler.registerGlobally()
// Create Routes
Routing.Routes["GET", ["/", "index.html"] ] = { (_:WebResponse) in return IndexHandler() }
// Check the console to see the logical structure of what was installed.
print("\(Routing.Routes.description)")
}
//Create a handler for index Route
class IndexHandler: RequestHandler {
func handleRequest(request: WebRequest, response: WebResponse) {
response.appendBodyString("Hello World")
response.requestCompletedCallback()
}
}
Then you are ready to run. On my blog I have a long, more detailed version of this and I will update here if necessary.
Build Settings
Deployment Location: Yes
Installation Build Products Location : $(CONFIGURATION_BUILD_DIR)
Installation Directory : /PerfectLibraries
Skip Install : NO
I just wrote up a tutorial I want to share as another solution that outlines how to create a web service with Perfect and an app to interact with it.
http://chrismanahan.com/creating-a-web-service-swift-perfect
Summary
You must have your project in a workspace. This workspace should also include the PerfectServer and PerfectLib projects.
In your project, create a new OSX Framework target. This will be your server target
Link PerfectLib with both your server target and your app's target (if you're building an app alongside the server)
Edit your server's Run scheme to launch with PerfectServer HTTP App.
In your Server target's Build Settings, set the following flags:
Skip Install = No
Deployment Location = Yes
Installation Directory = /PerfectLibraries
Installation Build Products Location = $(CONFIGURATION_BUILD_DIR)
Create a new file in the server's folder. This file will handle requests that come in. Include [most of] the following:
import PerfectLib
// This function is required. The Perfect framework expects to find this function
// to do initialization
public func PerfectServerModuleInit() {
// Install the built-in routing handler.
// This is required by Perfect to initialize everything
Routing.Handler.registerGlobally()
// These two routes are specific to the tutorial in the link above.
// This is where you would register your own endpoints.
// Take a look at the docs for the Routes API to better understand
// everything you can do here
// register a route for gettings posts
Routing.Routes["GET", "/posts"] = { _ in
return GetPostHandler()
}
// register a route for creating a new post
Routing.Routes["POST", "/posts"] = { _ in
return PostHandler()
}
}
class GetPostHandler: RequestHandler {
func handleRequest(request: WebRequest, response: WebResponse) {
response.appendBodyString("get posts")
response.requestCompletedCallback()
}
}
class PostHandler: RequestHandler {
func handleRequest(request: WebRequest, response: WebResponse) {
response.appendBodyString("creating post")
response.requestCompletedCallback()
}
}
As you're building out different aspects of your service, you can test it by using cURL in the command line, or other REST testing tools like Postman
If you wanna dive deeper and learn how to integrate with a SQLite database or create an app that talks with your new server, check out the tutorial at the top of this post.
I would recommend staying away from the templates, as others suggested, and create a clean project yourself.
Create this folder structure:
MyAPI
├── Package.swift
└── Sources
└── main.swift
Then, in the Package.swift file
import PackageDescription
let package = Package(
name: "MyAPI",
targets: [],
dependencies: [
.Package(url: "https://github.com/PerfectlySoft/Perfect-HTTPServer.git", majorVersion: 2)
]
)
And the main.swift file:
import PerfectHTTP
import PerfectHTTPServer
do {
let route = Route(method: .get, uri: "/hello", handler: { (request: HTTPRequest, response: HTTPResponse) in
response.appendBody(string: "world!")
response.completed()
})
try HTTPServer.launch(.server(name: "localhost", port: 8080, routes: [route]))
} catch {
fatalError("\(error)")
}
Go to the command line and run:
swift package generate-xcodeproj
Open the generated project file:
MyAPI.xcodeproj
Change the active scheme, then build and run:
Open in safari:
http://localhost:8080/hello
I'm not sure if you have found a solution or not, but this is what I did:
The 'Tap Tracker' app is an app written the the Perfect libraries, so even if documentation isn't ready yet you can still dissect the app. I renamed the app, and the classes/methods. There's a single index.html, which I moved into a 'www' root, and then rerouted the view with TTHandler to try and make a standard layout. It doesn't work very well because the framework is so young, but it can be done. I would be much more specific but I went back to rails for the time being because I want to wait until it's a little more mature.
It's fun to mess around with, and I will probably write my own library on top of perfect onc feature innovation calms down and I can make something stable with it.
Just copy all files from one of the sample-projects to your git repository:
https://github.com/PerfectExamples
Rename the example_project_name in all files (you've copied) to your project name.
In terminal run
swift package generate-xcodeproj
And you'll get a Perfect Project with the required name.

Resources