Find out hosting Uri when selfhosting JobHost - c#

I'm trying to self host a JobHost using Microsoft.Azure.WebJobs and including the Http extension but I can't seem to figure out what Uri/port it is hosting on
This is my Main method:
static void Main(string[] args)
{
var config = new JobHostConfiguration();
var filter = new LogCategoryFilter();
filter.DefaultLevel = LogLevel.Trace;
config.LoggerFactory = new LoggerFactory()
.AddConsole(filter.Filter);
var httpExtensionConfiguration = new HttpExtensionConfiguration();
config.UseHttp(httpExtensionConfiguration);
if (config.IsDevelopment)
{
config.UseDevelopmentSettings();
}
var host = new JobHost(config);
host.RunAndBlock();
}
and here is the output window when running

While the HTTP Extension will add the required bindings, services and HTTP features, it does not provide a listener, so it won't setup the host for you (it relies on an external listen you'd need to setup).
With the Azure Functions runtime, the WebHost itself is the listener. The CLI uses that implementation in order to spin up the host and expose HTTP functions. You can see this approach here:
https://github.com/Azure/azure-functions-cli/blob/f0e8121c51569d8d0551fbb9bb81fbed5a9ad64c/src/Azure.Functions.Cli/Actions/HostActions/StartHostAction.cs#L102-L112
You could have a simpler approach if you don't want to rely on the Script WebHost (the CLI leverages many of its features, so it makes sense there) by simply providing your application directly when building the host. You can look at the Startup class provided by the CLI to see how things are registered and configured with the latest bits:
https://github.com/Azure/azure-functions-cli/blob/ff45a85c462c6f1e83e04dcba13da8bcca7099c5/src/Azure.Functions.Cli/Actions/HostActions/StartHostAction.cs#L349-L374
NOTE: The extension version you're using, as well as the code I've shared are pre-release (or not even merged yet), so they're subject to change, but that's the direction we're going.

Related

IDataProtector unable to decrypt when application runs as a service

I'm using ASP.NET Core data protection with default DI behavior. That works fine when my ASP.NET application is hosted on IIS. Now I have an application that needs to run as a service. So I'm using Microsoft.Extensions.Hosting.WindowsServices to do the windows service part with our standard
Host.CreateDefaultBuilder(args)
.UseWindowsService()
The BackgroundService then hosts ASP.NET Core with your standard
var builder = Host.CreateDefaultBuilder()
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddJsonFile("secrets.json", optional: true, reloadOnChange: true);
}
.ConfigureWebHostDefaults(....)
inside the background service, I can then resolve an instance of IDataProtectionProvider, create a protector, and use it to unprotect my secrets
var dataProtectionProvider = Container.Resolve<Microsoft.AspNetCore.DataProtection.IDataProtectionProvider>();
var protector = dataProtectionProvider.CreateProtector(appName);
var decryptedSecret = protector.Unprocect(some secret)
Now that all works fine as long as I run my application from the CLI. But running it as a service (same file, same location, and of course under the same account), I get an 'invalid payload' exception when I call Unprotect.
I know same path and same account is important, so that's taken care of. I also know that the application can find secrets.json as I wrote some probing code that checks if the file is present and can be read before I even try to unprotect. I'm even checking if the string I'm trying to unprotect is null/empty (which it isn't).
I finally installed a debug build as a service and attached the debugger, and when I look at IDataProtectionProvider, it has a Purpose.. and when running as a service, that's c:\windows\system32. When my app runs from the CLI, it's the path to the exe. So, is there a way to specify the purpose on my own so things behave the same regardless of CLI/Service?
So how can I control the purpose?
So having noted the difference in purpose of the IDataProtectionProvider, I was well on my way of solving this. The solution was to set a static purpose as explained here

How can I execute a plugin from a test method?

