This is mostly an academic question, but it might have some real world value in my project.
Having defined a web host in a web project (dotnet core 3.1), is there any way to call this host directly with a HttpContext?
I assume there might be a service somewhere to override to allow me to just run the HttpContext processing part of the pipeline, without having an actual web server running - but I can't quite find it. Any ideas?
Related
After reading Microsoft documents I am still confused. I need to deploy a .net core 2 web application I developed to an IIS server and I can't get a straight forward answer on anything. This is just the beginning of my questions.
What is the difference between IWebHost, WebHostBuilder, BuildWebHost?
Thanks!
First of all, let me start with that I very much disagree with your statement: The documentation on ASP.NET Core is actually very good. Yes, it may be still lacking in some details, and it also has some problems catching up to changes with releases, but overall the content is really good and the team working on it is really doing a remarkable job. It’s really difficult to author a documentation for such a large and fast-moving framework, and the amount of information you get through the documentation is actually very good. You will likely get to recognize that once you have overcome the initial problems in starting with a new framework.
But coming back to your question:
IWebHost: The web host is the general thing that hosts and runs your web application. It gets created when your application starts up, and then it will construct all the necessary pieces, like the Kestrel web server, the application middleware pipeline, and all the other bits, and connects them, so that your application is ready to serve your requests.
The web host is basically the thing that makes up your web application.
IWebHostBuilder: The web host builder is basically a factory to create a web host. It is the thing that constructs the web host but also configures all the necessay bits the web host needs to determine how to run the web application.
With ASP.NET Core 2, you will usually create a “default web host builder” which will already come with a lot defaults. For example, the default web host will set up the Kestrel web server, enable and configure logging, and add support for the appsettings.json configuration.
Usually, your applications will always start with such a default web host and you then just use the web host builder to subsequently configure the web host before it is actually being built.
BuildWebHost is part of the older convention before ASP.NET Core 2.1 where the default pattern in the Program.cs was to build the web host in a separate method. With 2.1, this was changed so that the method would no longer build the web host directly but just create the web host builder (hence the method now being called CreateWebHostBuilder). So basically, the .Build() call on the web host builder was refactored out of the method. You can see this nicely in the migration guide for 2.0 to 2.1.
The reason this was done is to make the CreateWebHostBuilder reuseable. The builder configuration that happens in that method is basically everything that is necessary to configure the web host. So by making that reusable, without generating an actually created web host, it can be used for other purposes. In this case, this was done for integration testing using the TestHost. The test host will basically host the web host internally for your integration tests, and it will do so by looking for the CreateWebHostBuilder method.
With ASP.NET Core 2.1, the default pattern you see in the Program.cs is the following (comments added by me for further explanations):
public class Program
{
// main entry point for your application
public static void Main(string[] args)
{
// create the web host builder
CreateWebHostBuilder(args)
// build the web host
.Build()
// and run the web host, i.e. your web application
.Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
// create a default web host builder, with the default settings and configuration
WebHost.CreateDefaultBuilder(args)
// configure it to use your `Startup` class
.UseStartup<Startup>();
}
Btw. this topic is generally covered in the application startup and hosting sections of the official documentation.
ASP.NET Core 3.x
Starting with ASP.NET Core 3.0, there has been a change with the setup I described above. The reason for this is the generic host. The “generic host” is a generalization of the web host and the web host builder, to allow non-web scenarios outside of ASP.NET Core, making ASP.NET Core itself just a “hosted service” that runs on top of the generic host.
IHost: The host is the component that hosts and runs your application and its services. This is a generalization of the previous IWebHost but fullfills basically the same task: It starts configured hosted services and makes sure that your app is running and working.
IHostBuilder: The host builder constructs the host and configures various services. This is the generalization of the previous IWebHostBuilder but also basically does the same just for generic IHost. It configures the host before the application starts.
There is the Host.CreateDefaultBuilder method that will set up a host with various defaults, e.g. configuration using appsettings.json and logging.
IHostedService: A hosted service is a central component that the host hosts. The most common example would be the ASP.NET Core server, which is implemented as a hosted service on top of the generic host.
You can also write your own hosted services, or add third-party services that allow you to nicely add things to your application.
The generic host introduced with ASP.NET Core 3.0 and .NET Core 3.0 basically replaces the previous IWebHost and IWebHostBuilder. It follows the very same architecture and idea but is simply reduced to non-web tasks so that it can work with a number of different purposes. ASP.NET Core then just builds on top of this generic host.
I have a sample web API hosted in an OWIN process (self hosted, not in IIS). I get a JWT token in my controller and I want to be able to retreive it in another part of the application, a class that implements NserviceBus IMutateOutgoingTransportMessages. In my other web application POC (hosted in IIS), I used a simple session variable and it works just fine. But I'd like to know what would be the best way to do it in my new OWIN self hosted environment ? Static property in static class ?
This question is really broad and difficult to answer without detailed knowledge of your specific needs. Here's my interpretation of your issue:
You're already signing each request, perhaps storing the token in the browser sessionStorage (or even localStorage), but this does not suffice
You need to retrieve the token outside of or not in relation to any request cycle (if not, this is probably where you should be looking for answers)
Your application does not need to be stateless
Just one static property for one token in a static class would of course start breaking as soon as more than one request hits the application at the same time. Implementing a class that maintains a list of tokens may be a solution, although I can't tell what key you should use to identify each token. Interface details would vary depending on things like if you need to retrieve the token more than once.
Thread safety issues would apply to all handling and implementation of such a class. Using Immutable Collections and functional programming practices as an inspiration may help.
If lingering tokens poses a problem (and they probably would from a security perspective, if nothing else), you need to figure out how to make sure that tokens do not outstay their welcome, even if the cycle is for some reason not completed.
Seeing how you used Session as a solution in your POC, I'm assuming you want some similar behavior, and that one user should not be allowed to carry two tokens at the same time. You could store the tokens i a database, or even in the local file system, making maintenance and validity a separate issue all together.
There are implementations of cache-like functionality already available for OWIN self-hosted applications, and maybe one of those would serve as a shortcut to implementing everything yourself.
If this token business in fact is the only reason for introducing state in your application, then the best solution IMHO would be to rethink your architecture so that the application can remain stateless.
I'm facing a similar dilemma on a server i'm currently developing for a customer. My problem is that the server must make calls (and retain a live connection) with a legacy, multithreaded DLL, (aka the SDK).
I struggled to get this working on IIS with a regular Web API project. Failed badly since IIS recycles threads when it determines that a thread is going rogue... witch is what the SDK thread looks like in that perspective. Also, the SDK must be able to callback on the caller (client - single page app) and for this I'm using SignalR.
I then tried a multi-part system (single page + web api on IIS + WCF service for the SDK integration). But it is a real nightmare to manage because of the 2 way async communication that must occur between all apps. Again: failure.
So I reverted to a single self hosted OWIN + WebAPI service in a console app (for now). My problem is that some of the calls are lengthy and are processed in a worker thread. I managed to pass the SignalR client id in each ajax calls via headers. I can extract the id when in web api controller. But when the task goes async, I need to get the id (via an Unity injected service) from the class that manages the async task. This is where my problem is similar to yours. In IIS hosted apps, we have HttpContext. It is contextualized on each client calls, and follows any thread changes in the pipeline... But not in self hosted OWIN WCF apps...
I'm looking into Thread Local Storage, CallContext... and other means of keeping track of the original caller info during the lifecycle of the async call. I have read about OWIN pipeline, I can capture the info in a OWIN middleware... but how to safely keep that info for use in injected services? I'm still searching for an answer...
I was wondering if you have found a solution to this rather interesting problem ?
I prefer adding to your thread rather than start another parallel thread / SO question.
I've implemented an OData service using ASP.NET WebAPI. I also have some existing web methods in a seperate WCF project which is hosted in an ASP.NET Web Application.
By copying some bits of web config around and copying a couple of code files I've managed to get the WCF methods hosted in the WebAPI project.
Everything seems to be working but I've got a nagging doubt I'm doing something horribly wrong that's going to break when I least expect it.
Is this a good idea?
Depends on your anticipated call volume. The only problem I can think of with this is that incoming WCF requests will be serviced from the same dispatcher thread pool as the OData service. This makes it more likely that you will suffer availability based issues on either endpoint.
I've got an MVC web application that is used as an interface to a Console based app that exposes a bunch of ServiceHost/s using the net.pipe protocol.
I would like to use the asp.net membership/role/profile provider to manage my users and their roles and profile information (Inside the Console Application). I've done this in quite a few apps, but normally I reference these providers directly from the web application itself.
This is a good walk-through on doing pretty much what I would like, except I don't want to host the WCF service endpoints in IIS, but inside my console app - which will eventually become a windows service. When I try and host the ServiceHost through my console application I get the following error:
This service requires ASP.NET compatibility and must be hosted in IIS.
Either host the service in IIS with ASP.NET compatibility turned on in
web.config or set the
AspNetCompatibilityRequirementsAttribute.AspNetCompatibilityRequirementsMode
property to a value other than Required.
Now it seems that I won't be able to set that property to anything other than Required.
I've tried another route which is using the wrapper class/interface defined here for my authentication service, which I managed to get wired into in my MVC app without too much trouble, but this doesn't cover my Authorisation (using roles) or profile needs.
Has anyone got a solution to this, I can't be the only one trying to do this? I'm not
We currently have a WCF Service which is beginning to reach it's limits performance wise.
We have decided to add another server which will host another instance of the WCF Service.
We have web applications which must communicate with a specific server based on context... e.g. If the web application is dealing with objects from ServiceInstance1 then requests must be directed to ServiceInstance1's EndPoint. If the web application is dealing with objects from ServiceInstance2 then requests must be directed to ServiceInstance2's EndPoint.
I initially thought that a "Intermediate Service" or "Service Manager" could be created, the web application's Service Reference would be updated from the individual Service Instance to the "Intermediate Service" or "Service Manager" and said service would act as a "Broker" to the various Service Instances.
How is this accomplished?
I have currently added a ServiceReference to each service from the Manager however it seems that once a Service is "Referenced" it's types becomes specific to the that of the ServiceReference e.g.
ServiceInstance1's type's are all {ServiceInstance1}.
ServiceInstance2's type's are all {ServiceInstance2}.
I need the types to be the same on the web application end, so this obviously seems like the wrong way to do it.
I would also like that when methods are called on the client generated from referencing the "Intermediate Service" or "Service Manager" that the correct Service Instance is invoked, e.g.
IServiceManager.GetProjectById( {GUID} ) ->
Comes Back to ServiceManager ->
Determines which host has the project and returns the ProjectObject from the correct ServiceInstance.
Where ProjectObject is a Type Defined in ServiceInstance1 and ServiceInstance2.
I think the original service needs to have some of the DLL's pulled out so they can be referenced from the web application side and ServiceManager and a GenericWCF Client can be made.
If I am right hooray for me If someone can point me in the right direction I would appreciate it. If I am wrong can someone please scold me and show me how this is properly done!
The way to solve your problem is to create shared assembly with types used by both services. Reference this assembly on the client consuming your services (manager) and when creating proxies by Add service reference mark Reuse types from referenced assemblies.
What you are building is very simple message router. In WCF 4.0 there is additional support for routing services so you should check those features before developing your own. For WCF 3.5 MSDN magazine contains articles about building message router - part 1, part 2.
Just to Answer this and close it I wound up utilizing the Routing Strategy in .Net 4.0 and custom client class which I modeled after the generated classes from the Proxy.
Before I had the custom client ready I used the auto generated client code and I derived a class from it which allow me to change which service it was connecting to. I determined which service via a property which was made available on all service objects which were serialized.
Long story short this is working 100% as expected including the ServiceManager which can even be bypassed on certain calls which we allow.
We even have the ability to move a project from server to server during run time!
Thanks to everyone who helped! (Especially myself for actually doing the work without being spoon fed)
The easiest way to accomplish what you're trying to do is to stop generating your proxies using the server-hosted URL of the service. Instead, generate your proxies from the *.xsd and *.wsdl locally, and merely change the URL of the endpoint. Alternatively, you can use ChannelFactory<T> to generate proxies on-the-fly, and reference your interface .dll on the client side.
Once you've done that, you can use any common webserver load balancing technique to balance the load between the servers.
Not to put too fine a point on it, but Visual Studio's "Service Reference" is not useful, and should not be used, for services you develop. It's useful only for services developed externally, whose URL and contracts are likely to NEVER change. I personally have never had occasion to use it. For your own services, you should probably be using ChannelFactory<T> or a class based on ClientBase<T> to work out the proxies.