C# Extension methods in F# - c#

I am trying to use C# extension methods and fluent APIs from F# but I can’t figure out how to do it. The following snippet is from Asp.Net Core RC2 as an example:
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
I can’t figure out how to use APIs like this from F#. If someone has experience working with fluent APIs in F#, maybe they can shine some light on it.

The following translation of the C# 'hello world' example works for me:
open System
open Microsoft.AspNetCore.Builder
open Microsoft.AspNetCore.Hosting
open Microsoft.AspNetCore.Http
type Startup () =
member this.Configure(app: IApplicationBuilder) =
app.Run(fun context -> context.Response.WriteAsync("Hello world!"))
[<EntryPoint>]
let main argv =
let builder = new WebHostBuilder()
let host = builder.UseKestrel().UseStartup<Startup>().Build()
host.Run()
0

Try to add the full AspNetCore package.
Install-Package Microsoft.AspNetCore
You are most likely missing something.

Related

Host.CreateDefaultBuilder vs Host.CreateApplicationBuilder in .NET Platform Extension 7

We generally Create Host using the Host.CreateDefaultBuilder()
Method.
The Host.CreateDefaultBuilder returns an IHostBuilder.
The IHostBuilder has some extension methods by which we can configure the builder. After configuring the IHostBuilder We build the IHost by IHostBuilder.Build().
But on .NET Platform Extension 7, a new method is introduced Host.CreateApplicationBuilder().
It gives us an HostApplicationBuilder instance.
It doesn't have extension methods like IHostBuilder to configure, but it has some properties such as Configuration, Environment, Logging, Services, etc.
And using HostApplicationBuilder.Build() we can eventually Build the IHost.
My question is when and why we should build Host using the HostApplicationBuilder instead of IHostBuilder?
And how to configure srvices, configurations, etc on HostApplicationBuilder, do we need to directly use its properties(Configuration, Environment, Logging, Services, etc)?
I tried searching on google but got no answer.
It is documented a bit here and here.
The general idea was to move away from calbacks and move to linear code for configuring everything
Code samples from the link...
Web
var builder = WebApplication.CreateBuilder();
builder.Logging.AddConsole();
builder.Services.AddOptions<MyOptions>().BindConfiguration("MyConfig");
builder.Services.AddHostedService<MyWorker>();
var app = builder.Build();
app.MapGet("/", () => "Hello World");
app.Run();
Non-Web
var builder = Host.CreateApplicationBuilder();
builder.Logging.AddConsole();
builder.Services.AddOptions<MyOptions>().BindConfiguration("MyConfig");
builder.Services.AddHostedService<MyWorker>();
var host = builder.Build();
host.Run();

Cannot resolve scoped service Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.IViewBufferScope from root provider

I'm trying to use in my ASP.NET Core 2.0 web app this sample RazorViewEngineEmailTemplates to create an html email body from View. But when I run it and my controller gets an ajax request, I get this error:
Cannot resolve scoped service Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.IViewBufferScope from root provider
It's probably coming from resolving dependencies in the RazorViewToStringRenderer class but I have no idea how to fix this.
ok, the problem was I used renderer from a Singleton service (EmailerService). I changed its registration to Scoped and it all works now:
services.AddScoped<IEmailer, EmailerService>();
When a service gets injected as scoped, the dependent class must also be injected as scoped.
Unfortunately, this does not work for every use case. When creating the E-Mail service statically, you don't have an HTTP Context.
In my case, I had a scheduled Task that was executed statically by Hangfire:
var mailer = ServiceProviderSinleton.Instance.GetService(typeof(IEmailer))
When you need that scoped service from a static context, you have two options:
use a dependency injection framework that gives you more control over the injection context. I highly recommend DryIoc.Microsoft.DependencyInjection from NuGet. (Documentation)
disable the scope validation:
return WebHost.CreateDefaultBuilder()
.ConfigureLogging(builder => builder.AddSerilog(Log.Logger, dispose: true))
.UseKestrel(options => options.ConfigureEndpoints(configuration))
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<TStartup>()
.UseSerilog()
.UseDefaultServiceProvider(options => options.ValidateScopes = false)
.Build();

Provide DI container from outside for self hosted .NET Core MVC application

Is it possible to provide configured DI container into the WebHostBuilder ?
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.UseApplicationInsights()
.Build();
host.Start();
I have singleton object running/managing some background jobs. I would like to have it managed via DI container (eg. Autofac), which is exposing management interface via REST API.
My idea is to create DI container outside WebHostBuilder, get from it Singleton, start it's job managment thread and pass it to the WebHostBuilder as a dependency to Controller to expose it via REST Interface.
Is it possible to achieve or my approach is completely wrong ?

Use https with Microsoft.AspNetCore.Server.WebListener

I need to configure a Asp.net core web application with WebListener as server and https procotols. I wasn't able to find any documentation or faqs about that.
My Progam.cs is:
var host = new WebHostBuilder()
.UseWebListener(options => {
})
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseUrls("http://localhost:5001", "https://localhost:5002")
.UseStartup<Startup>()
.Build();
host.Run();
What can I do for configure WebListener in https?
Thanks all in advance!
One way is to bind your SSL certificate to the specific port that your WebListener is listening on, using the netsh command. See How to: Configure a Port with an SSL Certificate for more information on how to do this. After the certificate is bound to the port, you can specify an https url for your WebListener. You can write code to do the netsh part for you (before you start your WebListener), but that probably falls outside the scope of this question.
Enabling https is a lot simpler in Kestrel - any specific reason why you want to use a WebListener? When using Kestrel, you can do the following (there are also several other overrides that you can use, e.g. use cert from store):
new WebHostBuilder().UseKestrel(options => options.UseHttps(#"C:\MyCert.pfx"));
Remember to include the Microsoft.AspNetCore.Server.Kestrel.Https package in your project.json file.
I also found this question on StackOverflow that may help to point you in the right direction.

Specifying the url (port) that a asp.net core 1.0 WebAPI.exe should use in program.cs for both prod and dev

I am doing the following in my asp.net core 1.0 web api (.NET Framework) program.cs to specify which port I want my web api exe to run in for development purposes only:
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.UseUrls(new string[1] { "http://*:12012" })
.Build();
host.Run();
}
However, when I publish to production this line causes the WebAPI to error since I want the exe to use the production web-api url i.e. productionWeb/api/values rather than localhost:12012/values
Is there anyway I can get the best of both worlds being able to specify that I want it to run on port 12012 for development purposes and the production url for prod purposes?
My current solution is to just comment out the line before publishing.
When using IIS you are overwriting the url the IIS (AspNet Core Module) told the app to listen to by calling .UseUrls() after .UseIISIntegration(). You should change the order of these two calls so that .UseIISIntegration() is after .UseUrl(). .UseIISIntegration() will not touch urls you set if you are not running with IIS so in development your application still will be listening on port 12012. When running with IIS .UseIISIntegration() will overwrite the url to listen on the port IIS told it to listen on. I wrote a post on running Asp.NET Core apps with IIS and Azure Websites which explains how things work including this nuance.

Categories