I've added a test project to my solution where I want to test the integrations, and by that testing the plugins from my local machine. I've added Microsoft.Crm.Tooling.Connector and have a connection to my test instance. But I'm unsure on how and what the configuration and service is set up.
var crm = new CrmServiceClient(crmConnectionString);
crm.OrganizationServiceProxy.EnableProxyTypes();
var service = crm.OrganizationServiceProxy;
var unsecureConfig = "?";
var secureConfig = "?";
var plugin = new ExternalWorkorder_OnCreate(unsecureConfig, secureConfig);
plugin.ExecutePluginLogic(service?);
For executing the plugin, does the configuration matter? As long as i have the IServiceProvider, and how do I get that? Can I get it from CrmServiceClient? Or the OrganizationServiceProxy?
No you do not need t worry about secure and unsecure config.
Look at this article which will connect to dynamics and perform operations as expected.
You don't need the configuration if youre not counting on it in Plugin. But depending on how the plugin code is structured you will need to provide some even empty configuration.
I would recommend using FakeXrmEasy. https://dynamicsvalue.com/home
There are many examples on how to use the library.

Who invoke IHost.Run when using Generic Host Builder in Xamarin.Forms?

I am trying to digest a Xamarin.Forms app (developed by James Montemagno) on which the Generic Host Builder is applied.
The following is the Init method extracted from this line:
public static App Init(Action<HostBuilderContext, IServiceCollection> nativeConfigureServices)
{
// others are removed for simplicity
var host = new HostBuilder()
.ConfigureServices((c, x) =>
{
nativeConfigureServices(c, x);
ConfigureServices(c, x);
})
.ConfigureLogging(l => l.AddConsole(o =>
{
o.DisableColors = true;
}))
.Build();
App.ServiceProvider = host.Services;
return App.ServiceProvider.GetService<App>();
}
Note: Init have not run the host but it will be invoked from Android project as follows:
protected override void OnCreate(Bundle savedInstanceState)
{
// others are removed for simplicity.
LoadApplication(Startup.Init(ConfigureServices));
}
Question
Now if I compare with Asp.net Core, we know that IHost.Run() is invoked in Program.Main. The question is:
Who invokes IHost.Run() in the Xamarin.Forms app above?
From the way I understand it, this setup does not make use of actually running the host. Instead, it just relies to building it to make sure that DI and all the other related services are available and can be used by Xamarin.
Starting a host actually doesn’t do that much with the generic host. It will mostly just start the host lifetime and run hosted services (like the ASP.NET Core application would be).
But in Xamarin, starting the XAML application is something that already works on its own. So it doesn’t need to be “hosted” (although I rather think that we simply cannot have it owned by the host yet).
So this setup just makes use of the host environment to enable DI, configuration and logging, instead of using the host capabilities to actually run things. This also means that with this setup you probably won’t be able to run other hosted services within the application (unless you manage a way to properly start and stop the host within the App).

Google Cloud PubSub V1 using GCloud Emulator

