This is a very old question, but I hope this reference helps someone else.
Now we are using 'API Protector .NET' (https://apiprotector.net) to protect our APIs against DoS and DDoS attacks.
It's a library compatible with MVC, WebApi and .NetCore too, that has given us very good results, both in simplicity, but fundamentally in maintainability. With this lib you can protect each function of your API litterally with a single line, and in a very specific way.
As is explained in the website of API Protector .NET:
If you limit your API, in general way, to N requests per IP or per
user, it is enough for these N requests can be used to constantly
impact the same specific heavy function that can severely slow down
the entire service.
“Each function of your API must be restricted in a
particular way depending on the normal frequency of use and the cost
of processing which that function implies for the server, otherwise
you are not protecting your API.”
API Protector .NET allows you to protect each function of your .NET
API against DoS and DDoS attacks without effort, in a simple,
declarative and maintenable way.
The only negative point is that it costs USD 5, but it gave us what we was looking for at a very low price, unlike the WebApiThrottle library that although it was the first option I tried (because it is free), it ended up being impractical unmaintainable when we wanted to protect different functions in a specific way (which is critical for effective protection, as explained).
API Protector .NET allows to combine different protections (by ip, by user, by role, in general, etc) decorating each function with a single line, which makes it easy to implement and maintain. For a detailed explaination read: https://apiprotector.net/how-it-works
An interesting anecdote is that time ago, when we still protecting our APIs with WebApiThrottle, we did some tests simulating DDoS attacks, with many parallel requests from different hosts, and for some reason, (I think that is due to something related to thread synchronization), bursts of requests came in to the functions, and late with the server already overloaded, the throttling started. This, added to the difficult maintainability, did not give us too much confidence for a solid protection, and that's why we ended up trying this alternative that works well.