REST based Response Status codes - c#

I'm not sure what response code to use when the request is valid but there is no result for the given parameter
The JSON returns a success of true/false and a message
When I do a GET and there is some data I use:
200 HttpStatusCode.OK
However where there is no data should I still use OK and return the JSON success / message or should I use 400 HttpStatusCode.BadRequest to indicate something in the request is bad.

It depends on what does it mean for the client to not have results.
Typically lack of data would still be http 200 ok.
e.g. /employees etc.
However, for some scenarios you could return
HTTP 404 Not Found.
Especially when the client expects a particular resource to be present.
e.g. employees/update/32
Normally any other response code (204 etc.) though technically valid and fitting, might confuse the client.
Also, 400 Bad Request should also be not used, if there is nothing wrong with the request.

If the operation was successful but there is really no response data, use the status 204 NO CONTENT. If an expected entity was missing, return 404 NOT FOUND. If there was some sort of internal error, return 500 SERVER ERROR.
According to the HTTP/1.1 spec,
The server has fulfilled the request but does not need to return an
entity-body, and might want to return updated metainformation. The
response MAY include new or updated metainformation in the form of
entity-headers, which if present SHOULD be associated with the
requested variant.
If the client is a user agent, it SHOULD NOT change its document view
from that which caused the request to be sent. This response is
primarily intended to allow input for actions to take place without
causing a change to the user agent's active document view, although
any new or updated metainformation SHOULD be applied to the document
currently in the user agent's active view.
The 204 response MUST NOT include a message-body, and thus is always
terminated by the first empty line after the header fields.

If ther was nothing wrong with the request but you just don't have any data (i.e. search returns 0 rows) than I would not use BadRequest:
BadRequest is sent when no other error is applicable, or if the exact
error is unknown or does not have its own error code.
http://msdn.microsoft.com/en-us/library/system.net.httpstatuscode%28v=vs.110%29.aspx

Related

414. The request URL is too long. asp.net

I'm getting the error "HTTP Error 414. The request URL is too long." From the following article, I understand that this is due to a very long query string:
http://www.mytecbits.com/microsoft/iis/query-string-too-long
In web.config, I have maxQueryStringLength="2097151". Is this the maximum value?
In order to solve this problem, should I set maxUrl in web.config? If so, what's the maximum value supported?
What should I do to fix this error?
The GET request should never be this long. You need to change it to POST method instead since it was designed to transmit block of data such as forms.
An excerpt from the RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1:
The POST method is used to request that the origin server accept the
entity enclosed in the request as a new subordinate of the resource
identified by the Request-URI in the Request-Line. POST is designed to
allow a uniform method to cover the following functions:
Annotation of existing resources;
Posting a message to a bulletinboard, newsgroup, mailing list, or
similar group of articles;
Providing a block of data, such as the result of submitting a
form, to a data-handling process;
Extending a database through an appendoperation.

CustomVision API returns “Operation returned an invalid status code: 'Bad Request'”

I get this error when using the CustomVisionPredictionClient like so:
var predictionApi = new CustomVisionPredictionClient()
{
ApiKey = _predictionKey,
Endpoint = "https://westeurope.api.cognitive.microsoft.com"
};
var result = await predictionApi.ClassifyImageAsync(project.Id, _modelName, imageData);
The project/project id is retrieved via the training API, on which I can call GetProjects() without a problem. It should be correct, if I change it to something wrong I get a "not found" exception.
_modelName is the published name of the iteration ("xxxRecognition", see screenshot below), it should also be correct, when I change it I get "not found".
imageData is just a FileStream from a PNG image.
The problem was that I created an "Object Detection" type project and tried to use it with ClassifyImage() which has to be used with "Classification" type projects. So I have to use DetectImage() instead. :)
There's two items to address here.
Your particular "Bad Request"
Your example, specifically, has one or more of these problems that you haven't really included.
The _modelName is malformed
The imageData is not formatted properly
Some configuration, likely of request headers, is missing or incorrect
That's about the most we can provide from the example you've given. But here's the other concern that will benefit you greatly in the future: "Bad Request" tells you a lot about what's happened.
More about "Bad Request" in general
If you look at ranges within HTTP status codes you'll notice a pattern in the "error" ranges.
In 4xx the requester (you) did something wrong and you can correct it.
In 5xx the responder did something wrong and you cannot correct it.
Beneath that:
In 404 Not Found it seems the request was formed well but the responder cannot find what you've asked for
In 401 Unauthorized you didn't provide any kind of identity
In 403 Forbidden you did provide an identity but you're not allowed to perform this action
But in 400 Bad Request the responder couldn't validate your request as good input at all. That means you can look at the API documentation again, compare it with your implementation, and try again.

Can you return a different object sent from a PUT request?

