CoreWCF / CoreWCF

Main repository for the Core WCF project
MIT License
1.62k stars 281 forks source link

Enpoints with same prefix lead to 400 Bad Request #679

Open oruchreis opened 2 years ago

oruchreis commented 2 years ago

Hi, I'm trying to migrate our old wcf service to coreWCF. Old Wcf service has these endpoints:

This configuration works in old wcf service successfully. I've added same endpoint and binding configuration with AddServiceEndpoint method at startup in the coreWcf app. But I couldn't make a request to the endpoints end with /soap and /binary because of 400 bad request. I've debugged into the source of coreWCF and I saw these lines: https://github.com/CoreWCF/CoreWCF/blob/40610b671b75b145f2b90f39be713712bb4c69c8/src/CoreWCF.Http/src/CoreWCF/Channels/ServiceModelHttpMiddleware.cs#L163 So the endpoint with WsHttpBinding catches all requests because it starts with AService. I don't know if this is a bug or intended behavior, but old wcf doesn't behave like this. For a workaround, I've added the /AService endpoint with WsHttpBinding as the last element of the endpoints, but coreWCF should handle this scenario like old wcf or it should throw an ambigious route exception.

mconnew commented 2 years ago

This is a side effect of using the asp.net core mapping capabilities compared with .NET Framework. We have another data structure we use which is like a hierarchical map to find the best match. Luckily there's an easy solution, change the order that you call AddServiceEndpoint to have the longest paths first. Add them in the order /AService/soap, /AService/binary, /AService and the mapping setup for asp.net core will attempt to match your soap and binary endpoints before your WSHttp endpoint. You will have the same behavior if you were mapping things yourself in asp.net core:

app.Map("/AService", mapapp => { mapapp.UseMyApp(); });
app.Map("/AService/longerpath", mapapp => { mapapp.UseMyOtherApp(); });

This would cause MyApp to shadow MyOtherApp. We could maybe sort everything in reverse ordinal order and then map them. I'm not sure if that's a better situation though. It's a tough call between doing something smarter which could have a scenario which hasn't been considered and now is difficult to work around, or blindly doing things in the same order that the application code is doing them.

skurth commented 2 years ago

I think this is the same issue like we have: #669

While the requests work when setting the longest path first to BasicHttpBinding, WSHttpBinding and WebHttpBinding endpoints, when trying to refresh the client service reference, it fails with 400 Bad Request (for ...?wsdl and also for .../mex).

As a work-around we remove endpoint with WebHttpBinding and refresh service reference in client and add WebHttpBinding endpoint after that again.