ServiceStack.Client 5.92 update to 6.11, predefined route problem

Hi.

Using JsonServiceClient

  • I updated ServiceStack.Client 5.92 to 6.11
  • Server API has not (yet) been updated

I have a RequestDto like so

   [Route("/analysebatch/{Id}", "PATCH")]
public class PatchAnalyseBatch : IReturn<GetAnalyseBatchResponse>
{
    public Guid? Id { get; set; }
    public string Name { get; set; }
    public Guid? LaboratoryId { get; set; }
    public string[] Codes { get; set; }
    public bool? Test { get; set; }
    public AnalyseBatchStatusEnum? Status { get; set; }
    public List<AnalyseBatchParameter> Parameters { get; set; }
    public DateTime? LabSent { get; set; }
    /// <summary>
    /// Tevens Intermediair
    /// </summary>
    public Guid? TenantId { get; set; }
    public Dictionary<string, string> Meta { get; set; }
}

Handled in the interface like so

        [Authenticate]
        public object Any(PatchAnalyseBatch request)

Now i send an request with the .Send of the JsonServiceClient
In version 5.92 it would do an POST to de defaultendpoint:

POST https://something.special.nl/json/reply/PatchAnalyseBatch HTTP/1.1
Accept: application/json
User-Agent: ServiceStack .NET Client 5.92
Accept-Encoding: gzip,deflate
Content-Type: application/json
Host: something.special
Cookie: ss-pid=pSnAWyVxTizeJggZ8f4g; ss-id=BIRmStsmL55Vrz2f9LPJ; ss-opt=temp; X-UAId=7
Authorization: Basic dHBfZGVtbzp0cF9kZW1v
Content-Length: 62
Expect: 100-continue

{"Id":"4b72efbee2dd495696004f3e9d4ec271","Status":"Verzenden"}

after update to 6.11 the route looks like this:

PATCH https://something.special/analysebatch/4b72efbee2dd495696004f3e9d4ec271 HTTP/1.1
Accept: application/json
User-Agent: ServiceStackClient/6.110
Accept-Encoding: gzip,deflate
Content-Type: application/json
Host: something.special
Cookie: ss-pid=Xe7gC7YHgaicnGe3YLnB; ss-id=kLarvbynzZdufTOZ5mfm; ss-opt=temp; X-UAId=7
Authorization: Basic dHBfZGVtbzp0cF9kZW1v
Content-Length: 62
Expect: 100-continue

{"Id":"4b72efbee2dd495696004f3e9d4ec271","Status":"Verzenden"}

So; it started using the predefined route. Should not be a problem, but on the server side the request comes in incomplete.

5.9.2:

6.110

What could be the reason of this?

The JsonServiceClient is using the best matching user-defined route if one exists and if you use Send it will use Primary Default Method, which since you only have “PATCH” on your single user-defined route it will use that. You can have your Request DTO implement IPost if you want it to use POST, otherwise you can explicitly send the Request DTO with client.Post()

Is the incomplete part you’re referring to the enum? By default the JSON Serializer doesn’t serialize default values but as the enum is nullable it should be be populated since the default value would be null instead of the default enum value.

Not sure why it’s not getting populated, Is Verzenden the default value of the enum? If it is does is the Request DTO property populated with it? Does it work any other enum value?

Can you also enable Strict Mode to ensure all Serialization errors are thrown.

Env.StrictMode = true;

Can you also provide your AnalyseBatchStatusEnum enum and I’ll check if I can repro the serialization issue.

Hi!

Yes, i’m referring to the enum value not beeing sent.
The request that’s been done in code clientside is:

var response  = client.Send(new PatchAnalyseBatch
                              {
                                  Id = analyseBatch.Id,
                                  Status = AnalyseBatchStatusEnum.Verzenden
                              }).Response;

The Enum is like so

[EnumAsInt]
public enum AnalyseBatchStatusEnum
{
    Concept,
    Verzenden,
    Verzonden,
    Ontvangen,
    Analyseren,
    Afgerond
}

It however seems strange to me that the update caused it to revert to using de predefined route al of a sudden.

I’ve seent his happen too on another part of the application after this update, different class, wouldnt sent all properties either anymore, and also has reverted to using the predefined route.

Just tried setting the

Env.StrictMode = true;

but that doesn’t make a difference.

Makes sense too as the data itsself is not sent different between these versions.
(as you can see in above raw requests recorded in Fiddler)

Is there a way to force the client to use the default endpoint?

The .NET Service Clients will use the best matching user-defined Route if one exists, which it’s been doing for years, not sure when this behavior was added but v5.9.2 is a fairly old version.

You can force it to use the pre-defined routes by removing the user-defined [Route] attribute from the Request DTO or you could use a TypedUrlResolver, e.g:

var client = new JsonServiceClient(BaseUrl)
{
    TypedUrlResolver = (client, method, request) => method is "POST" or "PATCH" 
        ? client.SyncReplyBaseUri.CombineWith(request.GetType().Name)
        : null
};
var response = client.Send(new PatchAnalyseBatch());

I’m unable to repro this issue. If you can upload a minimal stand-alone repro on GitHub that reproduces this Issue I can take a look.

New finding.

Following some best practices, i made a change to server in the application pool in IIS.
Switching from .NET CLR Version v4.0.30319 to ‘No Managed Code’, as its a netcore api.
image

Then; the request comes through in full, as expected, both in the POST to the default endpoint, as the PATCH to de predefined route.

Is there something to be said about that?

Yeah it looks like it’s an issue with IIS:

Looks like you could also add it to Request Restrictions to enable PATCH Requests:

H67nz

Interesting.

This change however does not have the same effect on my machine, PATCH request is still empty.
I will run some other tests.

1 Like