NO definition for 'SetBeforeAccess' TokenCache - azure-active-directory

I've directly copied a GitHub sample code and cannot get rid of these errors.
Error CS1061 'TokenCache' does not contain a definition for 'SetBeforeAccess'
I've included Microsoft.Identity.Client in my using statements.
using System.IO;
using System.Security.Cryptography;
using Microsoft.Identity.Client;
namespace TokenCache1
{
static class TokenCacheHelper
{
public static TokenCache GetUserCache()
{
if (usertokenCache == null)
{
usertokenCache = new TokenCache();
usertokenCache.SetBeforeAccess(BeforeAccessNotification);
usertokenCache.SetAfterAccess(AfterAccessNotification);
}
return usertokenCache;
}
static TokenCache usertokenCache;
/// <summary>
/// Path to the token cache
/// </summary>
public static string CacheFilePath = System.Reflection.Assembly.GetExecutingAssembly().Location + "msalcache.txt";
private static readonly object FileLock = new object();
public static void BeforeAccessNotification(TokenCacheNotificationArgs args)
{
lock (FileLock)
{
args.TokenCache.Deserialize(File.Exists(CacheFilePath)
? File.ReadAllBytes(CacheFilePath)
: null);
}
}
I'm using .NET4.5 and UWP apps.

This could have occurred due to missing MSAL library. It can be installed from NuGet on Visual Studio itself.
On Visual Studio, select the Tools menu, choose NuGet Package Manager, then Package Manager Console, and type the following command:
Install-Package Microsoft.Identity.Client -Pre

I had the same problem:
TokenCacheExtensions class was not accessible when the reference added from packages\Microsoft.Identity.Client.1.1.3-preview0012\Microsoft.Identity.Client.dll
But when I added the reference from
packages\Microsoft.Identity.Client.1.1.3-preview0012\lib\net45\Microsoft.Identity.Client.dll
then i was able to access the TokenCacheExtension class.

Related

Installation of MudBlazor in a Blazor winforms application

I was going through the installation for MudBlazor and I am having some issues with the following lines of code in the installation guide...
using MudBlazor.Services;
builder.Services.AddMudServices();
winforms does not contain a builder by default so I altered the program.cs file as figured below...
internal static class Program
{
public static IServiceProvider? ServiceProvider { get; set; }
static void ConfigureServices()
{
var services = new ServiceCollection();
services.AddMudServices();
ServiceProvider = services.BuildServiceProvider();
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
ConfigureServices();
Application.Run(new Form1());
}
}

Using Prism for building a Plugin (.dll)

I am developing a plugin to be used for a software I use. The software plugin is attached to the software by attaching the .dll produced from my code. Therefore, the software's documentation requires you to have a certain class (call it CPlugin) as the plugins entry point.
All the tutorials I am reading with Prism is where you initiate your project as a WPF Application. This way your project will have App.xaml and App.cs files where you start to implement your Prism framework. Compiling the code also (for a WPF application) will produce a .exe not a .dll.
The way I have my plugin setup is I start my project with a C# class. I would then create my CPlugin class and initiate all my variables and then display my MainView which creates my ViewModel and take it from there. There is no App.xaml or App.cs. I am not sure how to use Prism with the constraints I have.
This is the software I am developing the plugin for: https://www.csiamerica.com/products/etabs
Upon installation in the install directory; the API helpfile can be found which explains how to develop or initiate a plugin. Here is a sample of the relevant information:
In your plugin, all functionality must be implemented in a class called cPlugin.
Class cPlugin must contain a subroutine cPlugin.Main that has two
reference arguments of types ETABSv1.cSapModel and
ETABSv1.cPluginCallback
Also
Adding a .NET Plugin
The process for adding a .NET plugin is much simpler. In the External Plugin Data form, the user should simply browse for and select the plugin .NET DLL and click the "Add" button
Here is some sample code for a plugin that displays an empty window:
Create a C# Class Library file (.NET Framework), reference the API as one of my references.
CPlugin.cs:
using Combonito.Views; // Access Views (open window)
using CSiAPIv1; //to Access ETABS/SAP2000 API
using System;
using static Globals;
namespace Combonito
{
// cPlugin has to be implemented in ETABS Plugins, it has to contain two functions Main() and Info()
public class cPlugin
{
private MainView _MyForm;
//Entry point of plugin - has to exist with this exact signature
// must call Finish() when plugin is closed!
public void Main(ref cSapModel _SapModel, ref cPluginCallback _ISapPlugin)
{
ParentPluginObject = this;
SapModel = _SapModel;
ISapPlugin = _ISapPlugin;
try
{
_MyForm = new MainView(); //Create MainView
_MyForm.ShowDialog(); // Display window
}
catch (Exception ex)
{
try
{
ISapPlugin.Finish(1);
Console.WriteLine(ex);
}
catch (Exception ex1)
{
Console.WriteLine(ex1);
throw;
}
}
}
// return value should be 0 if successful
public int Info(ref string txt)
{
try
{
txt = "Plugin is written by Moustafa El-sawy (mk.elsawy#live.com)";
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
return 0;
}
//Deconstructor to clean up
~cPlugin()
{
Console.WriteLine(GC.GetGeneration(0));
}
}
}
I then have an empty window MainView and A viewmodel MainWindowViewModel.
Edit: Here is the boiler initial to start any plugin similar to what I showed above but has more explanation https://kinson.io/post/etabs-plugin-quickstart/
Your starting point should be Bootstrapper
First you need to install:
Prism.Unity
Prism.Wpf
Need to create your bootstrapper based on
https://github.com/PrismLibrary/Prism/blob/master/src/Wpf/Prism.Wpf/PrismBootstrapperBase.cs
Override the virtual method to create Shell (which is your main view that contains regions
Override the virtual method to configure your container.
Finally register your views and viewmodels
P.S.: Consider using an interface for each registered type e.g. IShellViewModel
using Prism;
using Prism.Ioc;
using Prism.Unity;
using System.Windows;
namespace PrismTest
{
public class Bootstrapper : PrismBootstrapperBase
{
protected override IContainerExtension CreateContainerExtension()
{
return new UnityContainerExtension();
}
protected override DependencyObject CreateShell()
{
return Container.Resolve<Shell>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.Register<IShellViewModel, ShellViewModel>();
}
}
}
Call your Bootstrapper from your plugin :
Bootstrapper bootstrapper = new Bootstrapper();
bootstrapper.Run();
Your View (Shell)
<Window
x:Class="PrismTest.Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:PrismTest"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="Shell"
Width="800"
Height="450"
mc:Ignorable="d">
<Grid>
<TextBox Text="{Binding MyText}" />
</Grid>
</Window>
In Shell.xaml.cs: Use your view model. This can be also automatically injected
public partial class Shell : Window
{
private readonly IUnityContainer _container;
public Shell(IUnityContainer container)
{
InitializeComponent();
_container = container;
this.DataContext = _container.Resolve<IShellViewModel>();
}
}
Your ViewModel
public class ShellViewModel : BindableBase, IShellViewModel
{
private string m_MyText = "Shell ViewModel Text";
public string MyText
{
get { return m_MyText; }
set { SetProperty(ref m_MyText, value); }
}
}
Your interface:
internal interface IShellViewModel
{
string MyText { get; set; }
}
Resulting view;

WPF and EntityFrameworkCore - Adding migration gives "No database provider has been configured for this DbContext"

Note I have read the large number of SO answers that appear to be similar, but I am already doing what they suggested, so I don't know if there is some difference with WPF (they all seem to relate to ASP.NET). Also, most answers relate to run-time errors, not ones when adding migrations.
I'm trying to set up a .NET Core 3 WPF project that uses EntityFrameWork Core, but am having problems adding a migration. I have set up my context as follows...
public class ApplicationDbContext : DbContext {
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options) {
}
public ApplicationDbContext() {
}
public DbSet<Product> Products { get; set; }
}
The parameterless constructor is there, as without it I get an exception Unable to create an object of type 'ApplicationDbContext' when trying to add a migration.
My App.xaml.cs contains the following...
public partial class App {
public IServiceProvider ServiceProvider { get; private set; }
public IConfiguration Configuration { get; private set; }
protected override void OnStartup(StartupEventArgs e) {
IConfigurationBuilder builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appSettings.json", optional: false, reloadOnChange: true);
Configuration = builder.Build();
ServiceCollection serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
ServiceProvider = serviceCollection.BuildServiceProvider();
MainWindow mainWindow = ServiceProvider.GetRequiredService<MainWindow>();
mainWindow.Show();
}
private void ConfigureServices(IServiceCollection services) {
// Configuration
services.Configure<AppSettings>(Configuration.GetSection(nameof(AppSettings)));
// Database
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("SqlConnection")));
// Windows
services.AddTransient(typeof(MainWindow));
}
}
I realise that some of this is irrelevant, but thought I'd show the whole class in case it reveals something I missed. The code is based on this blog post.
However, when I try to add a migration, I get an exception "No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions object in its constructor and passes it to the base constructor for DbContext."
As far as I can see, I have configured the database provider. I put a breakpoint in the ConfigureServices method, and can see that services.AddDbContext is called with the correct connection string.
Anyone any ideas what I've missed?
UPDATE I tried connecting to an existing database, and it worked absolutely fine, so it looks like the database provider has been configured correctly. It's only when I try to add a migration that I get the exception.
UPDATE 2 It seems that the migration tool is using the parameterless constructor on the context, which is why it thinks the provider hasn't been configured. If I remove the lines that configure it from App.xaml.cs, and instead override the OnConfiguringmethod to call UseSqlServer then the migration works fine. However, apart from the fact that I've not seen anyone else doing this (which makes me wonder if it's really the right way to do it), I don't see how to get the connection string from the config file. I can't inject an IConfiguration parameter, as the whole issue is that migrations requires a parameterless constructor.
It's actually quite simple with .Net Core 3.1 and EF Core Version 5, Entity Framework will look at the entry point class for the static function CreateHostBuilder, in my case that would be the App class in app.xaml.cs.
Not entirely sure the convention required prior to .Net Core 3.1. From my experience it had something to do with having a Startup class with .Net Core 2.1 and ASP.Net.
https://learn.microsoft.com/en-us/ef/core/cli/dbcontext-creation?tabs=dotnet-core-cli
My solution:
public partial class App : Application
{
/// <summary>
/// Necessary for EF core to be able to find and construct
/// the DB context.
/// </summary>
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
// Configure Application services
.ConfigureServices((context, services) =>
{
ConfigureServices(context, services);
});
}
/// <summary>
/// Not necessary but I prefer having a separate function for
/// configuring services.
/// </summary>
private static void ConfigureServices(HostBuilderContext context, IServiceCollection services)
{
...
}
/// <summary>
/// Hold the built Host for starting and stopping
/// </summary>
private readonly IHost AppHost;
/// <summary>
/// Constructor
/// </summary>
public App()
{
// Create Application host
AppHost = CreateHostBuilder(new string[] { }).Build();
}
/// <summary>
/// App Startup Event Handler
/// </summary>
private async void Application_Startup(object sender, StartupEventArgs e)
{
// Start the application host
await AppHost.StartAsync();
...
}
/// <summary>
/// App Exit Event Handler
/// </summary>
private async void Application_Exit(object sender, ExitEventArgs e)
{
// Kill the application host gracefully
await AppHost.StopAsync(TimeSpan.FromSeconds(5));
// Dispose of the host at the end of execution
AppHost.Dispose();
}
}
You need to implement IDesignTimeDbContextFactory. There is a lot of hidden plumbing in an ASP.NET Core app that deals with wiring up the apps service provider so it can be found by the dotnet ef tooling, but no such plumbing exists in WPF. In addition the ef tools know nothing about WPF events so your OnStartup method isn't going to even be called (an instance the class wont even get created) to create your DI setup so that the ef tools can find your DBContext.
Move the code that creates the ServiceProvider into the constructor, other than the bit that looks up the main window and displays it.
Implement IDesignTimeDbContextFactory<ApplicationDbContext>. In the implemented CreateDbContext method return ServiceProvider.GetRequiredService<ApplicationDbContext>()
The tooling will then create an instance of your class, which will setup DI, and call that method to get your (now configured) DB Context and it should work.
I'd also recommend moving to HostBuilder based config (that blog post was written before the final version of Core 3 was released). You will find an updated version of the same post here

Nancy fails to find static content in custom convention

I've set up a Nancy bootstrapper to serve static content from a non-default directory path (it's self hosted Nancy).
Strangely, the following works for the custom View location convention but not either of the js or css static content conventions (and yes, both files and folders exist at these locations!). My attempts at trying to resolve this are further compounded as I haven't figured out how to log errors which occur when static content is not found.
using System;
using System.IO;
using Nancy;
using Nancy.Conventions;
using Nancy.Bootstrapper;
using Nancy.TinyIoc;
namespace MyApp
{
public class ApplicationBootstrapper : DefaultNancyBootstrapper
{
private const string RELATIVE_PATH_TO_SOURCE = #"../static/MyApp/";
protected override void ConfigureConventions(NancyConventions nancyConventions)
{
nancyConventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("js", string.Concat(RELATIVE_PATH_TO_SOURCE, "Scripts/")));
nancyConventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("css", string.Concat(RELATIVE_PATH_TO_SOURCE, "Content/")));
this.Conventions.ViewLocationConventions.Add((viewName, model, context) =>
{
return string.Concat(RELATIVE_PATH_TO_SOURCE, "Views/", viewName);
});
this.Conventions.ViewLocationConventions.Add((viewName, model, context) =>
{
return string.Concat(RELATIVE_PATH_TO_SOURCE, "Views/", context.ModuleName, "/", viewName);
});
base.ConfigureConventions(nancyConventions);
}
protected override IRootPathProvider RootPathProvider
{
get
{
return new MyRootPathProvider();
}
}
protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
{
pipelines.OnError += (ctx, ex) =>
{
Console.WriteLine("RootPath : {0}", DebugRootPathProvider.RootPath);
Console.WriteLine("Unhandled error on request: {0} : {1}", ctx.Request.Url, ex.Message); //HACK
Console.WriteLine(ex.StackTrace); //HACK poor man's logging
return null;
};
}
}
public class MyRootPathProvider : IRootPathProvider
{
public static readonly string RootPath;
static MyRootPathProvider()
{
RootPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
}
public string GetRootPath()
{
return RootPath;
}
}
}
The output from Chrome and ProcMon is as follows:
How should I:
Log errors occurring with not found js and css files?
Resolve the 404 errors with the static file conventions?
Instead of logging you can use sysinternals process monitor and look for what files the nancy process (exe or IIS worker process) are attempting to read.
I had problems with serving static files (in my case js files) in a self host environment as well. They were not recognized at all, not even in the default "Content" folder. My solution: I installed the Microsoft StaticFiles NuGet Package.
In the startup class, register a static files folder like this:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseStaticFiles("/Scripts");
app.MapSignalR();
app.UseNancy();
}
}
This way, all files and subfolders in the "Scripts" folder are served as static files. There is also an overload of the UseStaticFiles() function that lets you map a physical path to a virtual path.
Important here: the call to UseNancy() has to be the very last, otherwise everything after it won't work. I also tried to combine it with SignalR, as you can see above, and there the UseNancy() call had to be at the end as well.

