我正在构建客户端/服务器解决方案,使用AngularJS单页面应用程序作为客户端组件,并使用自主机ServiceStack RESTful API作为服务器组件。单个Visual Studio控制台应用程序项目包含AngularJS组件的HTML和JavaScript文件,以及用于引导ServiceStack AppHost的C#类(我已将接口和服务职责分配给单独的Visual Studio项目)。
我已将所有HTML和JavaScript文件设置为“构建操作”为“无”,并将“复制到输出目录”设置为“如果更新则复制”。
只要我准备好在我的网站网址中加上“#”,一切都很顺利。我想通过使用HTML5 pushstate URL消除这种情况。
实际上,这意味着每当请求不存在的路由时,我需要说服ServiceStack提供我的默认单页面应用程序HTML shell页面。现在有一个FallbackRoute属性available in ServiceStack,似乎已经为此目的添加了。{/ p>
但是,我不确定如何使用它。我发现有人提出类似的问题here,here和here。但是所给出的答案都是在新的FallbackRoute属性到来之前。
基本上,我正在寻找一个简单但完整的示例,说明如何使用FallbackRoute属性来确保对不存在的路由的任何请求被重定向到单个静态HTML页面。
答案 0 :(得分:4)
RazorRockstars.Web有一个实现。我将修改它以使用通配符路径和默认视图:
[FallbackRoute("/{Path*}")]
public class Fallback
{
public string Path { get; set; }
public string PathInfo { get; set; }
}
public class RockstarsService : Service
{
[DefaultView("Index")]
public object Any(Fallback request)
{
request.PathInfo = base.Request.PathInfo;
return request;
}
// ...
}
由于这是一项服务,因此需要查看页面(details here)而不是内容页面。
在RockStars示例中,我无法确定为FallBackResponse呈现的视图,但显式设置视图应该是您所需要的。
我添加到[DefaultView("Index")]
方法的Any
属性将响应映射到Views / Index.cshtml文件。 Index.cshtml文件可以为空,但是对于模板声明,单页应用程序的完整标记可以在您的模板文件中(即_Layout.cshtml)
没有Razor
将html读入字符串并将其返回,同时将内容类型设置为带有属性的“text / html”,请参阅wiki docs on service return types
public class RockstarsService : Service
{
static string readContents;
[AddHeader(ContentType = "text/html")]
public string Any(Fallback request)
{
// check timestamp for changes for production use
if (readContents == '') {
using (StreamReader streamReader = new StreamReader(pathFromConfigFile, Encoding.UTF8))
{
readContents = streamReader.ReadToEnd();
}
}
return readContents;
}
// ...
}
答案 1 :(得分:4)
事实证明,使用FallbackRoute功能非常简单,一旦你弄清楚如何正确使用它:
[FallbackRoute("/{Path*}")]
public class Fallback
{
public string Path { get; set; }
}
public class FallBackService : Service
{
public object Any(Fallback request)
{
return new HttpResult(new FileInfo("index.html")) {ContentType = "text/html"};
}
}
一旦这个到位,我发现每当我试图找到一条不存在的路线时,'index.html'确实会被提供。
任何静态文件(例如JavaScript和CSS资源)都会正常提供(只要它们具有'复制到输出目录'设置'当更新时复制',当然)。
这就像AngularJS中的HTML5推送状态功能一样。