I'm fighting with Google Docs for setting up Cloud PubSub with .NET using a PubSub emulator.
https://cloud.google.com/dotnet/docs/getting-started/using-pub-sub
https://cloud.google.com/pubsub/docs/publisher
https://cloud.google.com/pubsub/docs/emulator
Coming from a Rails background, I'm tasked to implement Cloud PubSub for a .NET product, running our google cloud on .NET Core, to enable it to publish.
Google::Cloud::Pubsub.new(project: project_id, emulator_host: emulator_host)
From the documentation using .NET, I keep coming back to the following:
PublisherServiceApiClient publisherClient = PublisherServiceApiClient.Create();
PublisherClient publisher = PublisherClient.Create(...)
However, the library used from the docs Google.Cloud.PubSub.V1 -Pre
does not contain the definition.
'PublisherClient' does not contain a definition for 'Create'.
Instead, I get CreateAsync that takes in TopicName, PublisherClient.ClientCreationSettings and PublisherClient.Settings.
https://googleapis.github.io/google-cloud-dotnet/docs/Google.Cloud.PubSub.V1/api/Google.Cloud.PubSub.V1.PublisherClient.html
I noticed that PublisherServiceApiClient can take in a Channel, but I'm confused on how to get this going.
To conclude with an actual question, how does one currently implement Cloud PubSub with .NET for in cloud and then locally with emulator? Adding to that, am I using the wrong library or the wrong docs?
Any suggestions, pointers or piece of advice would be truly appreciated.
I managed a solution that I am happy with.
Instead of using the PublisherClient, I went with using the PublisherServiceApiClient alone.
emulatorAddr = Environment.GetEnvironmentVariable("PUBSUB_EMULATOR_HOST");
if (emulatorAddr != null)
{
channel = new Channel(emulatorAddr, ChannelCredentials.Insecure);
pub = PublisherServiceApiClient.Create(channel);
}
else
{
pub = PublisherServiceApiClient.Create();
}
Which meant that publishing was slightly more involved then sending string to the PublisherClient, but overall not so bad.
PubsubMessage msg = new PubsubMessage
{
Data = ByteString.CopyFromUtf8(JsonConvert.SerializeObject(payload))
};
pub.PublishAsync(topic, new[]{ msg });
If the project is running in a Google Compute Engine, it will have default credentials. Otherwise, wether you're running an emulator locally or in docker you can define PUBSUB_EMULATOR_HOST.
What really helped was this https://googleapis.github.io/google-cloud-dotnet/docs/Google.Cloud.PubSub.V1/index.html
To make the PublisherClient connect to a local emulator, you need to pass custom ServiceEndpoint and ChannelCredentials to CreateAsync:
var serviceEndpoint = new ServiceEndpoint(theEmulatorHost, theEmulatorPort);
var publisherClient = await PublisherClient.CreateAsync(
topicName,
new PublisherClient.ClientCreationSettings(credentials: ChannelCredentials.Insecure, serviceEndpoint: serviceEndpoint));
To switch to the real PubSub, just leave away the ClientCreationSettings.
You can use the EmulatorDetection property on the ClientCreationSettings using extension method .WithEmulatorDetection(EmulatorDetection.EmulatorOrProduction). Like this:
PublisherClient publisher = await PublisherClient.CreateAsync(
topicName,
new PublisherClient.ClientCreationSettings()
.WithEmulatorDetection(EmulatorDetection.EmulatorOrProduction));
This will work if you have the following environment variable for the local emulator endpoint: PUBSUB_EMULATOR_HOST=localhost:8085
(If you use Visual Studio you might have to restart VS for the environment variable to be detected)
In windows I had problems using the set PUBSUB_EMULATOR_HOST=localhost:8085 command, so I ended up adding it manually.
Details here: https://cloud.google.com/pubsub/docs/emulator
Extra tip: you can add topics directly to API using curl: curl -X PUT http://localhost:8085/v1/projects/my-project-name/topics/my-topic

ASP.NET 5 / MVC 6 Console Hosted App

