我非常喜欢新的asp.net(asp.net 5\core 1.0)web应用程序的方法,其中wwwroot文件夹是根文件夹,并且只提供其中的静态文件。
是否可以通过路由或其他配置,让asp.net 4.5项目中的wwwroot文件夹以类似的方式运行,从而使静态文件仅从中提供,并且它是静态文件的Web应用程序的"根"?
(我问这个问题的部分动机是,我在VS2015中的一个asp.net 5项目中托管了一个angular应用程序,但我需要将其转移到asp.net 4.5项目中,但希望保留磁盘上的现有结构)
尝试使用OWIN
我曾使用一个空的ASP.NET 4.5 web应用程序项目和OWIN尝试过这一点。所以我的文件夹结构有我的angular应用程序,在项目文件夹的wwwroot文件夹中有一个主要的index.html文件。项目的根目录中没有HTML文件。
我已经通过nuget和以下启动文件添加了OWIN:
[assembly: OwinStartup(typeof(MyApp.UI.Startup))]
namespace MyApp.UI
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
string root = AppDomain.CurrentDomain.BaseDirectory;
var physicalFileSystem = new PhysicalFileSystem(Path.Combine(root, "wwwroot"));
var options = new FileServerOptions
{
EnableDefaultFiles = true,
FileSystem = physicalFileSystem
};
options.StaticFileOptions.FileSystem = physicalFileSystem;
options.StaticFileOptions.ServeUnknownFileTypes = false;
options.DefaultFilesOptions.DefaultFileNames = new[] {"index.html"};
app.UseFileServer(options);
}
}
}
不过,这失败了——当我运行这个程序时,我的index.html文件的源确实加载了,但它引用的所有css、js等文件都失败了,返回404。更糟糕的是,如果我将gullfile.js附加到根url上,它会从项目文件夹的根加载我的gull文件。这正是我试图避免的事情。
有什么想法吗?
我相信我现在有了这样做的工作方法。花了一些谷歌搜索和实验,但最终我想出了以下过程:
-
在VS2015中创建一个新的ASP.NET 4.5项目,选择空模板
-
通过nuget(
Install-Package Microsoft.Owin.Host.SystemWeb
和Microsoft.Owin.StaticFiles
)添加OWIN引用 -
添加一个类似的启动文件:
[assembly: OwinStartup(typeof(MyApp.Startup))] namespace MyApp.UI { public class Startup { public void Configuration(IAppBuilder app) { string root = AppDomain.CurrentDomain.BaseDirectory; var physicalFileSystem = new PhysicalFileSystem(Path.Combine(root, "wwwroot")); var options = new FileServerOptions { RequestPath = PathString.Empty, EnableDefaultFiles = true, FileSystem = physicalFileSystem }; options.StaticFileOptions.FileSystem = physicalFileSystem; options.StaticFileOptions.ServeUnknownFileTypes = false; app.UseFileServer(options); } } }
-
将以下内容添加到web.config文件中,以防止IIS为您不希望的静态文件提供服务,并强制所有内容通过OWIN管道:
<system.webServer> <handlers> <remove name="StaticFile"/> <add name="Owin" verb="" path="*" type="Microsoft.Owin.Host.SystemWeb.OwinHttpHandler, Microsoft.Owin.Host.SystemWeb"/> </handlers> </system.webServer>
关于如何做到这一点,我总是乐于接受更好的建议,但这似乎至少对我有效
尽管OWIN在VS 2017中运行的开发环境中对我有效,但一旦部署到azure,它就不起作用了。我们也运行了一个SPA,并将webpack输出存储在~/wwwwroot/中,但希望它像在项目根目录中一样加载~/,就像.net core webapi所做的那样。我只使用如下所示的URL重写就完成了它:
<system.webServer>
<rewrite>
<rules>
<rule name="wwwRootFix" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{APPL_PHYSICAL_PATH}wwwroot{R:1}" matchType="IsFile" />
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(wwwroot)" negate="true" />
</conditions>
<action type="Redirect" url="/wwwroot/{R:1}" />
</rule>
<rule name="React Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(wwwroot)" negate="true" />
</conditions>
<action type="Rewrite" url="/wwwroot/index.html" />
</rule>
</rules>
</rewrite>
</system.webServer>
第一条规则确保您要查找的文件不存在于根目录中,不是文件夹,在新路径中找到,不是wwwroot文件夹,也不是api的一部分。如果满足所有这些条件,它将尝试从wwwroot加载数据。
第二条规则进行检查,以确保您没有试图加载api或根目录中实际存在的文件。如果这两个条件都满足,它将加载默认的SPA.html文档(在我们的案例中,我们使用react)。
有效地,这允许反应路由器4在上述所有其他条件都未能找到匹配之后处理所有其他路由,并使其在尝试加载反应路由器路由之一时不会抛出404错误。
如果您想为此使用IIS,可以创建一个重写规则:
<system.webServer>
<rewrite>
<rules>
<rule name="RewriteUnknownToIndex" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^wwwroot/.*" negate="true" />
<action type="Rewrite" url="/wwwroot/index.html" />
</rule>
</rules>
</rewrite>
</system.webServer>
如果这是一个您想在/api上托管的web api,您也可以向url regex添加前缀,例如^(wwwroot|api)/.*
。