Dear all,
we are oing to start a migration of our portal from Razor to Blazor server. Problems comes when i trie to take into telerik UI.
As soon i did the basics steps explained here
https://docs.telerik.com/blazor-ui/getting-started/server-blazor
and here
https://docs.telerik.com/blazor-ui/knowledge-base/blazor-in-asp-net
But Kestrel server didnt' go up. It crasched on
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute("default", "{controller}/{action=Index}/{id?}");
....
on
System.Reflection.ReflectionTypeLoadException: 'Unable to load one or more of the requested types.
Method 'BeginInvokeJS' in type 'Microsoft.AspNetCore.Components.WebAssembly.Services.DefaultWebAssemblyJSRuntime' from assembly 'Microsoft.AspNetCore.Components.WebAssembly, Version=3.2.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60' does not have an implementation.'
Why it is seaching for 3.2.1.0 while i am in framework 5?
Regards
Daniele
1 Answer, 1 is accepted
Hi Marin
I looked to you sample but is really simple compared to the huge quantity of things i have on the project.
But i'm super sure that i'm not having any web assembly project, all of them are razor projects.
Is there a way i can explicitelly ask for a blazor server?
Is There a way to post my files? I would like to show you how it is configured...
Regards
Daniele
BElow you can find my StartUp.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using System.Text;
using dblu.Portale.Core.Infrastructure.Classes;
using dblu.Portale.Core.Infrastructure.Identity.Services;
using dblu.Portale.Core.Infrastructure.Interfaces;
using ExtCore.WebApplication;
using ExtCore.WebApplication.Extensions;
using FluentMigrator.Runner;
using FluentMigrator.Runner.Initialization;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyModel;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json.Serialization;
using NLog;
using NLog.Extensions.Logging;
using NLog.Web;
using Syncfusion.Blazor;
using Syncfusion.Licensing;
namespace dblu.Portale
{
/// <summary>
/// Class that start up the web site
/// -> Boot strap the enviroiment
/// -> Load the external plugins
/// -> Manage the DB Migration
/// </summary>
public class Startup : IAssemblyProvider
{
/// <summary>
/// Extension paths (in witch search for plugins, in addiction to local directory)
/// </summary>
private readonly string extensionsPath;
/// <summary>
/// Log of the System
/// </summary>
private readonly Logger _log = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
/// <summary>
/// Constructor
/// </summary>
/// <param name="configuration"></param>
/// <param name="hostingEnvironment"></param>
public Startup(IConfiguration configuration, IWebHostEnvironment hostingEnvironment)
{
Configuration = configuration;
HostEnvironment = hostingEnvironment;
this.extensionsPath = hostingEnvironment.ContentRootPath + configuration["Extensions:Path"];
}
/// <summary>
/// COnfiguration interface
/// </summary>
public IConfiguration Configuration { get; }
/// <summary>
/// Envroinment
/// </summary>
public IWebHostEnvironment HostEnvironment { get; }
/// <summary>
/// Configure the services
/// </summary>
/// <param name="services"></param>
public void ConfigureServices(IServiceCollection services)
{
# region AUTHENTICATION
services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddAuthentication(options =>
{
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie(options => { options.LoginPath = "/Account/Login"; })
.AddJwtBearer("Bearer",options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = false,
ValidateAudience = false,
ValidAudience = "",
ValidIssuer = "",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"].PadRight(32, '.')))
};
options.ForwardSignIn = "/Account/Login";
});
#endregion
#region RAZOR
services.AddRazorPages(options =>
{
options.Conventions.AuthorizeFolder("/");
options.Conventions.AllowAnonymousToPage("/Error");
options.Conventions.AllowAnonymousToPage("/Account/Login");
options.Conventions.ConfigureFilter(new IgnoreAntiforgeryTokenAttribute());
}).AddNewtonsoftJson();
#endregion
#region MVC
services.AddMvc().AddNewtonsoftJson(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());//.AddNToastNotifyToastr();
#endregion
#region BLAZOR
services.AddServerSideBlazor();
#endregion
#region MISC
services.AddExtCore(this.extensionsPath,this);
services.AddKendo();
services.AddDistributedMemoryCache();
services.AddHttpContextAccessor();
services.AddSession(options => {
options.Cookie.Name = "dbluPortaleCookie";
options.IdleTimeout = TimeSpan.FromMinutes(30);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
services.Configure<IISServerOptions>(options =>
{
options.AutomaticAuthentication = false;
});
#endregion
#region SERVICES
services.AddTransient(typeof(IIndexManager), typeof(IndexManager));
#endregion
#if (DEBUG)
var mvcviews = services.AddControllersWithViews();
if (HostEnvironment.IsDevelopment())
mvcviews.AddRazorRuntimeCompilation();
#endif
services.AddTelerikBlazor();
services.AddSyncfusionBlazor();
}
/// <summary>
/// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
/// </summary>
/// <param name="app"></param>
/// <param name="env"></param>
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
SyncfusionLicenseProvider.RegisterLicense("NDI1NDc5QDMxMzkyZTMxMmUzMEVtV2pXZU5JanFMdFAwZnZLcG9EZnNzNm5nSzYxeGN0U0ZYQ1pHcDFRd1E9");
if (!env.IsProduction())
{
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(@$"C:\Users\{Environment.UserName}\.nuget\packages\syncfusion.blazor.core\19.1.0.57\staticwebassets"),
RequestPath = "/_content/Syncfusion.Blazor.Core"
});
}
else app.UseStaticFiles();
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
else
app.UseExceptionHandler("/Error");
app.UseSession();
app.UseDefaultFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseNToastNotify();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute("default", "{controller}/{action=Index}/{id?}");
endpoints.MapRazorPages();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
app.UseExtCore();
ApplyFluentMigrator();
}
/// <summary>
/// Apply Fluent Migrator to the current database
/// </summary>
private void ApplyFluentMigrator()
{
try
{
IServiceProvider ISP = new ServiceCollection().AddFluentMigratorCore().ConfigureRunner(rb => rb
.AddSqlServer()
.WithGlobalConnectionString(Configuration["ConnectionStrings:dblu.Access"])
.ScanIn(AppDomain.CurrentDomain.GetAssemblies().Where(y => y.GetName().Name.StartsWith("dblu.Portale")).ToArray()).For.Migrations())
.Configure<RunnerOptions>(opt => { opt.Tags = new string[] { }; })
.BuildServiceProvider(false);
using (var scope = ISP.CreateScope())
{
var runner = scope.ServiceProvider.GetRequiredService<IMigrationRunner>();
if (runner.HasMigrationsToApplyUp())
{
_log.Warn($"Startup.ApplyFluentMigrator: Migration ...");
runner.MigrateUp();
_log.Warn($"Startup.ApplyFluentMigrator: Migration completed");
}
_log.Info($"Startup.ApplyFluentMigrator: DB is up to date");
}
}catch(Exception)
{
_log.Warn($"Startup.ApplyFluentMigrator: No migrations found into assemblies");
}
}
/// <summary>
/// Load the plugin aseemblies (and their deps)
/// </summary>
/// <param name="path"></param>
/// <param name="includingSubpaths"></param>
/// <returns></returns>
public IEnumerable<Assembly> GetAssemblies(string path, bool includingSubpaths)
{
_log.Info($"Startup.GetAssemblies: Loading lazy assemblies...");
var pluginsPath = Path.Combine(path);
string fullPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
List<string> rootFiles = Directory.GetFiles(Path.GetDirectoryName(fullPath), "*.dll", SearchOption.TopDirectoryOnly).ToList();
List<string> plugFiles = Directory.GetFiles(pluginsPath, "*.dll", SearchOption.TopDirectoryOnly).ToList();
plugFiles.AddRange(rootFiles);
List<Assembly> Loaded = new();
List<Assembly> PlugIns = new ();
List<Assembly> Identity = new ();
List<Assembly> Asm = AppDomain.CurrentDomain.GetAssemblies().ToList();
foreach (var assemblyFile in plugFiles)
{
//ATTENZIONE!Devo caricare tutti gli assembly, non posso limitarmi ai soli "dblu.portale.plugin"
//altrimenti mancano le dll collegate.
try
{
if (Asm.FirstOrDefault(y => y.Location+y.GetName().Name == assemblyFile) == null)
{
Loaded.Add(AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyFile));
string AsmName = Path.GetFileName(assemblyFile).ToLowerInvariant();
if (AsmName.StartsWith("dblu.portale.plugin"))
{
PlugIns.Add(Loaded[^1]);
_log.Info($"Startup.GetAssemblies: Plug-in -> {Loaded[^1].GetName().Name} sucessefully loaded");
}
if (AsmName.StartsWith("dblu.portale.identity.") && !AsmName.Contains("usersmanagement"))
{
Identity.Add(Loaded[^1]);
_log.Trace($"Startup.GetAssemblies: Identity -> {Loaded[^1].GetName().Name} sucessefully loaded");
}
Asm.Add(Loaded[^1]);
}
}
catch (Exception)
{
_log.Warn($"Startup.GetAssemblies: Unable to load {assemblyFile} ");
}
}
if (Identity.Count > 1)
_log.Warn($"Startup.GetAssemblies: Loaded more than one Identity plugin ({Identity.Count})!");
if (Identity.Count < 1)
_log.Error($"Startup.GetAssemblies: Missing Identity plugin");
else
_log.Info($"Startup.GetAssemblies: Identity PlugIn -> {Identity[0].GetName().Name} sucessefully loaded");
_log.Info($"Startup.GetAssemblies: Dinamically loaded {Loaded.Count}/{Asm.Count} assemblies...");
_log.Info($"Startup.GetAssemblies: Loaded {PlugIns.Count} assemblies as external plugins");
return Loaded;
}
}
}
Again on this.
I dig really in deep and i see that the problem is that we are loading all assemblies that we found in base folder for feed our plugin system..
Since your assembly reference to Mono.WebAssembly.Interop.dll , it generates that we load it and we have the error.
I tried to avoid to load it but still cannot move forward.
:-(
Regards
Daniele
Hello Daniele,
I see a couple of potential issues I can see here:
- the line endpoints.MapFallbackToPage("/_Host"); should not be necessary, adding Blazor components to an MVC/RazorPages solution should not need it because it won't use the blazor routing.
- loading all assemblies like that should not be needed, the framework can resolve the dependencies. I am not aware of any reasons to manually load assemblies for ASP.NET (Core) or Blazor, and I recommend you do not do that.
I would suggest you start off by plugging in a vanilla Blazor app (or, rather, components) in a rather plain MVC/RazorPages setup so you can see how that works at its core, so you can then repeat the process in your real app. Then, you can start adding references to complex components and third party vendors.
As for the interop dll - I am not aware of issues with that in the general setup. Nevertheless, our next (2.24.0) release will carry optimizations around the dependencies we bring. We will stop carrying Newtonsoft.Json, Microsoft.AspNetCore.Components.WebAssembly and Microsoft.AspNetCore.Components.WebAssembly.DevServer.
--Marin
Hi Daniele,
This is just a guess, but this error indicates that a WebAssembly blazor project is being referenced in the MVC/RazorPages project you already have, while you need to have a Server-side Blazor project.
At this point I can suggest you compare against the sample project we have in this repo to find the difference causing the problem: https://github.com/telerik/blazor-ui/tree/master/common/razor-components.
Regards,
Marin Bratanov
Progress Telerik
Тhe web is about to get a bit better!
The Progress Hack-For-Good Challenge has started. Learn how to enter and make the web a worthier place: https://progress-worthyweb.devpost.com.