Updating to SS 8.1+ - client still requesting /json/reply

I’m working through updating from SS 6 to 8.5. I have mostly everything working, and am to a point where I’m testing my UI calling my API, but keep running into an issue where it can’t find the /json/reply endpoint.

image

The above is using a JsonServiceClient in JavaScript. Is there something I need to do to add all the /json/reply handlers?

But if I use the SS UI API browser, it hits /api/GetEnvironment and works as expected:

Program.cs startup:

using LENSSX.ServiceInterface;
using Serilog;

var builder = WebApplication.CreateBuilder(args);

Log.Logger = new LoggerConfiguration()
    .Enrich.FromLogContext()
    .WriteTo.Console()
    .CreateBootstrapLogger();

builder.Logging.ClearProviders();
builder.Services.AddServiceStack(typeof(UserService).Assembly);

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
    app.UseHttpsRedirection();
}
else
{
    app.UseDeveloperExceptionPage();
}
app.UseServiceStack(new AppHost(), options =>
{
    options.MapEndpoints();
});

app.Run();

The endpoint defined on the DTO is “/api/Environment”. I guess I’m confused which should be the canonical endpoint that clients should hit. Why does JsonServiceClient use /json/reply?

/json/reply is the legacy pre-defined route and the JsonServiceClient is the legacy ServiceClient, for .NET 6+ it’s recommended to use JsonApiClient which is configured to use the newer /api predefined route which is the only pre-defined route available when using Endpoint Routing.

If needed see the docs for how to configure the legacy JsonServiceClient to use the new /api pre-defined routes.

Ahhh ok, I see. I was still using the legacy client in JS.

The only other issue I’m encountering is it says ambiguous match on some of my endpoints and throws an exception.

Could it be because of the endpoint routing?

I was referring to C# JsonServiceClient/JsonApiClient, for JS you’d need to upgrade to the latest version which has switched to use /api predefined route.

I don’t know what Exception you’re referring to, look at the StackTrace and see if you can find the ambiguous routes in your code base.

Here is the endpoint definition:

image

I figured it out, whoever wrote this endpoint routed to /api/GetSiteConfiguration, instead of our typical pattern of /api/SiteConfiguration, which I believe collided with ServiceStacks mapping of /api/{DtoName} (since the DTO is named GetSiteConfiguration).

Once I changed the name of the URL to /api/SiteConfiguration GET/POST it started working.

If you want it to work with /api/SiteConfiguration you don’t even need a user-defined [Route] as you can rename the DTO SiteConfiguration. Although possible, in general I wouldn’t recommend using /api/* for user-defined routes. i.e better to use the default /api predefined route or use a different prefix for user-defined routes so it’s clear that all /api/* endpoints use the predefined route and anything else uses the user defined route.

Also note that all APIs have a Primary HTTP Method, i.e. if you want it available from GET you’d need to have it implement the IGet interface marker.

Hrmm, I have quite a few DTOs defined this way, which was probably done around 2017 / 2019.

For now I’ve got to get through this update, but I will come back and use the marker interfaces.

If I rename my Dto from GetSiteConfiguration to just “SiteConfiguration”, how will I have different entities for Get and Save? How will I delineate between a Get (singular) and Post (update) other than in my service method names.

The pattern for my project is:

public class GetEntity : IReturn<Entity> {
  public int Id {get;set;}
}

public class SearchEntities {
  public int[] Ids {get; set; }
  public string FirstNameStartsWith {get;set;}
}

public class CreateEntity { } 
public class UpdateEntity { }

My UI developers use the dtos.ts with this pattern.

EDIT:
But I do understand what you’re saying now - SS uses the /api/* base route for all {DtoName} endpoints for use with clients, and I’m littering that namespace (or causing conflicts in them). Hrmmm, I’ve probably got around 600 DTOs, I’ll have to think on this one. So far no one outside of my UI (and the ss js client) is using this API, but we are building it out for public developer consumption next. So I’ll need to fix this for sure.

Every Request DTO is unique so every route would also be unique, e.g. /api/GetEntity and /api/CreateEntity