We have an application using ASP.NET Core 1.0 RC1 and hosted on IIS. It works fine. Now we have static content, that is available on a file share and should be accessible from the application.
Before ASP.NET 5, we added a virtual directory in IIS and could access the shared content easily. With our hosted ASP.NET 5 application, this unfortunately doesn't seem to work. We just get a 404 back when trying to access the static content.
Our application is using app.UseIISPlatformHandler() and app.UseStaticFiles(), but this doesn't work. We discovered that we could use app.UseFileServer() with custom FileServerOptions to get the desired behavior, but we are curious if it's also possible with the normal "old" way of adding a virtual directory in IIS.
I have found a blog which I think must have been written by the OP.
The upshot is not to use a virtual directory in IIS at all but rather map your path in Startup.cs to the physical server directory. I hope the OP does not mind that I have pasted the blog below, but it helped me when I first encountered this problem today.
Source: https://www.jauernig-it.de/asp-net-coreiis-serving-content-from-a-file-share/
There are situations, when you want to serve static content with your application, that is not part of it, e.g. because it exists on a common file share. Website content, that is managed by a business division, could be such a use case. In ASP.NET before Core, this was no problem in IIS: just create a virtual directory within your IIS website and point it to the file share.
Unfortunately, with ASP.NET Core, this approach isn’t working any longer. If you add a virtual directory to your ASP.NET Core application in IIS, it isn’t recognized and a 404 is returned. It’s because of DNX/Kestrel, which is running beneath IIS (using the HttpPlatformHandler module) and to which IIS only brokers the requests. Kestrel doesn’t know anything of virtual directories from IIS. And because ASP.NET Core applications are independent from IIS and could also be run without it (e.g. running Kestrel standalone), that should be considered as a good thing.
But now we need another solution for our problem… fortunately, ASP.NET Core gives us a programmatic interface to serve files from anywhere. Just add the following code to your Startup.cs Configure() method:
app.UseFileServer(new FileServerOptions
{
FileProvider = new PhysicalFileProvider(#"\\server\path"),
RequestPath = new PathString("/MyPath"),
EnableDirectoryBrowsing = false
});
What this essentially does, is adding a file server to a physical server path, that is then available on a certain request path, in this case with directory browsing disabled. You are also able to serve from a path relative to your application, using new PhysicalFileProvider(env.WebRootPath + "\path") (given env is of type IHostingEnvironment as parameter of Configure()). Voila, that’s it. There is no need to add a „virtual directory“ in IIS, this stuff is deprecated and a thing of the past. For me, this is a good thing, because we get more independent of the whole IIS…
I encountered this problem today, and finally managed to fix it. The trick (for me, probably not for everyone) is making sure the aspNetCore handler is disabled in the sub-application and enabled in the main (ASP.NET Core) application.
My ASP.NET Core app has a basic Web.config
<configuration>
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" type="" modules="AspNetCoreModule" scriptProcessor="" resourceType="Unspecified" requireAccess="Script" allowPathInfo="false" preCondition="" responseBufferLimit="4194304" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\bin\Debug\netcoreapp2.0\myapp.dll" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" />
</system.webServer>
</configuration>
and the application added as a sub-application in IIS has
<configuration>
<!-- removed -->
<system.webServer>
<handlers>
<remove name="aspNetCore" />
</handlers>
</system.webServer>
</configuration>
I know its a question with 1,8 year, but if someone needs to resolve the same problem, try to use this:
public void Configure(IApplicationBuilder app)
{
app.UseStaticFiles(); // For the wwwroot folder
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), #"wwwroot", "images")),
RequestPath = new PathString("/MyImages")
});
}
Is perfectly possible to change parameters of PhysicalFileProvider to any local or shared folder, and with this serve a file.
Doing that in this way is not SECURITY recommended. But, for study propose, its acceptable.
The static file module provides no
authorization checks. Any files served by it, including those under
wwwroot are publicly available. To serve files based on
authorization: Store them outside of wwwroot and any directory
accessible to the static file middleware and Serve them through a
controller action, returning a FileResult where authorization is
applied.
In Microsoft's Asp.Net documentations we can find more complete information to help with this issue.
Check this link: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/static-files
Not directly.
You see, the problem is, when you have a .NET-Core application, the application is run in Kestrell, not IIS (for .NET Core < 2.2).
Now, to host your .NET-Core application in IIS, the AspNetCoreModule starts your .NET-Core application with Kestrell on Port X of 127.0.0.1, and then reverse-proxies the traffic from your iis-domain+virtual directory to Port X on 127.0.0.1 (it might use something else than TCP).
Problem 1 is, Kestrell has pretty limited functionality, meaning no virtual directories.
Problem 2 is, unlike nginx, IIS does not really do the reverse-proxying properly, or should we say "completely".
IIS can forward domainxy:80 to 127.0.0.1:random alright.
But what it doesn't do properly is rewrite domainxy:80/foo to 127.0.0.1:random (images, header, json-ajax-results, urls, return-urls, cookies, etc. and vice-versa).
Instead it rewrites domain:80/foo to 127.0.0.1:random/foo, which is a problem if the server on 127.0.0.1:random (Kestrell) doesn't support virtual directories.
So if you want to run your application in your virtual-directory, you have two options (both involve modifying "your" application - if you can do that):
Put all your stuff into directory "foo" (including the MVC controller route), if your application is going to be deployed only once.
As suggested in https://github.com/aspnet/Hosting/issues/416#issuecomment-149046552 you can have the application-framework simulate that folder for you, kindof like in RoR:
public void Configure(IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
string virtual_directory = "/Virt_DIR";
// virtual_directory = "/";
if (virtual_directory.EndsWith("/"))
virtual_directory = virtual_directory.Substring(0, virtual_directory.Length - 1);
if (string.IsNullOrWhiteSpace(virtual_directory))
Configure1(app, env, loggerFactory); // Don't map if you don't have to
// (wonder what the framework does or does not do for that case)
else
app.Map(virtual_directory, delegate(IApplicationBuilder mappedApp)
{
Configure1(mappedApp, env, loggerFactory);
}
);
}
// Configure is called after ConfigureServices is called.
public void Configure1(IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
// [...] (here comes what used to be in your old Configure method)
}
You will have to configure the name of the virtual-directory somewhere.
Careful when you have/return URLs in JavaScript/ajax-requests, they won't be automagically mapped. You have to do this yourselfs, but that used to be this way with old ASP.NET, too.
Really, like RoR:
map Rails.application.config.relative_url_root || "/" do
run RedmineApp::Application
end
As for a virtual directory within the application:
No, this is not that simple.
IIS is a full webserver, which will serve the content of that mapped directory like it was there (if it can read the contents).
If you forward the entire parent directory to Kestrell, then IIS can't serve the subdirectory, and you're application would have to do that. That means you'll have to setup a static file server for that specific directory, and tell it where the files are, as you have done.
What you might be able to do, is tell IIS to not proxy that specific virtual sub-directory (just as you can define a static-file location in nginx - except that IIS probably does not support that feature).
However, you could create a symlink (or mount/junction) within your application directory that goes to the networked folder, if Windows is capable of that (mklink). Then .NET Core should be able to serve it statically. But really, that sounds like a hack.
If you can't configure IIS, you really should use app.UseFileServer() and define the document's location in the database. That way you can just delete&re-insert the application later.
.Net Core has very limited support for IIS virtual directories.
As a workaround, you can use Microsoft.Web.Administration to get list of a Site ("Default Web Site") virtual directories.
Replace Path with PhysicalPath to locate the resources
Create a .NetStandard lib project (>= 1.6.0), and use this example
My solution was using path="/" instead of path="*" on web.config file
Have tried recommendations as found in HTTP Error 500.30 - ASP.NET Core 5 app failed to start and other similar posts but not having a lot of luck.
My API works perfectly fine running with IIS Express in VS2019, but after publishing it just won't start.
This is my web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\MyApi.dll" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
</system.webServer>
</location>
</configuration>
Have tried both inprocess and outprocess, provided environment variables no difference.
Code is deployed to C:\inetpub\wwwroot\MyApi
IIS_IUSRS has been given read/write access to wwwroot folder
This is my working lunchsettings.json file from the VS project
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "https://localhost:44307",
"sslPort": 44307
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"MyApi": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
This is my program.cs
public class Program
{
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
_ = webBuilder.UseStartup<Startup>();
})
.ConfigureServices(services =>
{
_ = services.AddHostedService<MyApiWorker>().Configure<EventLogSettings>(config =>
{
config.LogName = "My API";
config.SourceName = "My API";
});
});
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
}
IIS logs in /inetpub/logs/logfiles are not all that useful (4443 was the port I used when adding to IIS).
#Software: Microsoft Internet Information Services 10.0
#Version: 1.0
#Date: 2021-10-27 09:31:01
#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status time-taken
2021-10-27 09:31:01 ::1 GET / - 4443 - ::1 Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/95.0.4638.54+Safari/537.36 - 500 0 2147500037 4
2021-10-27 09:31:07 ::1 GET / - 4443 - ::1 Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/95.0.4638.54+Safari/537.36 - 500 0 2147500037 0
2021-10-27 09:32:39 ::1 GET /swagger - 4443 - ::1 Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/95.0.4638.54+Safari/537.36 - 500 0 2147500037 0
2021-10-27 09:36:45 ::1 GET / - 4443 - ::1 Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/95.0.4638.54+Safari/537.36 - 500 0 2147500037 0
Any ideas would be greatly appreciated. I can't seem to find any meaningful logs, and the logs the app outputs never publish anything.
EDIT: Application Pool is No Managed Code
Have installed dotnet-hosting-5.0.11-win.exe and rebooted and restarted IIS multiple times.
Event Log shows:
Application '/LM/W3SVC/1/ROOT' with physical root 'C:\inetpub\wwwroot\myapi' failed to load coreclr. Exception message:
Managed server didn't initialize after 120000 ms.
EDIT 2 Now getting this in the Event Logs:
The application-specific permission settings do not grant Local Activation permission for the COM Server application with CLSID
{3480A401-BDE9-4407-BC02-798A866AC051}
and APPID
{30AD8C8E-AE85-42FA-B9E8-7E99E3DFBFC5}
to the user IIS APPPOOL\DotNetCore SID (S-1-5-82-2530134163-791093599-2246298441-3166710890-3969430272) from address LocalHost (Using LRPC) running in the application container Unavailable SID (Unavailable). This security permission can be modified using the Component Services administrative tool.
All stdout logs 0kb empty files
EDIT 3
I can also go to the folder and run it by double-clicking the exe, but for some reason, IIS will not. This makes no sense. All I get is this error:
Application '/LM/W3SVC/1/ROOT' with physical root 'C:\inetpub\wwwroot\myapi\' failed to load coreclr. Exception message:
Managed server didn't initialize after 120000 ms.
Extending timeout doesn't help either, when manually executing it takes seconds to get up and running.
EDIT 4
I had some Google Gmail functions in the API to send out emails on errors. Seems they were causing a problem. Removed all traces of the google stuff, and it no longer takes minutes to start. I suspect this was because Google was trying to get IIS to accept terms to use Gmail, but that obviously cannot happen.
Now that is out of the way, I am still getting a new error:
Application '/LM/W3SVC/1/ROOT' with physical root 'C:\inetpub\wwwroot\myapi\' has exited from Program.Main with exit code = '0'. Please check the stderr logs for more information.
But no stderr messages to be found, but at least the error is different.
I was able to host on my windows IIS.
Pre-requisite: You need to have .Net Core Hosting Bundle installed on the server.
In IIS Manager,
Created New Website in IIS and point to the folder where you published the code. IIS Website
When the website gets created, the application pool automatically gets created which runs on ApplicationPoolIdentity. Make sure the .Net CLR version is to "No Managed Code"app pool
Reset IIS
Browse the application url: http://:port/<controllername/route>
Please make sure that you have installed your .net core on server
Setup your application pool to No Managed Code
If still not working, please check error logs
I follow these steps https://dotnetblog.asphostportal.com/how-to-publish-asp-net-core-blazor-application-to-iis/ and my application work flawlessly.
Okay, so I figured it out without any useful logs.
The fact it wouldn't run the Google auth made me start thinking about whether I needed to run the Application Pool as myself, so I set the Application Pool identity as my user account. No dice. So then I found this post: ASP.NET Core Web 3.1 - IIS Express can fetch data from localdb but local IIS can not
Followed what they suggested, now the application reports starting okay. I can see logs that it is running and can hit the endpoints.
Was also able to add back my Google auth for email notifications. Everything is working.
I also took the opportunity to set the timeout for the Application Pool to 0 and set it to Start Mode: Always Running.
Built a default Net Core 2 app w/no authorization and successfully web-deployed via VS2017 Publish to remote IIS instance under Win 7. However, the app fails to run, generating an HTTP 500 error.
Log file shows a 500.19 error:
Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port
cs-username c-ip cs(User-Agent) sc-status sc-substatus sc-win32-status
time-taken 2018-03-29 20:42:20 ::1 GET / - 81 - ::1
Mozilla/5.0+(Windows+NT+6.1;+WOW64;+Trident/7.0;+rv:11.0)+like+Gecko
500 19 5 296
After researching, there seems to be a myriad of options for setting up to run under IIS. I first tried MS recommendations, which resulted in above error.
Here is web.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="aspNetCore"
path="*" verb="*"
modules="AspNetCoreModule"
resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet"
arguments=".\WebApplication1.dll"
stdoutLogEnabled="true"
stdoutLogFile=".\logs\stdout" />
</system.webServer>
</configuration>
Here is IIS site configuration:
IIS add-ins:
MS Web Platform Installer
Net Core Server Hosting
Web Deploy
MS .NET Core 2.0.6 Windows Server Hosting
Questions:
should a default app work as is when published to IIS?
If not, what is necessary?
The solution was adding IIS Application Pool access rights to the folder holding the Net Core app as shown here in the Microsoft documentation.
So, yes, a default ASP.NET Core 2 app will run fine under IIS as is. Problem had nothing do with application at all.
Since this problem cost me almost three days of my life due to ignorance of web development and IIS specifically, I will post this answer in case someone else has the same problem.
Thank you Simonare for sending me down the right track, albeit indirectly.
This doesnt show enough information about error.
First thing first I suggest you to enable stdoutLog under web.config. And It also make sense to enable detailed error logs under program.cs by including
UseSetting("detailedErrors", "true")
CaptureStartupErrors(true)
var host = WebHost.CreateDefaultBuilder(args)
.UseSetting("detailedErrors", "true")
.CaptureStartupErrors(true)
.UseKestrel()
.UseStartup<Startup>()
.Build();
furthermore you can try to run dotnetcore application on server by opening command prompt on the deployment directory and running application with executing `dotnet yourApplicatonName.dll
further troubleshooting information can be found below
https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/troubleshoot
EDIT: When you publish your application it sometimes need to publish your application by targetting remote operation system version. For this you need to include RuntimeIdenfiers in your project.csproj
<RuntimeIdentifiers>win10-x64;win7-x64</RuntimeIdentifiers>
Catalog of the runtime identifiers can be found in
https://learn.microsoft.com/en-us/dotnet/core/rid-catalog
then you need to update your publish profile to target remote platform correcly. By Default, It is "Portable"
I am trying to get my new asp.net core rc2 version running on my dev server that running IIs 8.5 and window 2012 server
I've followed the steps list in here, which is:
On my local:
Create a new asp.net core project using VS 2015 (Dev14) U2
Change the web.config stdoutLogEnabled="true", create a new deploy profile and publish it locally to a folder
Make sure the website works on IIS Express.
On my server
Installed the DotNetCore.1.0.0.RC2-WindowsHosting.exe and reset IIS
Setup new app pool with no managed code, setup new website in IIS that points to the local: D:\apps\myapp1\
Copy the deploy content to D:\apps\myapp1\ (such as the dll is D:\apps\myapp1\myapp1.dll)
dotnet.exe is on the path. I can even go to D:\apps\myapp1\ and dotnet myapp1.dll. It will bring up the nano server.
What I see when I hit http://mydevserver/myapp1 (or localhost/myapp1 on my dev server):
HTTP Error 502.3 - Bad Gateway
When I view the Event log, I can see a bunch of failure like this:
my logs folder on D:\apps\myapp1\logs is also empty. There is no log in that folder whatsoever.
At this point I am pretty lost on what to do. Help!!!
Here's the content of my web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!--
Configure your application settings in appsettings.json. Learn more at http://go.microsoft.com/fwlink/?LinkId=786380
-->
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified"/>
</handlers>
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false"/>
</system.webServer>
</configuration>
</xml>
There are a few things you can do to troubleshoot:
go to the published app and try running it without IIS
logs won't be written if the folder does not exist and by default the logs folder does not exist
if it is a portable app make sure the path to dotnet.exe is on the system wide %PATH% (note you need to do iisreset after you set it to make IIS pick it up)
I wrote a blog post explaining how ASP.NET Core apps work with IIS and the post contains the section on troubleshooting your very problem.
So I finally figured out what's wrong. Apparently because I did not setup my website under "Default Web Site" of IIS, so IIS (I think) routes my website incorrectly. My fix is to move my website under Default Web Site.
One of my friends found another way to setup the website outside of Default Web Site by disabling the Default Web Site. I have not tried to get both Default Web Site enable and MyApp website enable working. Maybe somebody else can contribute in...
I have some code that wraps the PayflowPro .NET API. It essentially posts to a HTTPS address (a payment gateway) from C#. I can run this code locally and it works nicely. I can run it in my MSUnit tests and it works, and I can run it from a console application on my test environment and it also works.
I have a workflow hosted in IIS 6.1, which instantiates a class which in turn calls this code. When this workflow is started the code fails everytime; I get an error like System.Exception: Failed to connect to host Input Server Uri = https://pilot-payflowpro.paypal.com/ from the API object.
This exception is coming from the API, but I am completely lost as to how I can succesfully post from a console application but not from an IIS process.
The class is exactly the same, word for word.
I log in as administrator, so the console app is running as administrator. Therefore I have tried using the administrator account for the application pool for the website (for this testing only, obviously)
The console app can post so therefore the firewall / proxy aren't interfering... right?
Is there anything I need to adjust in IIS to allow an application to communicate outside? Are there any obvious security settings that I'm overlooking? Any suggestions for test cases to run to find out what might be going on?
edit: Turns out that this problem is somehow related to the VM environment in which the server is running. This problem doesn't occur on my development box, the test server or the production server - it's only occurring on the integration server. The cause is still unknown but I am no longer working on it.
This might be caused by an ASP.NET trust configuration issue. To check the trust level open the following file in an editor:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\web.config (if ASP.NET 2.0)
C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\CONFIG\web.config (if ASP.NET 4.0)
You may also need to edit the C:\WINDOWS\Microsoft.NET\Framework64 versions of these if you're running on 64 bit Windows.
Scroll down to the <securityPolicy> configuration section which looks like:
<location allowOverride="false">
<system.web>
<securityPolicy>
<trustLevel name="Full" policyFile="internal"/>
<trustLevel name="High" policyFile="web_hightrust.config"/>
<trustLevel name="Medium" policyFile="web_mediumtrust.config"/>
<trustLevel name="Low" policyFile="web_lowtrust.config"/>
<trustLevel name="Minimal" policyFile="web_minimaltrust.config"/>
</securityPolicy>
<trust level="Medium" originUrl=""/>
</system.web>
</location>
If you see anything other than <trust level="Full" originUrl=""/> it means the server is running under Partial Trust.
Open the .config file specified by the relevant policyFile attribute, for example web_mediumtrust.config if level="Medium".
It's highly unlikely that the server will be running under anything less than Low Trust.
Locate the <NamedPermissionSets> section, under this there is a <PermissionSet> that looks like:
<PermissionSet
class="NamedPermissionSet"
version="1"
Name="ASP.Net">
This contains a number of <IPermission> nodes. Look for one that called WebPermission, it looks like this:
<IPermission
class="WebPermission"
version="1">
If it's missing or looks like:
<IPermission
class="WebPermission"
version="1">
<ConnectAccess>
<URI uri="$OriginHost$"/>
</ConnectAccess>
</IPermission>
You need to add or modify so it looks like:
<IPermission
class="WebPermission"
version="1"
Unrestricted="true"/>
This setting controls outbound and inbound access from your application to or from a URI.
It may also be necessary to ensure that the SocketPermission configuration is similarly configured:
<IPermission
class="SocketPermission"
version="1"
Unrestricted="true"/>
Turns out that this problem is somehow related to the VM environment in which the server is running. This problem doesn't occur on my development box, the test server or the production server - it's only occurring on the integration server. The cause is still unknown but I am no longer working on it.