Updated on 6月 4, 2020
Owin 自托管 支持访问静态文件
公司在弄一个项目,需要用到C#通过Owin自托管启动一个Web服务,并且需要同时提供静态页面和WebAPI
搜索网上Owin自托管的相关文章,都是一个抄一个的,都没有什么深刻的讲解,比如下面这个Owin托管静态文件的例子:
public void Configuration(IAppBuilder appBuilder)
{
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}",
defaults: new { id = RouteParameter.Optional }
);
appBuilder.Map("wwwroot", map =>
{
map.UseStaticFile(new StaticFileMiddlewareOptions()
{
RootDirectory = "./wwwroot",
DefaultFile = "index.html",
EnableETag = true,
EnableHtml5LocationMode = true,
MimeTypeProvider = new MimeTypeProvider(new Dictionary<string, string>
{
{ ".html", "text/html" },
{ ".htm", "text/html" },
{ ".dtd", "text/xml" },
{ ".xml", "text/xml" },
{ ".ico", "image/x-icon" },
{ ".css", "text/css" },
{ ".js", "application/javascript" },
{ ".json", "application/json" },
{ ".jpg", "image/jpeg" },
{ ".png", "image/png" },
{ ".gif", "image/gif" },
{ ".config", "text/xml" },
{ ".woff2", "application/font-woff2"},
{ ".eot", "application/vnd.ms-fontobject" },
{ ".svg", "image/svg+xml" },
{ ".woff", "font/x-woff" },
{ ".txt", "text/plain" },
{ ".log", "text/plain" }
})
});
});
appBuilder.UseWebApi(config);
}
首先这个例子有个坑没说清楚,而且还有误导嫌疑,DefaultFile 的路径是相对于网站根路径的!举个例子,如果你把index.html放在wwwroot下,然后程序运行起来之后,你会发现这个DefaultFile压根不起作用,直接访问( http://localhost:9000/wwwroot )会返回404,而直接用完整路径(http://localhost:9000/wwwroot/index.html)就可以访问。
坑之二,RootDirectory可以使用相对路径。但是!!!这个相对路径跟你的程序当前的工作路径无关,它相对的是exe的所在路径。
另外,我们希望静态页面直接能在网页根路径下访问(http://localhost:9000),而不是要在后面再输一长串路径(这个需求应该很常见吧,为什么我百度半天都找不到一个例子!?)
带着思维定势,尝试将Map函数中传入的路径”wwwroot”改为空字符串””之后,网页的确可以在根路径下被访问了,但是WebAPI又访问不到了!
然后又经过一番折腾之后,终于搞明白了,其实没那么复杂,下面直接贴代码
public void Configuration(IAppBuilder appBuilder)
{
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}",
defaults: new { id = RouteParameter.Optional }
);
appBuilder.UseStaticFile(new StaticFileMiddlewareOptions()
{
RootDirectory = "wwwroot",
DefaultFile = "index.html",
EnableETag = true,
EnableHtml5LocationMode = true,
MimeTypeProvider = new MimeTypeProvider(new Dictionary<string, string>
{
{ ".html", "text/html" },
{ ".htm", "text/html" },
{ ".dtd", "text/xml" },
{ ".xml", "text/xml" },
{ ".ico", "image/x-icon" },
{ ".css", "text/css" },
{ ".js", "application/javascript" },
{ ".json", "application/json" },
{ ".jpg", "image/jpeg" },
{ ".png", "image/png" },
{ ".gif", "image/gif" },
{ ".config", "text/xml" },
{ ".woff2", "application/font-woff2" },
{ ".eot", "application/vnd.ms-fontobject" },
{ ".svg", "image/svg+xml" },
{ ".woff", "font/x-woff" },
{ ".txt", "text/plain" },
{ ".log", "text/plain" }
})
});
appBuilder.UseWebApi(config);
}