📜 ⬆️ ⬇️

I want from API a line, and a point, and a point

Hello.

Many probably had to design and develop a RESTful API in their lives. With the release of the Web API technology, this has become much easier, and with the release of Web API 2 it’s also much more pleasant. The routing system, migrated from ASP.NET MVC, does an excellent job with its task, and allows us not only to freely construct paths, but also to spice them up with various parameters, indicating them in curly brackets. It is unlikely that a template like “api / {controller} / {id}” causes anyone to be reverently awed. However, what happens if one of our API's methods as this {id} itself does not accept a number in a string representation, not a Guid, but, say, an email address? Well, for example, to check the presence of this address in the database. Then nothing will work, but the fault is a small and seemingly completely harmless point. How to live with it further and is told under the cut.


')
Immediately it is worth making a reservation that the very existence of the problem is not that far-fetched, but, let's say, easily walked in two completely standard ways:
- no need to stand, email can be transferred to the model;
- no need to emit, email can be passed as a parameter to the query string.

On the other hand, when e-mail is precisely that identifier, it seems to be more logical and ideologically to place it on a path, and not in a model or attribute. However, I am sure you can argue and debate on this topic for a long time, we are faced with a very specific problem: the presence of a dot in the email leads to the 404th error. The root cause, I think, is completely transparent: the web server is trying to search for a file (the exact same point), but of course there is no such file.

How can this be dealt with? There are many ways, they are all different, probably not even all possible ones will appear below (I hope, comments to help us).

Method 1.

Slash If we add it to the end of the path after our {id} parameter, everything will suddenly work. This is because this segment will be understood not as a file name, but as a folder name. The solution is very simple, but not very, you see, beautiful, because you have to inform the service consumer that it is necessary to put a slash at the end for this method, but not for others at all (yes, nobody usually puts them). Here it is worth mentioning another interesting point related to folders and points. If we put a dot at the end of the segment right before the slash, we also get 404. They can’t say that folder names in post-MSDOS systems (and their legs grow from there) end in a full stop. For the same reason, the following literals are used in the path of nonella: COM1-9, LPT1-9, AUX, PRT, NUL, CON. There is, of course, a way to get around this, in particular by using the attribute

<httpRuntime relaxedUrlToFileSystemMapping="true" /> 

Method 2

In the system.webServer section of the configuration file, we write

 <modules runAllManagedModulesForAllRequests="true" /> 

and voila, everything works. The bad way is very bad, although many people recommend it right away. Sometime without this option, it was really just impossible to do, but by and large it means that instead of native modules to get static content, such as images, CSS, scripts, etc., each request will pass through the entire set of managed modules your application, which is fraught with significant performance losses, at a minimum. That is why such a solution is a kind of such “brute force”.

Method 3.

We can achieve the desired effect with the following setting in the same configuration file:

 <modules> <remove name="UrlRoutingModule-4.0" /> <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" /> </modules> 

The point here is that we clear the preCondition attribute of the UrlRoutingModule, thus allowing this managed module to handle all incoming requests. The method is very similar to the previous one with the only difference that there every request was processed by all control modules, and here only one. Horseradish, in general, radish is not sweeter.

Method 4.

Back in 2010, Microsoft released a patch for IIS 7.0 and 7.5, which allowed handlers with the path attribute = "*." understand not only the path ending point, but the path without it. So the era of the so-called. extensionless URLs, and our way number two is no longer relevant. The patch description, by the way, can be found here . Now, in your web.config, you can easily find a similar entry in the handlers section:

 <remove name="ExtensionlessUrlHandler-Integrated-4.0" /> <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> 

How does this solve our problem? Yes, in general, nothing. Unless we change the value of the path attribute to a lonely asterisk. It is also a kind of way out, and our email will even work, though we will not get a single file with the extension, because we will get a fair 500th error from the same handler.

The question arises: so what to do? The answer to it alone may not be. The best solution in my highly personal opinion here is to use the latter method, but only partially. Let's say if we know that all the paths to methods (and only methods, not static resources!) APIs start with the corresponding prefix (“api / {controller} / {id}”), then we can add another handler of the same Type for addresses like "api / *":

 <remove name="ExtensionlessUrlHandler-Integrated-4.0" /> <add name="API-ExtensionlessUrlHandler-Integrated-4.0" path="api/*" verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> 

Thus, we, as they say, separate flies from cutlets at the API design level.

PS If anyone has other ways of solving this problem, as well as additional information and explanations, then the comments on their own and not only their own clever ideas are welcome in every way. Thanks for attention.

Source: https://habr.com/ru/post/254525/


All Articles