2

I've got a Fallback DTO that looks like the following:

[FallbackRoute("/{Path*}")]
public class Fallback
{
    public string Path { get; set; }
}

Now, in my Service I would like to redirect to an HTML5 compliant URL, and this is what I've tried:

public object Get(Fallback fallback)
{
    return this.Redirect("/#!/" + fallback.Path);
}

It is working all fine and dandy, except for the fact that query parameters are not passed along with the path. Using Request.QueryString does not work as no matter what I do it is empty. Here's what my current (non-working) solution looks like:

public object Get(Fallback fallback)
{
    StringBuilder sb = new StringBuilder("?");
    foreach (KeyValuePair<string, string> item in Request.QueryString)
    {
        sb.Append(item.Key).Append("=").Append(item.Value).Append("&");
    }
    var s = "/#!/" + fallback.Path + sb.ToString();
    return this.Redirect(s);
}

TL;DR: I want to pass on query strings along with fallback path.

EDIT: It turns out I had two problems; now going to mysite.com/url/that/does/not/exist?random=param correctly redirects the request to mysite.com/#!/url/that/does/not/exist?random=param& after I changed the above loop to:

foreach (string key in Request.QueryString)
{
    sb.Append(key).Append("=").Append(Request.QueryString[key]).Append("&");
}

But the fallback is still not being called at root, meaning mysite.com/?random=param won't trigger anything.

In essence, what I want to do is to have ServiceStack look for query strings at root, e.g., mysite.com/?key=value, apply some logic and then fire off a redirect. The purpose of this is in order for crawler bots to be able to query the site with a _escaped_fragment_ parameter and then be presented with an HTML snapshot prepared by a server. This is in order for the bots to be able to index single-page applications (more on this).

I'm thinking perhaps the FallbackRoute function won't cover this and I need to resort to overriding the CatchAllHandler.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
fsommar
  • 120
  • 1
  • 7

1 Answers1

3

I managed to find a solution thanks to this answer. First create an EndpointHostConfig object in your AppHost:

var config = new EndpointHostConfig
{
    ...
};

Then, add a RawHttpHandler:

config.RawHttpHandlers.Add(r =>
{
    var crawl = r.QueryString["_escaped_fragment_"];
    if (crawl != null)
    {
        HttpContext.Current.RewritePath("/location_of_snapshots/" + crawl);
    }
    return null;
});

Going to mysite.com/?_escaped_fragment_=home?key=value will fire off a redirection to mysite.com/location_of_snapshots/home?key=value, which should satisfy the AJAX crawling bots.

N.B. It's possible some logic needs to be applied to the redirection to ensure that there won't be double forward slashes. I have yet to test that.

Community
  • 1
  • 1
fsommar
  • 120
  • 1
  • 7