ConnectorStore changes in Bot Builder SDK 3.5.5? - c#

I’m upgrading Bot Builder SDK for our bot from 3.5.0 to 3.5.5 due to LUIS endpoint being deprecated in few weeks and it seems like latest SDK version has a way to specify ‘LuisApiVersion’.
During upgrade, I’m getting following error while modifying the behavior to use LastWriteWins policy for CachingBotDataStoreConsistencyPolicy:
Exception thrown:
'Autofac.Core.Registration.ComponentNotRegisteredException' in autofac.dll
Additional information: The requested service 'Microsoft.Bot.Builder.Dialogs.Internals.ConnectorStore' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.
builder.Register(c => new CachingBotDataStore(c.Resolve<ConnectorStore>(),
CachingBotDataStoreConsistencyPolicy.LastWriteWins)
.As<IBotDataStore<BotData>>()
.AsSelf()
.InstancePerLifetimeScope();
This code has worked for 3.5.0, but I’m not sure what’s the best way to handle the Autofac error that we are getting with 3.5.5. Any pointers or idea about this?

The registration of ConnectorStore has changed as you can see here.
To solve the issue you should change the c.Resolve<ConnectorStore>() in the your code to c.ResolveKeyed<IBotDataStore<BotData>>(typeof(ConnectorStore))

Related

What does AddEntityFrameworkStores exactly do in AddIdentity?

I recently needed to Generate Email Confirmation Token for my .net core 5 app, and while researching I found out I need to register "AddIdentity" at startup.
services.AddIdentity<AuthenticatedUser, IdentityRole>(options =>
{
options.User.RequireUniqueEmail = false;
}).
AddEntityFrameworkStores<SchoolDataContext>().
AddDefaultTokenProviders();
If I remove 'AddEntityFrameworkStores' piece, then application builds and starts but crashes at runtime with similar errors like in following:
Error:
System.AggregateException: 'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory1[WebApp1.Areas.Identity.Data.ApplicationUser] Lifetime: Scoped ImplementationType: WebApp1.Areas.Identity.Data.AdditionalUserClaimsPrincipalFactory': Unable to resolve service for type 'Microsoft.AspNetCore.Identity.UserManager1[WebApp1.Areas.Identity.Data.ApplicationUser]' while attempting to activate 'WebApp1.Areas.Identity.Data.AdditionalUserClaimsPrincipalFactory'.)'
My question is why we even need to register "AddEntityFrameworkStores", I could not found a good documentation or source code implementation of it. Can't we just avoid to use it, or any idea why we need it at first place?
Here's the source code.
Basically it adds default Stores: UserStore and RoleStore. If you don't use it you have to provide Stores yourself with AddUserStore and AddRoleStore.

Implemented custom data storage, bot still calls state.botframework.com

Summary:
We implemented TableBotDataStore in our C# Bot, but somehow the bot is still making calls to the deprecated State API.
Context:
In Application Insights I can see that our bot is making and a lot of calls to state.botframework.com. I also noticed that our production environment get's 200 responses on those requests, but our new Web App Bot is getting a 405 (Method Not Allowed) on all those request.
When we started developing the bot (May, 2018) we implemented the Azure Table Storage right away. So I was quite surprised to find that our bot is still calling state.botframework.com.
This blogpost by MS states:
Read options will continue to be available through July 31st 2018
My assumption is that MS still allows requests to the State API for bots that were registered before a certain date.
What I tried:
I have already followed Microsoft's guide on how to Manage custom state data with Azure Table Storage for .NET. I also read the related question Migrated bot state provider but calls to state.botframework.com are still being made but it doesn't help me.
My code:
Conversation.UpdateContainer(
builder =>
{
builder.RegisterModule(new AzureModule(Assembly.GetExecutingAssembly()));
var store = new
TableBotDataStore(ConfigurationManager.AppSettings["AzureWebJobsStorage"]);
builder.Register(c => store)
.Keyed<IBotDataStore<BotData>>(AzureModule.Key_DataStore)
.AsSelf()
.SingleInstance();
builder.Register(c => new CachingBotDataStore(store,
CachingBotDataStoreConsistencyPolicy
.ETagBasedConsistency))
.As<IBotDataStore<BotData>>()
.AsSelf()
.InstancePerLifetimeScope();
});
GlobalConfiguration.Configure(WebApiConfig.Register);
What I expect:
With this configuration, I expect that our bot only uses the TableBotDataStore and doesn't make any calls to the deprecated State API.

How to resolve service for type 'IdentityServer4.EntityFramework.Options.OperationalStoreOptions'

