Configuring bot without .bot file - botframework

Is there any way to configure a bot in the new Microsoft Bot Framework v4 without the .bot file?
I want to do this programatically and I cannot find this in the samples.

The appsettings.json points to the bot file like this:
{
"botFilePath": "BotConfiguration.bot",
"botFileSecret": ""
}
then in the startup.cs this happens:
var secretKey = Configuration.GetSection("botFileSecret")?.Value;
var botFilePath = Configuration.GetSection("botFilePath")?.Value;
// Loads .bot configuration file and adds a singleton that your Bot can access through dependency injection.
var botConfig = BotConfiguration.Load(botFilePath ?? #".\BotConfiguration.bot", secretKey);
services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot config file could not be loaded. ({botConfig})"));
// Retrieve current endpoint.
var environment = _isProduction ? "production" : "development";
var service = botConfig.Services.Where(s => s.Type == "endpoint" && s.Name == environment).FirstOrDefault();
You will need to make changes to this if you wish to handle things without a .bot file.

Related

MassTransit riders Add ability to dynamically connect endpoints

I would like to configure Add bus rider dynamically into a class not into startup.
Working well with RabbitMQ.
But I don't know how to Add Rider to my bus.
private IBusControl ConfigureBus()
{
var massTransitSection = this.configuration.GetSection("MassTransit");
var url = massTransitSection.GetValue<string>("Url");
var host = massTransitSection.GetValue<string>("Host");
var userName = massTransitSection.GetValue<string>("UserName");
var password = massTransitSection.GetValue<string>("Password");
var busControl =
Bus.Factory.CreateUsingRabbitMq(cfg =>
{
cfg.Host($"rabbitmq://{url}/{host}", configurator =>
{
configurator.Username(userName);
configurator.Password(password);
});
cfg.PublishTopology.BrokerTopologyOptions = PublishBrokerTopologyOptions.MaintainHierarchy;
});
busControl.StartAsync();
return busControl;
}
Thx a lot for your help
Riders cannot be connected after the bus has been configured. Topic endpoints are also not able to be connected after the bus has been configured.

DryIoC register configuration

I am working on a Xamarin project with Prism and DryIoC.
Currently I am setting up some custom environment-specific configuration, however I am struggling with the IoC syntax for this.
I have the following code as part of my App.xaml.cs:
private void SetConfiguration(IContainerRegistry containerRegistry)
{
// Get and deserialize config.json file from Configuration folder.
var embeddedResourceStream = Assembly.GetAssembly(typeof(IConfiguration)).GetManifestResourceStream("MyVismaMobile.Configurations.Configuration.config.json");
if (embeddedResourceStream == null)
return;
using (var streamReader = new StreamReader(embeddedResourceStream))
{
var jsonString = streamReader.ReadToEnd();
var configuration = JsonConvert.DeserializeObject<Configuration.Configuration>(jsonString);
What to do with configuration, in order to DI it?
}
What should I do with the configuration variable to inject it?
I have tried the following:
containerRegistry.RegisterSingleton<IConfiguration, Configuration>(c => configuration);
containerRegistry.Register<IConfiguration, Configuration>(c => configuration));
But the syntax is wrong with dryIoC.
RegisterSingleton and Register are meant for registering types where the container will then create the instances. You have your instance already, so you use
containerRegistry.RegisterInstance<IConfiguration>( configuration );
Instances are always singleton, obviously, so there's only no separate RegisterInstanceSingleton...

How to implement versioning for Token endpoint in Web API 2

I have a Asp.Net Web API 2 using Token based authentication (OAuth2).
I have implemented Web API versioning using aspnet-api-versioning.
So now I have three different versions of my API. It's really great, I can now change V3 without affecting the current API.
But the /token endpoint is not versioned because it is not in my controller. It's in the Providers.
I searched but couldn't find anything helpful.
We can register more than one token endpoint in the Startup.Auth.cs
So here's what I did:
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(TokenExpirationInDays),
AllowInsecureHttp = true, //Allow HTTP to send username password.
};
app.UseOAuthBearerTokens(OAuthOptions);
OAuthOptionsV3 = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/api/V3/Accounts/Token"),
Provider = new ApplicationOAuthProvider2(PublicClientId),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(TokenExpirationInDays),
AllowInsecureHttp = true, //Allow HTTP to send username password.
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptionsV3);
So now I have different token endpoint for each version.
I'm not familiar with this particular setup, but this looks like middleware. There isn't quite enough information here to provide you with a specific answer, but your goals should be achievable in one of a few ways:
Option 1 - Use the Conventions API
If you authorization endpoint is actually a controller (though I think it is not), you can use the Conventions API like so:
services.AddApiVersioning(options =>
{
options.Conventions.Controller<OAuthController>().IsApiVersionNeutral();
}
Conventions was specifically meant to deal with a scenario where a controller might be externally defined and you don't have any control over the source code.
Option 2 - Use a Custom Convention
Middleware could create actions dynamically. As long as actions are actually produced, then you can use a custom IControllerConvention. You would be passed the ControllerModel which contains the actions you need to version. Assuming this is the correct behavior, you'd be looking for matching actions in the source model and then you can apply it to the controller conventions with something like:
public class MyConventions : IControllerConvention
{
public bool Apply(IControllerConventionBuilder controller, ControllerModel controllerModel)
{
var method = // TODO: resolve the target method from controllerModel
if (method == null)
{
return false;
}
controller.Action(method).IsApiVersionNeutral();
return false;
}
}
Option 3 - In Middleware
If this is pure middleware, API versioning isn't directly supported there. You can, however, support versioning on your own if the pipeline is composed properly. Specifically, API Versioning must come before other parts of middleware that need it. This usually happens automatically, but if you need to control registration, you need to change your setup to handle it manually like this:
services.AddApiVersioning(options => options.RegisterMiddleware = false);
// ... inside application setup
services.UseApiVersioning();
The API Versioning middleware doesn't really do much of anything special. It merely adds a pipeline feature. As long as that's before your other middleware, it will be available downstream like this:
var feature = context.Features.Get<IApiVersioningFeature>();
// the raw, unparsed API version, if any
var rawApiVersion = feature.RawApiVersion;
// the parse API version; will be null if no version is specified
// or the value cannot be parsed
var apiVersion = feature.ApiVersion;
// TODO: enforce versioning policies within the middleware
Option 4 - Use the API Explorer
If none of the previous approaches will work for you, you can leverage the API Explorer extensions for API Versioning to build your configuration (as above) from discovered APIs. This would have the advantage of not being hardcoded or require changes every time you release a new version.
Your application startup configuration would change to something like this:
public void Configure(IApplicationBuilder app, IApiVersionDescriptionProvider provider)
{
foreach (var description in provider.ApiVersionDescriptions)
{
var options = new OAuthAuthorizationServerOptions()
{
TokenEndpointPath = new PathString($"/api/{description.GroupName}/Accounts/Token"),
Provider = new ApplicationOAuthProvider2(PublicClientId),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(TokenExpirationInDays),
AllowInsecureHttp = true,
};
app.UseOAuthBearerTokens(options);
}
}

Trying to set up Orleans Cluster membership with Consul

I'm trying to use an existing Consul cluster as the membership provider for a test Orleans application.
I get this error when connecting my client app to the Silo
Could not find any gateway in Orleans.Runtime.Host.ConsulBasedMembershipTable. Orleans client cannot initialize.
Digging into the ConsulUtils class, the entries being retrieved have no ProxyPort defined - and are discarded - hence the empty result set.
I initialize the silo like this:
var clusterConfiguration = new ClusterConfiguration();
clusterConfiguration.Globals.DataConnectionString = "http://localhost:8500";
clusterConfiguration.Globals.DeploymentId = "OrleansPlayground";
clusterConfiguration.Globals.LivenessType = GlobalConfiguration.LivenessProviderType.Custom;
clusterConfiguration.Globals.MembershipTableAssembly = "OrleansConsulUtils";
clusterConfiguration.Globals.ReminderServiceType = GlobalConfiguration.ReminderServiceProviderType.Disabled;
var silohost = new SiloHost("Fred", clusterConfiguration);
silohost.InitializeOrleansSilo();
startup = Task.Factory.StartNew(() =>
{
return silohost.StartOrleansSilo();
});
return true;
And I set my client app up like this:
var config = new ClientConfiguration();
config.CustomGatewayProviderAssemblyName = "OrleansConsulUtils";
config.DataConnectionString = "http://localhost:8500";
config.DeploymentId = "OrleansPlayground";
config.GatewayProvider = ClientConfiguration.GatewayProviderType.Custom;
GrainClient.Initialize(config);
Looking at the code in ConsulUtils I can see that the ProxyPort isn't set (i.e. is 0) when the entry is saved. So I'm assuming I have a problem when initializing the silo - but I can't figure out what it is!
Without digging deep in, does sound like a bug. Please repost on GitHub and we will try to help you.

Protecting webapi with IdentityServer and Autofac - can't get claims

I'm trying to protect my webapi with IdentityServer and OpenID Connect using Autofac. I'm using OWIN. But for some reason I can't get claims of the user. It seems that AccessTokenValidation is not triggered at all. That makes me think there is something wrong in the order of my declarations at my startup. Here is my startup.
public class Startup {
public void Configuration(IAppBuilder appBuilder) {
// Add authentication
this.AddAuthentication(appBuilder);
HttpConfiguration config = new HttpConfiguration();
var container = CreateAutofacContainer();
var resolver = new AutofacWebApiDependencyResolver(container);
config.DependencyResolver = resolver;
WebApiConfig.Register(config);
config.EnsureInitialized();
// Register config - you can't add anything to pipeline after this
appBuilder.UseAutofacMiddleware(container);
appBuilder.UseAutofacWebApi(config);
appBuilder.UseWebApi(config);
}
private static IContainer CreateAutofacContainer() {
var autofacBuilder = new ContainerBuilder();
var assembly = Assembly.GetExecutingAssembly();
// Register your Web API controllers.
autofacBuilder.RegisterApiControllers(assembly);
// For general logging implementation
autofacBuilder.RegisterType<ConsoleLogger>().As<ILogger>();
// Create empty usage context to be filled in OWIN pipeline
IUsageContext usageContext = new RuntimeUsageContext();
autofacBuilder.RegisterInstance(usageContext).As<IUsageContext>().SingleInstance();
// We need to get usage context builded
autofacBuilder.RegisterType<OIDCUsageContextProvider>().InstancePerRequest();
var container = autofacBuilder.Build();
return container;
}
private void AddAuthentication(IAppBuilder app) {
var options = new IdentityServerBearerTokenAuthenticationOptions();
options.Authority = "MYAUTHORITY";
options.RequiredScopes = new[] { "openid", "profile", "email", "api" };
options.ValidationMode = ValidationMode.ValidationEndpoint;
app.UseIdentityServerBearerTokenAuthentication(options);
// Add local claims if needed
app.UseClaimsTransformation(incoming => {
// either add claims to incoming, or create new principal
var appPrincipal = new ClaimsPrincipal(incoming);
// incoming.Identities.First().AddClaim(new Claim("appSpecific", "some_value"));
return Task.FromResult(appPrincipal);
});
}
I'm using hybrid flow and api is called from SPA-application. I've verified (by calling my identity server's endpoint directly) that access token is valid and there are claims available. I also downloaded IdentityServer.AccessTokenValidation project and attached it as a reference. When I set some breakpoints to methods in that project, they never get called. That is why I think there is something wrong with my startup and OWIN pipeline.
I've declared UsageContext in my startup. It is a class I'm using to collect claims and some configuration settings - to be injected to actual controllers. I think it would be nice way to handle this, so in controllers there is always valid UsageContext available.
I've read a lot of samples and examples but still haven't found exactly same situation. I'll appreciate any attempts to point me into right direction.
Regards,
Borre
Could it be your registration of UsageContext as a Singleton? You mention this class contains claims, so this object should be resolved once pr http request - shouldn't it?
It turned out that there was some mysterious line in AccessTokenValidation - library that didn't work. I use that library to get claims. After changing the line everything seemed to work.
So basically my question is closed now and stuff works. But I'm still not totally convinced this is the right way to do this.
Thanks John for your comments!

Resources