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

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

Related

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

Calling two HttpStatusCode.Created at the same line in asp.net Web API

In my POST method in a Controller.cs, I have been writing only a single value into the database so far, so at the end I returned the status of the response with the following code:
var response = Request.CreateResponse<object>(HttpStatusCode.Created, iconOffset);
return response;
But now, I am writing two values into the database, and I would love to return the status of both at the end of the POST method, how do I do that? I tried the following:
var response = Request.CreateResponse<object>(HttpStatusCode.Created, HttpStatusCode.Created, iconOffset, tempOffset);
return response;
But didn't work.
You wouldn't return multiple http status codes to the browser.
You make a request for something, you get a response back - that response was either OK or another status code, there's no concept of multiple response codes.
If you need to elaborate with your response, return a model along with your status for whatever is consuming the endpoint, one example would be:
return Request.CreateResponse(HttpStatusCode.OK, new DatabaseUpdateResult(results));
If your application could accept/return json, then this could be consumed by the client.
You can't do that. The response code is the HTTP response code and there is only one. You could either split out the method into two endpoints or return a status that represents the state of the operation.
Your client should have no knowledge of what is going on behind the service (database, services, ...) so if you're posting something to that endpoint and semantically it gets created just return Created. If an error occurs you could return InternalServerError.
Here's a list of HTTP status codes you can use: http://en.wikipedia.org/wiki/List_of_HTTP_status_codes

REST based Response Status codes

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

REST API: Combine login information and API action using C#?

I am trying to use name.com API in C#. The API has different actions including /Login, /account/get, /create/domain and more. You can find the documentation here
The /Login method is POST and the body is a JSON, and done it with HttpWebRequest and it works successfully. It returns something like:
{
"result": {
"code":100,
"message":"Command Successful"
},
"session_token":"a59a09be6562e977a166fdd2b345a235c8b6c724"
}
But after login, I need to use the other services (run the other API actions).
Here I am sending another HttpWebRequest as:
string base = "https://api.dev.name.com/api/"
HttpWebRequest request;
request = WebRequest.Create(base + "account/get") as HttpWebRequest;
....
....
Instead of returning the account information, it returns an error which says:
{
"result":
{
"code":251,
"message":"Authentication Error - No Api Session Or Username Token Supplied"
}
}
I think that I need a way to send the request along with the login information. The err message here is "Authentication Error - No Api Session Or Username Token Supplied"
NOTE: There is PHP sample code and classes for this API. Here is the link of the API Documentation
See page 18 of the documentation. You need to pass the returned session token as a request header:
Api-Session-Token: <session_token>
So, once you get the response and get the token, you would just add the following line:
httpWebRequest.Headers.Add("Api-Session-Token", <session_token>);

How to ensure a url is called from my application and not manually from browser

I have an application that contains a button, on click of this button, it will open a browser window using a URL with querystring parameters (the url of a page that i am coding).
Is there a way to ensure that the URL is coming from my application and only from my application - and not just anyone typing the URL manually in a webbrowser?
If not, what is the best way to ensure that a specific URL is coming from a specific application - and not just manually entered in the address bar or a web browser-
Im using asp.net.
You can check if the request was made from one of the pages of your application using:
Request.UrlReferrer.Contains("mywebsite.com")
That's the simple way.
The secure way is to put a cookie on the client containing a value encrypted using a secure key or hashed using a secure salt. If the cookie is set to expire when the page is closed it should be impossible for someone to forge.
Here's an example:
On the pages that would redirect to the page you are trying to protect:
HttpCookie cookie = new HttpCookie("SecureCheck");
//don't set the cookie's expiration so it's deleted when the browser is closed
cookie.Value = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(Session.SessionID, "SHA1");
Response.Cookies.Add(cookie);
On the page you are trying to protect:
//check to see if the cookie is there and it has the correct value
if (string.IsNullOrEmpty(Request.Cookies["SecureCheck"]) || System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(Session.SessionID, "SHA1") != Request.Cookies["SecureCheck"])
throw Exception("Invalid request. Please access this page only from the application.");
//if we got this far the exception was not thrown and we are safe to continue
//insert whatever code here
There's no reliable way to do this for a GET request, nor is their any reason to try for a legitimate user. What you should do instead is ensure that regardless of where the request comes from the user has the proper permissions and access rights and that the session is protected appropriately (HTTP only cookies, SSL, etc.) If the request is changing data, then it should be a POST, not a GET, and it should be accompanied by some suitable cross-site request forgery prevention techniques (such as a cookie containing a nonce that is verified against a matching nonce on the form itself).
There is no way, other than rejecting the request if it doesn't contain a previously generated random one-time token in the parameters (that would be stored in the session, for example).
While there is no 100% secure way to do this, what I am suggesting might at least take care of your basic needs.
This is what you can do .
Client: Add a HTTP header with an encoded string that is like hash (sha256) of some word.
Then make your client always do a POST request instead of GET.
Server: Check the HTTP Header for encoded string. Also make sure it is a POST request.
This is not 100% as ofcourse someone smart enough could figure out and still generate a request, but depending on your need you might find this enough or not
You can check the referer, the user agent, add an additional header to the request, always do post requests to that url. However, considering HTTP is transmitted in plain text, somebody is always able to let wireshark or fiddler run, capture the HTTP packets and recreate the requests with your measures in place.
Pass parameters from your application so that you can verify on the server side.
I suggest you use an encryption algorithm and generate random text using a password(key). Then, decrypt the param on the server side and check if it matches your expectation.
I am not very clear though. sorry about that, If had to do something like this, then, I would do something similar to mentioned above.
You can use to check the header on MVC controller like Request.Headers["Accept"]; if it is coming from your code in angularjs or jquery:
sample angularjs like this:
var url = ServiceServerPath + urlSearchService + '/SearchCustomer?input=' + $scope.strInput;
$http({
method: 'GET',
url: url,
headers: {
'Content-Type': 'application/json'
},.....
And on the MVC [HttpGet] Action method
[HttpGet]
[PreventDirectAccess]//It is my custom filters
// ---> /Index/SearchCustomer?input={input}/
public string SearchCustomer(string input)
{
try
{
var isJsonRequestOnMVC = Request.Headers["Accept"];//TODO: This will check if the request comes from MVC else comes from Browser
if (!isJsonRequestOnMVC.Contains("application/json")) return "Error Request on server!";
var serialize = new JavaScriptSerializer();
ISearch customer = new SearchCustomer();
IEnumerable<ContactInfoResult> returnSearch = customer.GetCustomerDynamic(input);
return serialize.Serialize(returnSearch);
}
catch (Exception err)
{
throw;
}
}

Categories

Resources