在 ASP.NET 4.5 项目中使用 wwwroot 文件夹(ASP.NET 核心风格)
Using a wwwroot folder (ASP.NET Core style) in ASP.NET 4.5 project
我非常喜欢新的 asp.net (asp.net 5\core 1.0) 网络应用程序的方法,其中 wwwroot 文件夹是根目录,并且只提供其中的静态文件。
可以通过路由或其他配置使 asp.net 4.5 项目中的 wwwroot 文件夹以类似的方式运行,这样静态文件仅从中提供,它是 "root" 用于静态文件的 webapp?
(我提出这个问题的部分动机是我有一个 angular 应用程序托管在 VS2015 的 asp.net 5 项目中,但我需要将其移动到 asp.net 4.5 项目,但希望保留磁盘上的现有结构)
尝试使用 OWIN
我尝试使用一个空的 ASP.NET 4.5 网络应用程序项目和 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更糟糕的是,如果我将 gulpfile.js 附加到根目录 url 上,它会从项目文件夹的根目录加载我的 gulp 文件。这正是我要避免的事情。
有什么想法吗?
我相信我现在有一个可行的方法来做这件事。进行了一些谷歌搜索和实验,但最后我想出了以下过程:
在 VS2015 中新建一个 ASP.NET 4.5 项目,选择空模板
通过 nuget 添加 OWIN 引用(Install-Package Microsoft.Owin.Host.SystemWeb
和 Microsoft.Owin.StaticFiles
)
添加类似这样的启动文件:
[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>
我总是乐于接受更好的建议,但这至少对我有用。
如果您想为此使用 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>
您还可以向 url 正则表达式添加前缀,例如 ^(wwwroot|api)/.*
,如果这是您希望托管在 /[=16 的网络 api =].
虽然 OWIN 在我的开发环境中为我工作 运行ning 在 VS 2017 中,但一旦部署到 Azure,它就无法工作。我们 运行 也是一个 SPA,并且将 webpack 输出存储在 ~/wwwroot/ 但希望它像在项目根目录 ~/ 中一样加载,就像 .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)。
实际上,这允许 react-router 4 在上述所有其他条件都找不到匹配项后处理所有其他路由,并使其在尝试加载其中一个反应时不会抛出 404 错误-路由器路由。
我非常喜欢新的 asp.net (asp.net 5\core 1.0) 网络应用程序的方法,其中 wwwroot 文件夹是根目录,并且只提供其中的静态文件。
可以通过路由或其他配置使 asp.net 4.5 项目中的 wwwroot 文件夹以类似的方式运行,这样静态文件仅从中提供,它是 "root" 用于静态文件的 webapp?
(我提出这个问题的部分动机是我有一个 angular 应用程序托管在 VS2015 的 asp.net 5 项目中,但我需要将其移动到 asp.net 4.5 项目,但希望保留磁盘上的现有结构)
尝试使用 OWIN
我尝试使用一个空的 ASP.NET 4.5 网络应用程序项目和 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更糟糕的是,如果我将 gulpfile.js 附加到根目录 url 上,它会从项目文件夹的根目录加载我的 gulp 文件。这正是我要避免的事情。
有什么想法吗?
我相信我现在有一个可行的方法来做这件事。进行了一些谷歌搜索和实验,但最后我想出了以下过程:
在 VS2015 中新建一个 ASP.NET 4.5 项目,选择空模板
通过 nuget 添加 OWIN 引用(
Install-Package Microsoft.Owin.Host.SystemWeb
和Microsoft.Owin.StaticFiles
)添加类似这样的启动文件:
[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>
我总是乐于接受更好的建议,但这至少对我有用。
如果您想为此使用 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>
您还可以向 url 正则表达式添加前缀,例如 ^(wwwroot|api)/.*
,如果这是您希望托管在 /[=16 的网络 api =].
虽然 OWIN 在我的开发环境中为我工作 运行ning 在 VS 2017 中,但一旦部署到 Azure,它就无法工作。我们 运行 也是一个 SPA,并且将 webpack 输出存储在 ~/wwwroot/ 但希望它像在项目根目录 ~/ 中一样加载,就像 .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)。
实际上,这允许 react-router 4 在上述所有其他条件都找不到匹配项后处理所有其他路由,并使其在尝试加载其中一个反应时不会抛出 404 错误-路由器路由。