HttpSelfHostServer and HttpContext.Current - c#

I'm working on a self-hosted ASP.NET web api-application.
Everything works fine, but now I'm struggling with HttpContext:
I need to save session-informations from the client.
But HttpContext.Current is always null.
So it's obvious that my HttpSelfHostServer don't work with the static HttpContext-Class.
The thing I don't understand is: why..?
And I can't figure out a way to tell neither HtttpSelfHostServer nor HttpSelfHostConfiguration to work with HttpContext.
Here's what I'm doing:
Creating a HttpSelfHostConfiguration
1.1 Adding Service-Resolvers & Routes
1.2 Adding custom UserNamePassword-Validator
create new Instance of HttpSelfHostServer with the config
2.1 server.OpenAsync().Wait()
Any help how I can tell my server to work with HttpContext.Current is greatly appreciated!
Cheers!

You won't be able to use HttpContext in a self-hosted environment. HttpContext is set by the ASP.Net pipeline, which you won't have if you don't run under IIS/ASP.Net.
The HttpContext is only available in the Web-Hosting mode, in which the HttpControllerHandler creates the request.
FYI- I invite you to read the following great articles from Pedro Felix to better understand the different hosting models:
HTTP processing architecture overview
Web-hosting
Self-hosting

To get around this problem (I find I am using a lot of components these days that need to work equally well in Web API and MVC), you can try this old shim I wrote to give you back an HttpContext-like interface that works in both flavours. It's on NuGet also, here's the source:
Link on github
(or Link on Nuget)

Related

Azure fluent management api bind custom root domain to app service

I've been having trouble with this for a while and now I really need help.
This is the code I am currently using to bind a custom subdomain to Azure and everything is working just fine:
var appService = await azure.AppServices.WebApps.GetByIdAsync(
"subscription-id");
await appService.Update().DefineHostnameBinding()
.WithThirdPartyDomain("mydomain.net")
.WithSubDomain("www")
.WithDnsRecordType(CustomHostNameDnsRecordType.CName)
.Attach()
.ApplyAsync();
So what will be the way to bind just mydomain.net except that CustomHostNameDnsRecordType.CName should be changed with CustomHostNameDnsRecordType.A because Azure does not support CNAME records for root domains?
I cannot skip the WithSubDomain(string) method. Tried passing and null/empty string/space or just . but the response from Azure for null is Object reference not set to an instance and for the others is Bad Request.
P.S. I know that I am using an old SDK which is in maintenance mode but the new ones are still in beta or even alpha and there is still no support for App Services so I have to stick with that.
#DeepDave-MT pointed me to the correct answer in a comment under my question even though it's ridiculous. I am now quite sure I will go with this fluent API because there are too many things that are bothering me, almost no documentation, bad error handling and so on. Anyway, this is how to add a root domain in Azure using the so called fluent management API:
await appService.Update().DefineHostnameBinding()
.WithThirdPartyDomain("mydomain.net")
.WithSubDomain("#")
.WithDnsRecordType(CustomHostNameDnsRecordType.A)
.Attach()
.ApplyAsync();
P.S. I don't know why I don't have the habit to check for issues in GitHub.

Generating links to self when running behind reverse proxy

How can I generate absolute links to other resources in my RESTful API app when the app is meant to be accessed via a reverse proxy that publishes just the paths under /api?
My app is an API with a common layout of routes like /api, /swagger and /health. It is published on my employer's API management under a path of the form /business-area/api-name/v1. Calling the API both directly and through the API gateway overall works: calling https://api-gateway.company.com/business-area/api-name/v1/some-resource results in internal call to https://my-app.company.com/api/some-resource.
The issue is that the links in my app's responses point directly to the backend app (https://my-app.company.com/api/another-resource), not the the API gateway (https://api-gateway.company.com/business-area/api-name/v1/another-resource). They are generated using IUrlHelper.
I solved the domain by the ForwardedHeadersMiddleware and adding the X-Forwarded-Host by a policy on the API management. Sadly, we are allowed to use just extremely simple policies, so if we published the API using multiple gateways, the current solution would generate link to just a single one. But that is an issue to be solved somewhen later; now it works OK.
I could not get the path to work well. I tried changing the paths using a middleware as hinted in the ASP.NET Core behind proxy docs:
app.Use((context, next) =>
{
context.Request.PathBase = "/business-area/api-name/v1";
if (context.Request.Path.StartsWithSegments("/api", out var remainder))
{
context.Request.Path = remainder;
}
return next();
});
When I insert this middleware high in the pipeline, it breaks the routing, but if I insert it low enough, the routing works OK and only link generation is affected. But it seems that only PathBase change really affects link generation as the /api is still in the generated URI. I can see that the Path of the request object is really changed, though, so it is probably just that link generation uses the routing info directly, without passing through my middleware, which makes sense, but it rules out the middleware solution.
Is wrapping the standard IUrlHelper in my own implementation and postprocessing the URLs it returns a good way to go? I don't know how to go about that. I use the IUrlHelper from the ControllerBase.Url property and debugger tells it is actually an instance of Microsoft.AspNetCore.Mvc.Routing.EndpointRoutingUrlHelper. Doing the wrapping in every action seems wrong (repetitive, error-prone).
Changing the routing so that /api moves to the root is my last resort option as it mixes up the namespaces: technical endpoints like /health and /swagger would live among the actual resources of the API. Is there a reasonable way to avoid that while keeping the links working? This all seems like a pretty standard problem and I am surprised I cannot find how to solve it.
We use .NET 5 and we will migrate to .NET 6 as soon as it is out, if that makes any difference.

