URL-адреса push-состояния HTML5 на ServiceStack
В настоящее время мы используем представление default.cshtml в корне ServiceStack для обслуживания нашего одностраничного приложения AngularJS.
То, что я хотел бы сделать, это включить поддержку hstml5 pushstate (поэтому в URL нет хэша), но единственные примеры, которые я обнаружил, пока включают зависимость от MVC с подстановочным маршрутом и передачу инфраструктуры ServiceStack в / Api Subroute.
Мы не можем взять зависимость MVC, поэтому я думаю, что нам нужно для запросов accept:text/html, нам нужно принять любой URL и обслуживать наше корневое приложение. Я был бы рад удалить расширение HtmlFormat по умолчанию или переопределить его (мы могли бы по-прежнему использовать его тип контента JsonReport, который нам нужен).
Как я могу лучше всего подойти к этому?
2 ответа
На вики-странице Order of Operations показано количество различных хуков, которые вы можете использовать, чтобы ввести свое собственное настроенное поведение, а также порядок их запуска.
Hi-Jacking запросы с RawHttpHandlers
Вы можете полностью обойти ServiceStack, добавив Config.RawHttpHandlers
вернуть IHttpHandler
на запросы, которые вы хотите использовать для hi-jack, например, так встроенный мини-профилировщик hi-jack обрабатывает все запросы на файлы, которые начинаются с ssr-
и возвращает физический файл:
config.RawHttpHandlers.Add((IHttpRequest request) => {
var file = GetFileNameWithoutExtension(request.PathInfo);
return file != null && file.StartsWith("ssr-")
? new MiniProfilerHandler()
: null;
}
Предоставление резервного обработчика для несоответствующих маршрутов
Если вы хотите предоставить обработчик по умолчанию для несоответствующего маршрута, вы можете зарегистрировать CatchAllHandlers в AppHost.Configure()
или в плагине с:
appHost.CatchAllHandlers.Add((string method, string pathInfo, string filepath) =>
{
return ShouldProvideDefaultPage(pathInfo)
? new RazorHandler("/defaultpage.cshtml")
: null;
});
Использование подстановочного знака для принятия любого URL в сервисе
Вы можете создать фиктивный сервис и просто вернуть тот же единственный вид, например:
[Route("/app/{PathInfo*}")]
public class App {
public string PathInfo { get; set; }
}
public class MyService : Service
{
public object Any(App request)
{
return request;
}
}
С помощью подстановочного знака этот сервис вернет вид, например /View/App.cshtml
на любом маршруте, начиная с /app
Например:
- /приложение
- / Приложение / привет
- / Приложение / привет / мой / имя / это? Foo = бар
Частичная поддержка страницы
Поскольку частичные перезагрузки связаны с pushstate, я также упомяну встроенную поддержку ServiceStack для частичных перезагрузок.
ServiceStack Docs - это пример демонстрации, в которой используется pushstate в браузерах, которые его поддерживают, в противном случае он вынужден использовать полностраничные перезагрузки в браузерах, которые этого не делают.
Вы можете попросить частичную страницу с ?format=text.bare
парам, например
- Полная страница: http://www.servicestack.net/docs/markdown/about
- Неполная страница: http://www.servicestack.net/docs/markdown/about?format=html.bare
- Частичная разметка страницы: http://www.servicestack.net/docs/markdown/about?format=text.bare
Хотя для этого используется Markdown Razor. В последней поддержке ServiceStack.Razor вы можете получить доступ к частичной странице с помощью: ?format=bare
Расширяю свой комментарий. Это то, что я закончил тем, что попытался разместить приложение в /app, также поддерживая виртуальную файловую систему.
host.CatchAllHandlers.Add((string method, string pathInfo, string filepath) =>
{
if (!Regex.IsMatch(pathInfo, "^/app([/?]|$)"))
return null;
// Serve valid requests as is
var vFile = HostContext.ResolveVirtualFile(pathInfo, null);
if (vFile != null)
return null;
var vDir = HostContext.ResolveVirtualDirectory(pathInfo, null);
if (vDir != null && vDir.GetDefaultDocument() != null)
return null;
// Fallback to default document
var vDef = HostContext.ResolveVirtualDirectory("/app/", null).GetDefaultDocument();
return new CustomResponseHandler((req, res) =>
new HttpResult(vDef.OpenRead(), MimeTypes.GetMimeType(vDef.Name)));
});