Array instead of List in WCF Service Proxy Generated using svcutil.exe

I have a ServiceContract,
using System.Collections.Generic;
using System.ServiceModel;
namespace MainModule.Sub.Communication
{
[ServiceContract]
public interface IWebMethod
{
[OperationContract(IsOneWay = false)]
bool InvokeAlert(List<int> userIds);
[OperationContract(IsOneWay = false, Name = "InvokeAlertByMainID")]
bool InvokeAlert(List<int> userIds, int mainId);
[OperationContract(IsOneWay = true)]
void DeletePopupNotifications(System.Data.DataSet deletedNotifications);
}
}
I used below command to generate proxy (I have to do this using command-line not via Add Service Reference.
SvcUtil.exe http://localhost/MainCommunicationServer/wm /ct:System.Collections.Generic.List`1 /out:HTTPRouterServerProxy.cs
Even I added the ct switch (collectionType) the proxy is Generating it as Array (int[]). How can I do that without using Add Service Reference window in VS
If I remember correctly, the /ct switch may not have any effect (in some circumstances?) on OperationContract-level collections. Try using a wrapper DataContract type, e.g. bool InvokeAlert(InvokeAlertRequest r); where InvokeAlertRequest will be a [DataContract] type containing one [DataMember] List<int> userIds;
The /ct switch stops working if SvcUtil fails to create a proxy that uses the DataContractSerializer and uses the XmlSerializer instead.
This is just a guess but I suspect that System.Data.DataSet might be causing this.

Resources