What is the difference between graphql-dotnet/graphql-dotnet/ and graphql-dotnet/server/

Good morning.
I am a bit confused about these two repositories(graphql-dotnet/graphql-dotnet/ and graphql-dotnet/server/).
https://github.com/graphql-dotnet/graphql-dotnet/ and
https://github.com/graphql-dotnet/server
They are both under the same organization and there is some overlap of contributors, but I'm a bit lost about deciding which one to use.
I would like to build a dotnet 5 application that hosts a graphql endpoint. In a nutshell that is my goal.
I noticed that the graphql-dotnet/server/repository has inbuilt some helpers such as.
serviceCollection
.AddGraphQL((options, provider) =>
{
options.EnableMetrics = HostEnvironment.IsDevelopment();
var logger = provider.GetRequiredService<ILogger<Startup>>();
options.UnhandledExceptionDelegate = ctx => logger.LogError("{Error} occurred", ctx.OriginalException.Message);
})
.AddSystemTextJson()
.AddErrorInfoProvider(opt => opt.ExposeExceptionStackTrace = HostEnvironment.IsDevelopment())
.AddWebSockets()
.AddDataLoader()
.AddGraphTypes(typeof(ApplicationSchema))
Which allows my DI to be setup nice and easy. Its counterpart, the graphql-dotnet/graphql-dotnet/ does not.
So my question is "which one should I use exclusivly? Which one is recomended, by secondary goals are to add jwt authentication and finally federation support. But those two are far down the line.
One of my coworkers went ahead and used graphql-dotnet/graphql-dotnet/ and his server application has a lot more configuration than the documentation of graphql-dotnet/server/ so how do I know which one do I use?
Can any one recommend any documentation that highlights the difference between the two of them?
The main graphql-dotnet repo is the "core" library of GraphQL components. The server repo contains ASP.NET specific extensions. It uses the core library. If you use the server project, you are also using the core library.
GraphQL itself can be used with any protocol, it is not required to be used with HTTP or JSON. So the core library does not have any HTTP or ASP.NET dependencies.
If you are using ASP.NET, then the server project is the quickest way to get started. If you want to use Subscriptions, then the server project provides that functionality.
If you don't need subscriptions and if you want a bit more control over how the framework handles the HTTP request, then it would be easier to write your own controller or middleware.
Using JWT authentication is handled by ASP.NET and can be used in either scenario. Federation can also be used in either scenario.

Get remote IP address in DotVVM

I'm building an app using DotVVM framework (ver 1.1.9) using AspNet.Core and .NET Framework 4.7.1.
At some point I need to log remote user's IP address. Is there a way to get it inside the ViewModel? I've seen many tutorials
There is a property Context in ViewModelBase that has property HttpContext but it's some build-in IHttpContext interface, not the proper HttpContext.
However I found out that I can cast existing IHttpContext to DotvvmHttpContext which contains property OriginalContext that indeed seems to be the one I was looking for.
var remoteAddr = ((DotvvmHttpContext)Context.HttpContext).OriginalContext.Connection.RemoteIpAddress;
So the question is, if this is "safe" approach or is there any other "proper" way to either access original AspNet HttpContext or the remote IP Address directly?
Yes, this is safe approach as long as you are only going to run the application on Asp.Net Core. If you'd switch to OWIN hosting for some reason, it would throw an invalid cast exception.
Also note that there is a helper method for getting the Asp.Net Core http context, Context.GetAspNetCoreContext().Connection... might be a bit more comfortable. As you can see from the source code, it's basically the same as your code: https://github.com/riganti/dotvvm/blob/d623ae5ddf57ecf3617eb68454d546f675b64496/src/DotVVM.Framework.Hosting.AspNetCore/Hosting/AspNetCoreDotvvmRequestContextExtensions.cs#L13
Looking at the source for IHttpContext that is exposed in the DotvvmViewModelBase, there does not seem to be a good way to access the connection information. I was hoping that the IHttpRequest might expose the remote IP address but that also isn’t the case.
You have to rely on accessing the original HttpContext from ASP.NET Core here to access that information. If you run on ASP.NET Core (instead of OWIN), then it should be totally save to cast the context to DotvvmHttpContext so that you can access the underlying HttpContext.
So yeah, your solution seems just fine here:
var originalHttpContext = ((DotvvmHttpContext)Context.HttpContext).OriginalContext;

Can not access IHttpRequest within ServiceStack Mvc Application

Sorry for my lack of understanding regarding the web stack but this has been haunting me for a couple days.
I am trying figure out how to access Request as a IHttpRequest within the web controllers of the https://github.com/ServiceStack/SocialBootstrapApi example.
It is currently a MVC3 app with ServiceStack's MVC PowerPack. My request always resolves to a System.Web.HttpRequest. I created an extension method on IHttpRequest to check if the current request is coming from a mobile device but it never gets picked up because all my requests are System.Web.HttpRequests instead of a ServiceStack.ServiceHost.IHttpRequest. any help would be great!
You can do something like
var httpReq = System.Web.HttpContext.Current.ToRequestContext().Get<IHttpRequest>();
to turn the request from System.Web.HttpRequest into a ServiceStack.ServiceHost.IHttpRequest.
The requests going into the Controllers of the SocialBootstrapApi examples don't come through the 'ServiceStack pipeline'. The Controllers do inherit from ServiceStackConroller but I think its purpose is to share Session data between MVC and ServiceStack. The ServiceStackContoller doesn't take over the request/response like a request going into the /api path which is handled entirely by ServiceStack in the example project.

Categories