How can I resolve a dependency on something on the current request? - ninject

I'm setting up dependency injection in my ASP.NET Web API application. I have a scenario where a dependency has a dependency on something on the current request (the hostname, for example).
So how can I use the current request as a dependency?
Below is what I've been able to come up with, but HttpContext.Current won't work in a self-hosted scenario.
kernel.Bind<IFoo>()
.ToMethod((context) =>
{
string hostName = HttpContext.Current.Request.Url.Host;
var foo = FooFactory.GetByHostName(hostName);
return foo;
})
.InRequestScope();
I'm currently using Ninject, but I can switch to a different IoC container if there's one that can handle this scenario better.

Related

OpenTelemetry .NET HttpClient not propagating TraceId

I am trying to get Tracing using OpenTelemetry to work with HttpClient in an integration test for an Asp.NET API.
Tracing works for everything else, we get traces from the API controllers and all other instrumented libraries.
Configuration looks like this:
webApplicationBuilder.Services.AddOpenTelemetryTracing(b =>
b.SetResourceBuilder(resourceBuilder)
.AddHttpClientInstrumentation()
.AddAspNetCoreInstrumentation()
.AddProtoActorInstrumentation()
.AddRedisInstrumentation()
.AddOtlpExporter(options =>
{
ConfigureOpenTelemetry(webApplicationBuilder, options);
})
);
But when calling the API using HttpClient. the current TraceId is not propagated.
The integration test uses a MyAppFactory : WebApplicationFactory<Program> for the test.
And the HttpClient is constructed in the tests using the factory.CreateClient() of the MyAppFactory.
If I check the Activity.Current.TraceId inside my integration test. I get one value.
Then directly after, when I call the API using the HttpClient, the API controller reports a different TraceId.
There are also no w3c trace context headers in the Request inside the controller method.
What am I missing here?

How do you setup a TestHost for a Blazor App to test routing?

I want to test if the right controller and routing information is being processed in my blazor server-side app which hosts 2 client apps. Microsoft.AspNetCore.TestHost.TestServer is the equivalent to what I think is needed for this. It accepts IWebHostBuilder, IServiceProvider, IFeatureCollection. Perhaps one of the constructors would at least enable me to test the local controllers that Program.cs adds with
app.UseEndpoints(ep => {
ep.MapControllers();
ep.MapRazorPages();
ep.MapFallbackToFile(appSegment + "/{*path:nonfile}", $"{appSegment}/index.html");
});
Is there a current way to test Blazor App routing for debugging and diagnostics?

HttpClient as singleton in dotnet core

On the full framework there was a pattern that came out making HttpClient a singleton. This is because the existing connections could be reused, however on the full framework there were dns caching issues when doing this. Mostly when you would run httpclient as a singleton on the full framework it would cache the dns results, and you would have to use ServicePointManager to force it to refresh once in a while.
Now dotnet core LTS currently does not have ServicePointManager, so my question is. Can you run HttpClient as a singleton in dotnet core and have it respect DNS updates?
I am quoting a post from the link below
"Unfortunately, there's no way to do this with .NET Core today.
Either ServicePointManager should be brought over to .NET Core or similar equivalent functionality should be enabled some other way."
Here is the link that might be worth checking: https://github.com/dotnet/corefx/issues/11224
I'm also using HTTPClient as a singleton and injecting it into the controllers in my .NET Core APIs.
I can confirm that ServicePointManager exists in .NET Core Runtime 2.0.5.
I'm using the following, after I've created the request to solve DNS issues.
Uri vRequestUri = new Uri ("https:api.example.com/....");
HttpRequestMessage vRequest = new HttpRequestMessage (HttpMethod.Post, vRequestUri);
ServicePoint vSP = ServicePointManager.FindServicePoint (vRequest.RequestUri);
vSP.ConnectionLeaseTimeout = 60 * 1000; // 1 Minute
For those who are not aware of the DNS problem, the following article would be informative http://byterot.blogspot.com.tr/2016/07/singleton-httpclient-dns.html
I have done it using the new SocketsHttpHandler
var handler = new SocketsHttpHandler()
{
ConnectTimeout = TimeSpan.FromMinutes(1),
PooledConnectionLifetime = TimeSpan.FromMinutes(5) //https://github.com/dotnet/corefx/issues/26331
};
var client = new HttpClient(handler){};
This should be fixed in dotnet core 2.1, currently available in preview.

ServiceStack - prevent unauthorized access to static files

I understand there is more than one way of handling service authentication/authorization, but I cannot make it work for static files.
Is there a way of configuring the behavior to be the same as with services; if not authenticated a request to index.html should redirect to login page the same as a request to secured dto/service.
I am currently looking into RawHttpHandlers but since it is too early in the pipeline how do I get the authentication setup in the apphost config?
thanks in advance
Gjergji
You would have to use IAppHost.RawHttpHandlers because that's the only custom handler in ServiceStack's Request Pipeline that gets executed before the built-in static file handling is accessed.
But you should still be able to access the Users Session with the available extension methods, e.g:
this.RawHttpHandlers.Add(httpReq =>
{
var isStaticFileRequest = httpReq.PathInfo.StartsWith("/static");
if (isStaticFileRequest)
{
var session = httpReq.GetSession();
if (!session.HasRole("TheRole"))
return new ForbiddenHttpHandler();
}
return null;
});
This handler simply checks if it's a request for a static file, in this case the path info starts with /static, and if is checks the user session if they have the required role, if not it returns a Forbidden request, otherwise it returns null to tell ServiceStack to continue executing the request.
Note: if it's needed you can access any registered dependency from outside of ServiceStack with HostContext.Resolve, e.g:
var authRepo = HostContext.Resolve<IAuthRepository>();

Share a Kernel between WebAPI and MVC

I've got a simple MVC4 site which uses ASP.NET webAPI and also MVC pages.
I'd like to use Ninject DI for both controller types but I'm wondering how this can be done?
I've got Ninject DI working for WebAPI, but now not sure how to share the same Kernel elegantly.
Should I be using some sort of Kernel singleton which both Dependency Resolvers can refer to?
Anyone had any experience with this?
Cheers.
You should use the same IKernel instance for a single application-level composition root, may be WebApi or MVC controllers.
If you are using Ninject.MVC3 package:
When the kernel is initialized in NinjectWebCommon.cs inside your App_Start folder, you already have access to it. For MVC controllers, you don't need to do anything else for Ninject DI to work.
But for WebAPI controllers, you need to use a DependencyResolver to inject dependencies into your controllers. Using this implementation for this resolver, you then set it to be the resolver for all your WebAPI controllers like this:
Bind the NinjectDependencyResolver to self (optional), inside RegisterServices in NinjectWebCommon.cs:
kernel.Bind<NinjectDependencyResolver>().ToSelf();
Set the WepAPI configuration to use your Resolver, usually inside WebApiConfig.cs:
public static void Register(HttpConfiguration config)
{
//Other initialization code
config.DependencyResolver = (new Bootstrapper()).Kernel.Get<NinjectDependencyResolver>();
}
This will fit your scenario for all controllers sharing the same IKernel.
Hope that helps!
Yes, you are right. There should be one kernel/ container for an application, because this will eleminate possible mistakes in the future.In case of multiple kernels, you may register an interface in a kernel, and then try to resolve it using another kernel, and the program crashes.Only After spending time debugging, you find out what was wrong,etc.
In addition, using a single kernel, you wouldn't have to register a same implementation multiple times.