I created a aspnet core web application and installed IdentityServer4 and IdentityServer4.EntityFramework packages to use database storage for Client and Resources configuration instead of inMemory. However when I add the ConfigurationDbContext and PersistedGrantDbContext in the services collection as shown in the image below
I get an exception saying "Unable to resolve service for type 'IdentityServer4.EntityFramework.Options.OperationalStoreOptions' while attempting to activate 'IdentityServer4.EntityFramework.DbContexts.PersistedGrantDbContext'."
as seen in the commandline screenshot below
How do I fix the exception being thrown
I have resole this error by adding below lines in StartUp.cs file
public void ConfigureServices(IServiceCollection services)
{
var storeOptions = new ConfigurationStoreOptions();
services.AddSingleton(storeOptions);
}
Hope that will helps you also
How to solve this issue
Firstly I removed the DbContexts that I was adding manually which is from line 49 to 53, in the first screenshot.
Secondly I made a mistake when adding the .AddSigningCredentials() loading the certificate I am supposed to use the IHostingEnvironment to get the ContentRootPath to my certificate. Therefore change .AddSigningCredentials(..) to:
.AddSigningCredential(new X509Certificate2(Path.Combine(_environment.ContentRootPath,
"sample-cert.pfx"), "password")
Add thats how I solved the exception being thrown and processed the migrations I wanted to.

MobileServiceTable.InsertAsync ZUMO-API-VERSION Error

I'm trying to migration Azure Mobile Service to Azure App Services. In C# I'm using MobileServiceClient.GetTable to get a MobileServiceTable object. With this I try to insert an object using MobileServiceTable.InsertAsync.
After upgrading I am getting the error-
An invalid API version was specified in the request, this request needs to specify a ZUMO-API-VERSION of 2.0.0
I understand the error, but I don't know how to update the request headers to add this. Is this possible?
You need to update the SDK. Remove the WindowsAzure.MobileServices SDK and add the Microsoft.Azure.Mobile.Client SDK. If you use offline-sync, then replace the equivalent SQLiteStore packages as well.
For more information, see https://learn.microsoft.com/en-us/azure/app-service-mobile/app-service-mobile-net-upgrading-from-mobile-services

ASP.NET MVC 5 + Owin + SimpleInjector

A new asp.net mvc project using owin, webapi, mvc and DI (SimpleInjector) runs fine if I remove the DI lib from the project. However, once introduced, the app blows up when registering the OWIN components for DI. The OWIN startup configuration is being hit and runs without error, but when it comes time to register the dependencies (listed below) I receive the following error:
An exception of type 'System.InvalidOperationException' occurred in Microsoft.Owin.Host.SystemWeb.dll but was not handled in user code
Additional information: No owin.Environment item was found in the context.
SimpleInjector Registration Code:
container.RegisterPerWebRequest<IUserStore<ApplicationUser>>(() => new UserStore<ApplicationUser>());
container.RegisterPerWebRequest<HttpContextBase>(() => new HttpContextWrapper(HttpContext.Current));
// app fails on call to line below...
container.RegisterPerWebRequest(() => container.GetInstance<HttpContextBase>().GetOwinContext());
container.RegisterPerWebRequest(() => container.GetInstance<IOwinContext>().Authentication);
container.RegisterPerWebRequest<DbContext, ApplicationDbContext>();
Update - Full Stack Trace
at
System.Web.HttpContextBaseExtensions.GetOwinContext(HttpContextBase
context) at
WebApplication1.App_Start.SimpleInjectorInitializer.<>c__DisplayClass6.b__2()
in
b:\temp\WebApplication1\WebApplication1\App_Start\SimpleInjectorInitializer.cs:line
41 at lambda_method(Closure ) at
SimpleInjector.Scope.CreateAndCacheInstance[TService,TImplementation](ScopedRegistration2
registration) at
SimpleInjector.Scope.GetInstance[TService,TImplementation](ScopedRegistration2
registration) at
SimpleInjector.Scope.GetInstance[TService,TImplementation](ScopedRegistration2
registration, Scope scope) at
SimpleInjector.Advanced.Internal.LazyScopedRegistration2.GetInstance(Scope
scope) at lambda_method(Closure ) at
SimpleInjector.InstanceProducer.GetInstance()
I think the exception is thrown when you call Verify(). Probably at that line, but only when the delegate is called.
Simple Injector allows making registrations in any order and will therefore not verify the existence and correctness of a registration’s dependencies. This verification is done the very first time an instance is requested, or can be triggered by calling .Verify() at the end of the registration process.
I suspect you're registrering the OwinContext only because you need it for getting the IAuthenticationManager.
The problem you face is that the OwinContext is only available when there is a HttpContext. This context is not available at the time the application is build in the composition root. What you need is a delegate which checks the stage of the application and returns a component that matches this stage. You could that by registering the IAuthenticationManager as:
container.RegisterPerWebRequest<IAuthenticationManager>(() =>
AdvancedExtensions.IsVerifying(container)
? new OwinContext(new Dictionary<string, object>()).Authentication
: HttpContext.Current.GetOwinContext().Authentication);
The delegate will return the Owin controlled IAuthenticationManager when the code runs at 'normal runtime stage' and there is a HttpContext.
But when making an explicit call the Verify() (which is highly advisable to do!) at the end of registration process there is no HttpContext. Therefore we will create a new OwinContext during verifying the container and return the Authentication component from this newly created OwinContext. But only if the container is indeed verifying!
A full and detailed description can be read here as already mentioned in the comments.
Although the question is different, the answer is the same as my answer here.
The problem is that you are injecting HttpContextWrapper into your application and attempting to use its members during application initialization, but at that point in the application lifecycle, HttpContext is not yet available. HttpContext contains runtime state, and it does not make sense to initialize an application within one specific user's context.
To get around this problem, you should use one or more Abstract Factories to access HttpContext at runtime (when it is available) rather than at application initialization, and inject the factories into your services with DI.
Using Ric .Net's answer might work, too, but it will throw an exception every time the application is initialized.
The answer of 'Ric .Net' has pointed me in right direction, but to allow changes to new SimpleInjector, have to change the code as below (as RegisterPerWebRequest is obselete):
container.Register<IAuthenticationManager>(() => AdvancedExtensions.IsVerifying(container)
? new OwinContext(new Dictionary<string, object>()).Authentication
: HttpContext.Current.GetOwinContext().Authentication, Lifestyle.Scoped);
Also, have to add below two registrations to the container, to allow 'container.Verify()' to work correctly:
container.Register<ApplicationUserManager>(Lifestyle.Scoped);
container.Register<ApplicationSignInManager>(Lifestyle.Scoped);

Categories