Take the 2-minute tour ×

I have a very basic html form being rendered in a ServiceStack.Razor ViewPage:

<form action="@Href("~/subfolder/someservice")" method="POST">

It works fine when running from my local IIS inside a virtual app directory. However once deployed to AppHarbor, I get this error:

The relative virtual path 'http:/myssrazorapp.apphb.com/subfolder/someservice' is not allowed here.

[ArgumentException: The relative virtual path 'http:/myssrazorapp.apphb.com/subfolder/someservice' is not allowed here.]
System.Web.VirtualPath.Create(String virtualPath, VirtualPathOptions options) +877
System.Web.VirtualPath.CreateNonRelative(String virtualPath) +9
System.Web.VirtualPathUtility.ToAbsolute(String virtualPath) +8
ServiceStack.Html.UrlHelper.Content(String url) +6
ServiceStack.Razor.ViewPageBase`1.Href(String url) +10
CompiledRazorTemplates.Dynamic.dbbfcbafad.Execute() +291
ServiceStack.Razor.Templating.TemplateService.ExecuteTemplate(T model, String name, String defaultTemplatePath, IHttpRequest httpReq, IHttpResponse httpRes) +149
ServiceStack.Razor.RazorFormat.ExecuteTemplate(T model, String name, String templatePath, IHttpRequest httpReq, IHttpResponse httpRes) +80
ServiceStack.Razor.RazorFormat.ProcessRazorPage(IHttpRequest httpReq, ViewPageRef razorPage, Object dto, IHttpResponse httpRes) +50
ServiceStack.Razor.RazorHandler.ProcessRequest(IHttpRequest httpReq, IHttpResponse httpRes, String operationName) +366
ServiceStack.WebHost.Endpoints.Support.EndpointHandlerBase.ProcessRequest(HttpContext context) +164
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +859
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +131

I've looked through the source code (ViewPageBase.Href and UrlHelper.Content) and all they do is pass the raw string through to VirtualPathUtility.ToAbsolute. I can't explain what would cause this apart from the AppHarbor environment somehow affecting what VirtualPathUtility does.

The weird thing with the error is the http:/ prefix is missing one of the forward slashes. Not sure if that raises any hints for anyone?

share|improve this question

3 Answers 3

If you don't want any replace tokens in the RazorFormat, than just remove it from the Razor plugin, e.g:

Plugins.Add(new RazorFormat { ReplaceTokens=new Dictionary<string,string>() }); 
share|improve this answer

Why dont you try something like this instead of what your doing

<form action="@Url.Action("ActionName","Controller",new{Area=""})" method="POST">

share|improve this answer
Thanks, but this is ServiceStack.Razor, not MVC Razor. There are no controllers or actions, just service endpoints that map to request/response DTO pairs. You do remind me of a good point though, I shouldn't be hard coding the route to that service in the view as its already defined as an attribute of the request DTO. I should have a helper method that reads it from the DTO - this is actually part of the plan but I havnt implemented it yet. Still, the above should also work (that href path could also be a static file). –  Tyson Jan 5 '13 at 23:41

Turns out this is a bug in ServiceStack when using the ServiceStack.Razor view engine combined with VirtualPathUtility related "~" usages combined with a EndpointHostConfig.WebHostUrl setting.

A pre-compile step of the SS razor views do some content rewriting to the raw text that makes up the template before being passed to the Razor compiler:

private string ReplaceContentWithRewriteTokens(string contents)
    foreach (var replaceToken in ReplaceTokens)
        contents = contents.Replace(replaceToken.Key, replaceToken.Value);
    return contents;

One of these tokens is automatically specified if a related WebHostUrl config option is set:

var webHostUrl = appHost.Config.WebHostUrl;
if (!webHostUrl.IsNullOrEmpty())
    this.ReplaceTokens["~/"] = webHostUrl.WithTrailingSlash();

Which means doing as I did above in a template:


with EndpointHostConfig.WebHostUrl = "http://myssrazorapp.apphb.com"

ends up with a template looking like the following being passed to the Razor compiler:

<form action="@Href("http://myssrazorapp.apphb.com/subfolder/someservice")" method="POST">

At runtime Href calls into VirtualPathUtility.ToAbsolute with that absolute url which obviously throws as it expects a relative path.

share|improve this answer

Your Answer


