Seems like a more modern & better alternative to UnloadAppDomain() (which force-terminates everything immediately)
@ThePukeOne - Translation: It'll never happen 😃
@TehWardy - As a protection strategy from malicious sites it's worthless. It only provides value to the host site from protecting itself and the client code from accessing resources it's not supposed to. It's a very limited security feature and I agree - it's mostly worthless in that it gives people who don't understand what it actually does a false sense of security that's not actually there.
Well, in 2019, xsd.exe still can't read import element... Microsoft
I am not sure what happened to my previous post. But, I am trying to have this installed on Windows 10 desktop for developers. Default it is going to be installed on C drive. Now, with the C drive being a VDISK and if it is locked down that users cannot make changes, will it affect in anyway if they have develop the websites and put it in InetPub folder in D drive? Next, I also got a script from this Microsoft link which be used to automate the relocating of the Inetpub contents, and will leave the existing directory structure untouched. Will this affect your installation in anyway? I am going to build a new Windows 10 box with C drive and D drive and I am going to run your script to install IIS and also I am going to run this script to see how it goes.
Excellent post! I used your first post on hosting an app in .Net Core and now you update it with this incredibly detail post on .Net Core 2.2 and IIS. Awesome!
Is It me or is CORS the most pointless piece of technology ever.
I mean ... any source can claim it's making a request from a given source domain and nothing in the CORS architecture requires any form of identification beyond "ok you gave me a header saying you are calling from x domain".
The whole CORS concept needs throwing out IMO, if services want to protect their endpoints preventing calls from only but a select few why not use pre-shared keys or something, that sort of mechanism already works for things like FTP clients so why not HTTP clients?
This is a truly awesome resource. I was stuck wondering how to integrate the full Identity Framework into my existing application and this fits the bill perfectly.
Must have taken you ages to work out the details - thanks for sharing.
I agree 100%. It is completely okay to use try, catch; to purposely ignore an exception run time error. Yes!
The exception 😉 to that is: following a solid set of short rules to justify ignoring an error message and the team must be okay with it. Otherwise, follow your development teams guidelines. My take on the rules, and it has worked well thus far.
#1 - Use try, catch, to ignore error message and continue with build, application usage ONLY, if the error message that it gives is due to one cause. Meaning, the error only ever happens because of a specific scenario 100% of the time, and when that scenario occurs, it does not impact in any way the user experience or expected behavior of the application.
#2 - If rule number one applies to the scenario, then you must add to your catch; a way to email the developer team, in case new unexpected errors occur. So you don't get caught off guard and can handle it accordingly. This way the event is not ignored completely, but at least allows for your application to work with minimal interruption.
That is it, the only rules I have.
@Bron - that's probably unrelated to the .NET Core hosting and sounds like an invalid or badly configured certifiate.
I use standard IIS certificates with my site without issues works no different than other IIS sites.
This is all well and good and really is a straight-forward configuration, but what about setting up SSL on IIS with an InProcess ASP.NET CORE app. I have a very simple site that works fine over HTTP but once I applied a certificate binding to port 443 on the IIS website, Chrome won't load the page with an error of my.web.site sent an invalid response. ERR_SSL_PROTOCOL_ERROR
my.web.site sent an invalid response. ERR_SSL_PROTOCOL_ERROR
Just an FYI, the format has changed slightly now
I see some people ran into this a while ago, but for future visitors:
If you're also receiving parameters via the [FromBody] attribute and also need access the raw request body, you have to reset the stream otherwise you'll get an empty string back.
Here's an example:
public static async Task<string> GetRawBodyStringAsync(this HttpRequest request, Encoding encoding = null)
if (encoding == null)
encoding = Encoding.UTF8;
using (StreamReader reader = new StreamReader(request.Body, encoding))
return await reader.ReadToEndAsync();
Thanks! I fixed this issue on Azure WebApps using an express NODEIIS deployment. Initially I thought it was a rewrite rule issue, but this solutions saved me a ton of time. Thanks again for delivering!
@Janus - As I've stated in the post I don't think I've ever used IOptions - but rather I either inject the actual typed configuration instance, or - more commonly use a static value which is easier and works across components without the gyrations of DI.
Refresh is a difficult thing to do in Web application. If you're scaled across instances/machines, refreshing a single instance isn't enough and that's where IOptions can help. But I'm not sure if that's worth the effort either. The smarter thing would be that if configuration changes the application should just restart - just as it did in class ASP.NET. Configuration changes are usually applied during startup configuration and that code will never re-run unless the app is restarted.
This MSDN article describes the VS preprocessor symbols that are generated when multi-targetting: https://docs.microsoft.com/en-us/dotnet/standard/frameworks
Thanks a lot dude, I was one step away to release logging with Debug log level on prod 😭
@BD9000 - All that is described in this article still applies in .NET Core 2.2 and later. The additional functionality is InProcess hosting which is linked at the top and bottom of this article with a follow up post.
Any way this can be updated for Dotnet Core 2.2? It appears configuring Windows Server 2012 (IIS8.0) with Dotnet Core 2.2 is an exercise in madness (lots of posts everywhere including StackExchange, MSDN, and no solutions).
Update: After downloading and installing DebugDiag 1.2 from Microsoft, and analyzing the crash dump, the access violation has stopped. Everything else I had done up to that point had made difference.
Using useHttpSys() doesn't use IIS, but it uses a raw HTTP Sys handler inside of the Console applicaiton - it's a standalone host similar to running raw Kestrel but instead of Kestrel it uses HttpSys as the Web interface. It's not IIS though.
HttpSys won't work on Azure because the way the ports need to be exposed and registered on Windows. Even on client Windows this is a pain to set up. Likely that's why you are getting the Access Denied errors.
I think what you want is UseIIS() and if you use inprocess hosting Windows Auth should still work.
Thank you so much. I just started my first .NET Core API project in the last week. I knew going into it, based on my previous work in .NET MVC projects, that switching between databases based on tenant id in the route was going to be one of the bigger challenges, but I wasn't really prepared for how different .NET Core would actually be. The part of your article concerning EndPointRouting was the final piece of a multi-day search puzzle that helped me conquer my challenge. It's incredible how many variations of searches you have to go through sometimes to find just what you want. The search that led me to your page was "get route value in ConfigureServices .net core"
Thanks Rick. Yes we did every flavor of 64bit and 32bit in the app and on the Azure App Service. The app service is reporting Microsoft-IIS/10.0.
We want to do HttpSys (InProcess) under IIS because we are using windows auth. Here is my program.cs...
options.Authentication.Schemes = AuthenticationSchemes.NTLM | AuthenticationSchemes.Negotiate;
options.Authentication.AllowAnonymous = false;
Check and make sure your target platform matches what you compiled to in your Azure settings. Specifically 64bit vs 32 bit.
Also looks to me like you're not ussing IIS hosting but HttpSys hosting - those are not the same thing AFAIK. Check your program.cs and make sure IIS hosting is in there rather than HttpSys hosting.
Great post as always. We have a .net core 2.2 web api we are hosting in an azure app service. We are getting an HTTP Error 500.30 - ANCM In-Process Start Failure error when navigating to our url. When we look at the event log we see this D:\home\site\wwwroot' hit unexpected managed exception, exception code = '0xe0434352'. Last 4KB characters of captured stdout and stderr logs: fail: Microsoft.AspNetCore.Server.HttpSys.HttpSysListener .Ctor Microsoft.AspNetCore.Server.HttpSys.HttpSysException (5): Access is denied at Microsoft.AspNetCore.Server.HttpSys.ServerSession..ctor() at Microsoft.AspNetCore.Server.HttpSys.HttpSysListener..ctor
Searched for days and cannot figure out the issue. Any thoughts?
Nice work Rick
This is excellent and the re-size plugin is most excellent too.
I used Frames in the past and that was excellent too but now its frowned upon. So when I found your sample I was
, well my searched ended.
I tried to add another splitter and column to resize the middle
a three column page with the first two resize-able.
This kind of worked.
It appears that the resizing is tied to to the first column. Am I doing something wrong?
Is this possible with out changing jquery-resizable.js. I am not an expert.
I would like for the re-sizing to change the widths of the column on the left and right(s).
Anyway thanks for sharing.
Hi Suran both worked!
var bodyStream = new System.IO.StreamReader(System.Web.HttpContext.Current.Request.InputStream);
string bodyText = bodyStream.ReadToEnd();
Also the nakedbody attribute code.
Thank you BOTH!
Thanks a lot for this in-depth article - it saved me hours of frustration!!! I hit the same issue with a MS Surface Book (touchscreen + high dpi), and couldn't for the life of me figure out he problem. Upgrading to 4.8 solved it!
This is much more than a Live Reload of course, but very awesome as such. Great stuff as always!
@Justin - I don't use IIS for development. There simply is not much reason to do so because unlike on IIS where there were lots of differences between IIS and IIS Express due to the hosting and security setup as well as the tight IIS pipeline integration, with .NET Core you're running the internal Web Server which exhibits the same behavior regardless of what front end Web server you are using.
That said there are a few differences, and if you happen to be using those (ie. Windows Auth and passthrough security for example) then yes you may have to run IIS for dev.
Personally for development I only run Kestrel ever with dotnet watch run. This is the most productive environment that allows for making changes and those changes being applied immediately without restarts.
dotnet watch run
Wrong Runtime (not 32 bit)
Wrong Runtime (not 32 bit)
This is more of a general problem with .NET Core unfortunately in that it can't resolve the differences between 32 bit and 64 bit, and by default uses the version that was last installed and is on the Windows path. You can however provide the specific runtime in the IIS command arguments for the .NET startup file.
IIS website's app pool is constantly tampered with by ASP.NET Core
IIS website's app pool is constantly tampered with by ASP.NET Core
I don't think so. There's something else going on. .NET Core does nothing with configuration. You deploy your app and once it's installed, it's just an application - it doesn't change server configuration and has no access to server level features like APplication Pool configuration unless your app is writing into web.config and mucking with settings itself.
When things go wrong with the IIS configuration
When things go wrong with the IIS configuration
Yeah that's difficult but somewhat understandable. IIS knows nothing about .NET Core and .NET Core has no specific IIS features either so if something goes wrong before the server is hoisted there's currently no error info.
The best way to work though that in my experience is to test run the application with Kestrel and see if that works first. In most cases there's a problem during the Asp.net core startup that causes the application to not connect to IIS properly and if you run with Development you should see the failures during startup. If Kestrel runs most likely the IIS app will also run. If you start in Debug mode you also getting logging info from the Kestrel app and you can hook up debug file logging to get more info written out.
There's no doubt this is more complex than classic ASP.NET hosting which was fully integrated into IIS and ASP.NET Core is more of a bolt on via a native module and the hand off during startup between the two can be rocky if something goes wrong there. But once ASP.NET Core is up and running you have access to all the tools and logging to troubleshoot.
Nice article. Just one question , where do I download ASP.NET Core Binaries for RHEL 6 X64 ? I dont see in microsoft official page(https://dotnet.microsoft.com/download/dotnet-core/2.2)
Good article - very clear.
One thing I've noticed is that I've not been able to Use Forwarded Headers despite following the simple steps here: https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.2
Maybe I'm missing something obvious, but still searching for an answer...
Is this something you've noticed or have an explanation for pls?
What a great use of middleware to help solve a real world problem.
Like many others I too was using the Browser Link extension (that didn't always work well)
With your middleware it works well, and integrates pretty seamless as part of the development lifecycle
Appreciate the efforts you have gone to and excellent work on explaining how you achieved this, keep up the great work
You might not believe this, but I am having the same problem Rick, using Windows Server 2019 and IIS 10. After my ISAPI extension is unloaded, either by timeout (21 minutes of inactivity) or by the command iisreset, I get the Exception Code: c0000005.
The last thing the extension does in the TerminateExtension function is cleanup some pooled connections to a Redis server, create a log entry, and create an event entry. All of those work fine. However, I commented all of this out, and the error remains. I am writing classic dll's using PureBasic, 64 bit unicode. It does not seem to cause any issues, other than annoying the Hell out of me as I prefer to see clean event logs.
Date: 6/2/2019 4:33:03 PM
Event ID: 801
Task Category: None
TerminateExtension() > Process terminating, all resources have been released
<Provider Name="iisapi_caddata.dll" />
<TimeCreated SystemTime="2019-06-02T20:33:03.520641100Z" />
<Data>TerminateExtension() > Process terminating, all resources have been released</Data>
```Log Name: Application
Source: Application Error
Date: 6/2/2019 4:33:03 PM
Event ID: 1000
Task Category: (100)
Faulting application name: w3wp.exe, version: 10.0.17763.1, time stamp: 0xcfdb13d8
Faulting module name: iisapi_caddata.dll_unloaded, version: 220.127.116.11, time stamp: 0x5cf310bf
Exception code: 0xc0000005
Fault offset: 0x0000000000034230
Faulting process id: 0x3240
Faulting application start time: 0x01d5197f70f26837
Faulting application path: c:\windows\system32\inetsrv\w3wp.exe
Faulting module path: iisapi_caddata.dll
Report Id: 56c79e65-df1a-498a-8e28-339ab06f3f3b
Faulting package full name:
Faulting package-relative application ID:
<Provider Name="Application Error" />
<TimeCreated SystemTime="2019-06-02T20:33:03.563640000Z" />
This is an awesome explanation of the .Net core SDKs & Runtimes
Found this post in your StackOverflow answer, hope you don't mind me commenting on an old post.
The only thing that worked was enabling dynamic content compression. Somehow IIS considers this ONE file dynamic. Weird.
Great article, however in your previous article from 2016 about ASP.NET Core you recommended NOT to use IIS hosting in the development environment. I was interested in this updated one if you'd recommend it now, but you didn't mention it one way or another.
At our company, it's been a nightmare trying to develop ASP.NET Core apps under IIS, here are some of the issues:
The fact that you didn't mention any of these tells me that you're still not using IIS for local dev, that you only use it for server hosting. Is that still your recommendation then, to use IIS express locally?
In Debug, the code from below will show:
Running the installed App shows:
public partial class App : Application
protected override void OnStartup(StartupEventArgs e)
The own constructor doesn't seem to be the "real" constructor:
Could you not do a MsBuild after build target to execute the BrowserSync command? It might be easier to move it to gulp (not the horrible WebPack). Then you could simply say:
@yaron - I hope not 😃 If you have a node_modules folder you'll want to build your project and not ship the huge amount of content in there, only the bundled and built content. If you build using CI on the server, then you shouldn't send that folder at all but do the NPM restore on the server.
in this case how are node_modules published? aren't they needed in the runtime env?
Same problem on brand new Windows Server 2019 and IIS 10. Nothing has changed since then. Maybe i'm not aware of some setting of ISS but I don't have to. Tweaking such things while moving a website from one server to another is kind of annoying. Huge thanks to the author for the post and saving my day.
I'm still learning new dot net core stuff. All these settings in startup and program class in asp.net app still perplexing task. Your post saved my day.
Thank you Rick 😃
Old post, but I really don't see the point in using IOptions unless you're developing a library of some sort and then utilize the PostConfig-feature.
Why would we ever rely on injection IOptions? Especially when we just need the value, which we easily and more obviously could get directly from a strong typed/ GetSection.
IMHO The Reload-feature could as easily just be handled by a simple db-setting/ adjust via query string for flexibility, I think this would be more readable and easier to maintain.
Anyway.. it is always nice to have some tools in the box 😃
Have a great day Rick.
I had the same problem, accessing the tenant ID from route data in custom middleware, and found the answer in https://stackoverflow.com/questions/38505184/asp-net-core-get-routedata-value-from-url. It is possible to initialize the route data early on in the pipeline.
@Rick, very well explained and thank you for this article. Actually, I just want to test this new .net core project on my hosting provider. I use .net 4.5 on my site. On new project, I plan to use new .net core on my hosting since my provider has support .net core. So, this article really helpful.
@Gary, With your budget around £5 per month, just use my hosting provider, asphostportal.com. So far, they are good and really stable. Or second option for you is hostforlife.eu, it is also worth for money. Hope it helps!
Thank You for this post
"Note the info icons ..." - they should have highlighted those with big red exclamation marks ...
Very nice explanation, also took my some time to figure out what is going on with this thing, but got it working mostly.
I have an issue now, my observable that I use for the results is updated externally, thus when a user types something, the request is sent to the server by tapping into the pipe and then using a switchMap on that returns my observable, but this observable comes from outside of my component, the function I call that does the web request also lives outside of my component.
What this is causing is that user might search a name and the http request returns a result, but the result is only shown when the user types another key, do you have any idea of how I can force the ngbtypeahead to update the results shown on screen?
@Andrew - I haven't checked that and not actually sure whether that is supported. I suspect it isn't. Is that really necessary though? Do you really need to run in process while debugging?
Rick, I have inprocess working fine but when running this way, I am unable to debug my app. Simple breakpoints fail to break. If I turn the hosting model settings under the project debug settings to "Out of Process" then my breakpoints start working. It wasn't clear to me from your write up that this is the behavior everyone should be seeing. Any help or pointer in the right direction would be appreciated. Thanks for the write up.