As the title says I am wondering if it possible to return information from the controller based on the success of the PUT request.
In this case I am using the put request to use my email service to send emails. Is there a way to return a results object that lists the statuses for each email so I can display on the front end which emails failed and why?
Thanks in advance for any advice.
Ideally PUT request(successful) is used to:
1.) Update an existing resource -200 OK with NO response body
2.) Creation of new resource (If the Request-URI does not point to an existing resource, origin server can create the resource with that URI) - 201 Created with some meta data ,resource identifier in the response body.
So as per the recommendation ,it should not be returned in the response of PUT request and a subsequent GET call should be made to get the status of the emails.
Refer the HTTP specification :
RF2616 -https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6

what's the proper way to handle this invalid api request?

I have an Web API 2 app which accepts a request that looks like this:
{
Type:"RunEtl",
Entities:["group","user"],
Domains:["corp-domain-1", "corp-domain-2"],
UpdatedWithinMinutes:5
}
I have code-based validation which validates each property of the request. However, I submitted a request like the following from Postman which returned a server error:
{
Type:"RunEtl",
Entities:["group","user"],
Domains
UpdatedWithinMinutes:5
}
How can I update my application to return a response to the user indicating a bad request instead of server error? I was assuming that if the request object was simply malformed as in my first example that the Web API 2 app would automatically return a bad request error to the user.
You can check to see if each of the json nodes are filled out, if not then return the node that is empty. In this instance you would return back Domains, since domains is empty

HttpWebRequest using GET on redirect instead of POST like idHttp

Sorry for my english.
In Delphi I have an idHttp component with the hoWaitForUnexpectedData option activated.
When I send a POST request to a URL, it redirects the client to a second URL with the same POST request and headers. Also, the server response contains "Connection: keep-alive" in its header.
However, when I try to do the same request in C# with a HttpWebRequest component, it redirects to the second URL using the method GET.
I need the C# HttpWebRequest component to work like the Delphi idHTTP one does. I don't understand why it uses a GET instead of a POST when following the redirection.
Here's my code in Delphi, using hoWaitForUnexpectedData:
// The server is supposed to send a 'Content-Length' header without sending
// the actual data. 1xx, 204, and 304 replies are not supposed to contain
// entity bodies, either...
if TextIsSame(ARequest.Method, Id_HTTPMethodHead) or
TextIsSame(ARequest.MethodOverride, Id_HTTPMethodHead) or
((AResponse.ResponseCode div 100) = 1) or
(AResponse.ResponseCode = 204) or
(AResponse.ResponseCode = 304) then
begin
// Have noticed one case where a non-conforming server did send an
// entity body in response to a HEAD request. If requested, ignore
// anything the server may send by accident
if not (hoWaitForUnexpectedData in FOptions) then begin
Exit;
end;
Result := CheckForPendingData(100);
end
else if (AResponse.ResponseCode div 100) = 3 then
begin
// This is a workaround for buggy HTTP 1.1 servers which
// does not return any body with 302 response code
Result := CheckForPendingData(5000);
end else begin
Result := True;
end;
An HTTP redirect, by definition from the standard, should be handled using a GET. Therefore, if you send a POST and get a redirect as an answer, the expected behavior is to perform a GET to the redirect address. I suspect the old Delphi component is following old practices and replicates the call including with the POST verb.
I would try to disable AllowAutoRedirect in the HttpWebRequest object and handle this manually, as your case seems to differ from the standard.
The hoWaitForUnexpectedData option has no effect on how TIdHTTP handles redirects, and neither does the section of code you quoted.
However, the hoTreat302Like303 option does affect redirect handling. If TIdHTTP receives a 303 redirect, or receives a 302 redirect with hoTreat302Like303 enabled, TIdHTTP sends the new request as a GET. Otherwise, it sends the new request using the same verb as the redirected request. This is by design, and there is a series of comments in the implementation code of the TIdHTTPProtocol.ProcessResponse() method explaining the rational behind this behavior:
// GDG 21/11/2003. If it's a 303, we should do a get this time
// RLebeau 7/15/2004 - do a GET on 302 as well, as mentioned in RFC 2616
// RLebeau 1/11/2008 - turns out both situations are WRONG! RFCs 2068 and
// 2616 specifically state that changing the method to GET in response
// to 302 and 303 is errorneous. Indy 9 did it right by reusing the
// original method and source again and only changing the URL, so lets
// revert back to that same behavior!
// RLebeau 12/28/2012 - one more time. RFCs 2068 and 2616 actually say that
// changing the method in response to 302 is erroneous, but changing the
// method to GET in response to 303 is intentional and why 303 was introduced
// in the first place. Erroneous clients treat 302 as 303, though. Now
// encountering servers that actually expect this 303 behavior, so we have
// to enable it again! Adding an optional HTTPOption flag so clients can
// enable the erroneous 302 behavior if they really need it.
The jist of it is that the HTTP spec says to send a GET for a 303 redirect, whereas it is ambiguous about whether to send a GET for 302. Some browsers do, some do not. That is why the hoTreat302Like303 option was added, though it is disabled by default for backwards compatibility with earlier Indy versions.
So, the behavior you describe means you must be encountering a 302 redirect, with hoTreat302Like303 disabled (which it is default). If you enable that option, TIdHTTP will behave more like HttpWebRequest, not the other way around.

Categories

Resources