In MVC5, I had a console application that would use Microsoft.Owin.Hosting.WebApp.Start(...) to host a bunch of controllers that would be dynamically loaded from assemblies placed in an external folder and run some custom initialization on them via API call. This way I could pass parameters to the initialization method that were determined at runtime (and would not be as clunky as maintaining config files).
In MVC6, the self-hosting is now done, as far as I know, by the DNX runtime using Microsoft.AspNet.Hosting, but this is all done via command line. Is there a way I can self-host from within a C# console application so I can keep this initialization architecture?
...I had a console application that would use Microsoft.Owin.Hosting.WebApp.Start(...) to host [and to] pass parameters to the initialization method that were determined at runtime...
In ASP.NET 4.x we self-host within a console application using an OWIN host. We run our MyApp.exe directly. Its Main() method calls WebApp.Start() to create the OWIN host. We use an instance of an IAppBuilder to build up the HTTP pipeline via appBuilder.Use() and chain it all together with appBuilder.Build(). This is all within the Microsoft.Owin.Hosting namespace.
Is there a way I can self-host from within a C# console application so I can keep this initialization architecture?
In ASP.NET Core rc2 we self-host inside a console application using an IWebHost. (This is not an OWIN host though OWIN inspired it.) We run our MyApp.exe directly. The Main() method creates a new WebHostBuilder(), which we use to build up the HTTP pipeline via webHostBuilder.Use(), chaining it all together with webHostBuilder.Build(). This is all within the Microsoft.AspNet.Hosting namespace.
Regarding Pinpoint's answer, in ASP.NET Core rc1 we need to run dnx.exe instead of running our app directly. The work of the WebHostBuilder is hidden inside the dnx.exe executable. Dnx.exe also starts-up our application. Our application's Main() method calls WebApplication.Run(), after which we use an instance of IApplicationBuilder to add middleware to the HTTP pipeline via calls to appBuilder.Use(). Both our application and dnx.exe shared the responsibility of creating/configuring the host. It's convoluted and I am glad that this changed in rc2. I supposed that in rc1 the equivalent of OWIN's WebApp.Start() is WebApplication.Run().
ASP.NET 4.x ASP.NET Core rc1 ASP.NET Core rc2
N/A Dnx.exe N/A
MyApp.exe MyApp.dll MyApp.exe
Main(args) Main(args) Main(args)
WebApp.Start() WebApplication.Run(args) N/A
appBuilder.Use() appBuilder.Use() webHostBuilder.Use()
appBuilder.Build() N/A webHostBuilder.Build()
Some References
http://www.asp.net/web-api/overview/hosting-aspnet-web-api/use-owin-to-self-host-web-api
https://msdn.microsoft.com/en-us/library/microsoft.owin.hosting.webapp%28v=vs.113%29.aspx
Katana's WebApp static class has been replaced by WebHostBuilder, that offers a much more flexible approach: https://github.com/aspnet/Hosting/blob/dev/src/Microsoft.AspNet.Hosting/WebHostBuilder.cs.
You've probably already used this API without realizing it, as it's the component used by the hosting block when you register a new web command in your project.json (e.g Microsoft.AspNet.Hosting server=Microsoft.AspNet.Server.WebListener server.urls=http://localhost:54540) and run it using dnx (e.g dnx . web):
namespace Microsoft.AspNet.Hosting
{
public class Program
{
private const string HostingIniFile = "Microsoft.AspNet.Hosting.ini";
private const string ConfigFileKey = "config";
private readonly IServiceProvider _serviceProvider;
public Program(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public void Main(string[] args)
{
// Allow the location of the ini file to be specified via a --config command line arg
var tempBuilder = new ConfigurationBuilder().AddCommandLine(args);
var tempConfig = tempBuilder.Build();
var configFilePath = tempConfig[ConfigFileKey] ?? HostingIniFile;
var appBasePath = _serviceProvider.GetRequiredService<IApplicationEnvironment>().ApplicationBasePath;
var builder = new ConfigurationBuilder(appBasePath);
builder.AddIniFile(configFilePath, optional: true);
builder.AddEnvironmentVariables();
builder.AddCommandLine(args);
var config = builder.Build();
var host = new WebHostBuilder(_serviceProvider, config).Build();
using (host.Start())
{
Console.WriteLine("Started");
var appShutdownService = host.ApplicationServices.GetRequiredService<IApplicationShutdown>();
Console.CancelKeyPress += (sender, eventArgs) =>
{
appShutdownService.RequestShutdown();
// Don't terminate the process immediately, wait for the Main thread to exit gracefully.
eventArgs.Cancel = true;
};
appShutdownService.ShutdownRequested.WaitHandle.WaitOne();
}
}
}
}
https://github.com/aspnet/Hosting/blob/dev/src/Microsoft.AspNet.Hosting/Program.cs

Categories