Cladoo
Cladoo

Reputation: 1124

Asp Core UsePathBase : how to deal with AJAX calls?

I want to host two version of my ASP Core website on the same VPS, one for each supplied environement (Staging and Test). I would like both web sites to be accessible from a subfolder of the same URL:

After reading a lot I found the following Github issue: https://github.com/aspnet/Hosting/issues/815

This tip works but for AJAX calls it crashes: Indeed, the JavaScript calls are not aware of this new path (BUG?). All requests are sent to the root base path (ignoring /Staging or /Test).

I partially solved it usig a middleware that redirects my AJAX calls to the correct path. It works for GET requests but it obviously fails for POST request that have a body.

Note that if we don't redirect, and just change the original PathBase request in the middleware, if the API call needs any authentication schema, it will throws a 401 error: The original PathBase is the root / where the response has a different path base, i.e. /Staging, then the cookie in the header prevents from this cross path base request/response.

Could someone tell me what is the recomanded practice to achieve my needs?

Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env
{
    app.UsePathBase($"/{env.EnvironmentName}");
    ...
}

My Middleware :

public async Task Invoke(HttpContext context)
{
    if (context.Request.Headers[RequestedWithHeader] == XmlHttpRequest)
    {
        if (string.IsNullOrEmpty(context.Request.PathBase))
        {
            if (context.Request.Method == HttpMethod.Post.Method)
            {

                // Do what ?
            }
            else
            {
                //Get request : set environement name + original path + original query string
                context.Response.Redirect(context.Request.Path.ToString().Insert(0, "/" + _env.EnvironmentName) + context.Request.QueryString);
                return;
            }
        }
    }
}

Upvotes: 1

Views: 3051

Answers (1)

poke
poke

Reputation: 388253

Of course, your client-side code will not be able to automatically change its code based on the path base that is active for the current request. JavaScript code is (usually) static content, so unless you actually rewrite the code dynamically, it cannot update URLs that are embedded inside.

You could determine the base path from the current request’s URL but that is a rather fragile solution since you need to find a logic that will work regardless of where in the application you are. So doing so is not recommended.

The overall problem is that on the client-side, there is no concept of a path base (or even an environment). So you will have to transfer that knowledge from the server to the client. And just like the path base is set for the server-side code using the path base middleware, you will need some server-side code that will pass the path base to the client-side code.

What I personally do is just configure the root path to the API in the application layout. So my _Layout.cshtml contains the following line:

<body data-api="@Url.Content("~/api/")">

That way, I can then retrieve the root path to the API using document.body.dataset.api in JavaScript. My AJAX calls are then all made so they respect that value. That way, I can host the site at any path, and the AJAX calls will use the proper path too.

You could also just use "~" as the content path to just refer to the root of your application. And you could also expose this value in a JavaScript variable inside a <script> block instead, if you prefer that.

Upvotes: 2

Related Questions