How to change the response code when not using HttpResponseMessage? - asp.net-web-api

I have this example of ASP.NET Web Api controller:
public Mea Get(Int32 id)
{
try
{
return Meas.GetById(id) ?? new Mea(-1, 0D, 0D);
}
catch (Exception)
{
return new Mea(-1, 0D, 0D);
}
}
I want to be able to return a different response code if the GetById returns null or in the catch exception.
All the examples that I see use HttpResponseMessage where you can add the response code.
My question is how to change the response code when not using HttpResponseMessage, like in the above example?

Well if you want to have different response code to be return from your function then you will have to wrap it in in a HttpResponseMessage.
Your function will always return an status code "200". Even if you return a bare object the framework pipeline will convert it to a HttpResponseMessage with default status code HttpStatusCode.OK, so better you do it by yourself.
What I would suggest is do not return bare objects/values from your API function. Always wrap the values in a HttpResponseMessage and then return a response message from your function.Basically by wrapping it in the HttpResponseMessage you can have proper status code in client side. Returning HttpResponseMessage is always the best practice.
So please change your function like this
public HttpResponseMessage Get(Int32 id)
{
try
{
// on successful execution
return this.Request.CreateResponse(HttpStatusCode.OK, Meas.GetById(id) ?? new Mea(-1, 0D, 0D));
}
catch (Exception)
{
return this.Request.CreateResponse(HttpStatusCode.InternalServerError, Mea(-1, 0D, 0D));
}
}
in the case of an error you can also throw an HttpResponseException

You can throw a System.Web.Http.HttpResponseException, specifying an HTTP status code and/or optionally a whole HttpResponseMessage to be returned to the client.

Related

HTTP 400 bad request when using POST

I am getting HTTP 400 when I POST some JSON using RestSharp PCL.
When I send a string, it seems that the \" is included. Which it should not. This might be the reason why the POST does not work.
I am probably missing something that I need to fill in but please do help me to understand what I am missing.
Here is the code I am using
public async Task<bool> DoPost<T>(string endPoint, T content) where T : class
{
var body = JsonConvert.SerializeObject(content);
var request = new RestRequest(endPoint, Method.POST);
request.AddParameter("application/json", body, ParameterType.RequestBody);
try
{
var response = await _client.Execute(request, _cancellationToken.Token);
if (response.IsSuccess)
{
return true;
}
}
catch (Exception e)
{
throw new GTSWebServiceException(e.Message, e);
}
return false;
}
Have you checked this: How to POST request using RestSharp I know you are including the content type in the first argument but maybe you can play with RequestFormat? I doubt that's needed though. Also, have you checked whether your string does actually contain an escaped character like a double quote on it? If you are also seeing that slash on strings could it also be because you are debugging it? What do you receive in the payload coming through in the server that returns you the bad request?

calling a spring controller from xhrPost doesnot redirect

I am calling a spring controller method from dojo xhrPost and I need to redirect to a new html from the controller method. But controller returns back to the dojo in javascript instead of moving to a new page.
my javascript:
var xhrArgs={
url:"/tradeIn/submitTradeIn",
postData:dojo.toJson(tradeInDetails),
handleAs:"text",
headers:{"Content-Type":"application/json"}
/*load:function(data){
console.log(data);
label=data;
if(data =="fail"){
location.reload(true);
window.location="/Fail";
}
else{
window.location="/success";
}
}*/
}
var deferred=dojo.xhrPost(xhrArgs);
my spring controller:
#RequestMapping(value="/tradeIn/submitTradeIn", method = {RequestMethod.POST})
public String submitTradeIn(#RequestBody TradeInDetails tradeDetails) throws UnsupportedEncodingException{
List<byte[]> labelList=new ArrayList<byte[]>();
ShippingInfo shippingInfo=new ShippingInfo();
shippingInfo.setAddress1(tradeDetails.getCustomerDetails().get(0).getAddress1());
shippingInfo.setAddress2(tradeDetails.getCustomerDetails().get(0).getAddress1());
shippingInfo.setCity(tradeDetails.getCustomerDetails().get(0).getCity());
shippingInfo.setCompany(tradeDetails.getCustomerDetails().get(0).getCompany());
shippingInfo.setDayPhone(tradeDetails.getCustomerDetails().get(0).getDayPhone());
shippingInfo.setEmail(tradeDetails.getCustomerDetails().get(0).getEmail());
shippingInfo.setEvePhone(tradeDetails.getCustomerDetails().get(0).getEvePhone());
shippingInfo.setFirstName(tradeDetails.getCustomerDetails().get(0).getFirstName());
shippingInfo.setLastName(tradeDetails.getCustomerDetails().get(0).getLastName());
shippingInfo.setState(tradeDetails.getCustomerDetails().get(0).getState());
shippingInfo.setZip(tradeDetails.getCustomerDetails().get(0).getZip());
shippingInfo.setCountry(tradeDetails.getCustomerDetails().get(0).getCountry());
List<ReturnRequestLabel> label;
List<TradeInClubs> tradeInList1= new ArrayList<TradeInClubs>();
for(ClubDetails cl: tradeDetails.getClubDetails()){
TradeInClubs tradeInclubs1=new TradeInClubs();
tradeInclubs1.setClubMaterial(cl.getShaftType());
tradeInclubs1.setClubType(cl.getClubType());
tradeInclubs1.setManufacturer(cl.getClubManufacturer());
tradeInclubs1.setModel(cl.getClubModel());
tradeInclubs1.setTradeInValue(cl.getTradeInPrice());
tradeInList1.add(tradeInclubs1);
}
try{
ReturnFedexLabel returnFedexLabel = new ReturnFedexLabel();
label=returnFedexLabel.fetchFedexLabel(tradeInList1, shippingInfo);
byte[] labelImageData;
String fedexLabelNumber=null;
for(ReturnRequestLabel rl: label){
labelImageData=rl.fedexReturnLabel.imageData;
labelList.add(labelImageData);
fedexLabelNumber=rl.trackingNumber;
}
File f=new File("label.jpg");
BufferedImage img=ImageIO.read(new ByteArrayInputStream(labelList.get(0)));
ImageIO.write(img,"JPEG",f);
int id=tradeInDao.insertQuery(shippingInfo,tradeInList1,fedexLabelNumber);
byte[] pdfData=fedexLabelToPdf.printFedexLabel(labelList);
emailTradeIn.emailTradeInDetails(pdfData,tradeDetails.getCustomerDetails().get(0).getEmail(),tradeInList1,id);
System.out.println("here");
} catch (Exception e){
logger.error(e.getMessage());
return "fail";
}
return "success";//Base64.encodeBase64String(labelList.get(0));
}
it is not moving to success page. it just stays in the current page
Check and see what deferred is, it is probably "success".
From http://dojotoolkit.org/reference-guide/1.7/quickstart/ajax.html:
dojo.xhrPost xhrPost will create an Ajax request using the HTTP POST
method and is usually used to submit data to a service. It returns
data to a callback. The callback is defined as a member of the object
used to create the request (the property-bag), or by using the
dojo.Deferred.then() method.
For complete details and examples, see the dojo.xhrPost documentation.
if you need to change the page from the controller it shouldn't be an ajax request. If you can change it from the client side then you can continue with the ajax request and respond accordingly.

Return a list of error messages with 400 Bad Request response in Web API 2

How can I return a list of error messages from Web Api 2 with 400 Bad Request status code? See the example below. Usually I use BadRequest method to return the 400 status code but it doesn't have any overload where it accepts a collection of string. It has an overload where it accepts ModelStateDisctionary. Does it mean I will have to create ModelStateDictionary from a list of error messages?
[Route("")]
[HttpPost]
public IHttpActionResult Add(Object data)
{
var valid = _serviceLayer.Validate(data);
if(!valid)
{
var errors = valid.Errors;
// errors is an array of string
// How do I return errors with Bad Request status code here?
}
var updatedObject = _serviceLayer.Save(data);
return Ok(updatedObject);
}
As per Mike's comment, I am going to add a new class implementing IHttpActionResult to return a list of error messages with 400 Bad Request. Thanks Mark

WebAPI CORS - why is the OPTIONS request making its way into my Controller?

I have CORS working with the following:
[System.Web.Http.HttpPut]
[System.Web.Http.AcceptVerbs("OPTIONS")]
[System.Web.Http.Route("api/exercise")]
public HttpResponseMessage UpdateExercise(Exercise exercise) {
try {
_adminService.UpdateExercise(exercise);
return Request.CreateResponse(HttpStatusCode.OK, "Success");
} catch (Exception e) {
return Request.CreateResponse(HttpStatusCode.InternalServerError, e);
}
}
In my global.asax:
protected void Application_BeginRequest() {
if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS") {
Response.Flush();
}
}
But something weird is happening - if I set a breakpoint in my controller, the OPTIONS request makes its way to the innards with a null exercise. Why is this happening? I would expect the Flush() to prevent this.
As it stands, I need to add checks for null to all of my CORS-sensitive endpoints (PUTs, DELETEs). This seems inelegant... should I be able to prevent OPTIONS requests from hitting the controller logic, instead just responding with the required headers straight-away?
Adding this as an answer, based on the comments in the question.
The problem is caused by accepting the OPTIONS verb on the action method. The MVC runtime then tries to execute the action method & the null problem occurs.
Remove the verb so MVC doesn't try to execute the method & the Application_BeginRequest event will sort out the pre-flight issue for you.

Set HTTP status code for redirect when returning a String in a Spring 3 controller

Is there a way to specify the HTTP status code when returning "redirect:/new/url" in Spring 3?
Haven't tried it, but looking at the source of org.springframework.web.servlet.view.RedirectView it has getHttp11StatusCode() method that determines the HTTP status of response.
It seems like you can override the default response code by settings org.springframework.web.servlet.View#RESPONSE_STATUS_ATTRIBUTE property on request. Simply set:
httpServletRequest.setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, status)
before returning with "redirect:" view.
As noted by Scolytus, you must return a RedirectView with the statusCode set. Using the "redirect:" prefix will always result in a status of HttpStatus.MOVED_TERMPORARILY (302).
If you need the ability to return String from your controller method as well as RedirectView, you must change the method signature to return Object. Example:
#RequestMapping
public Object someMethod() {
if (doRedirect) {
RedirectView rv = new RedirectView("/new/url");
rv.setStatusCode(HttpStatus.MOVED_PERMANENTLY); // set our own status code
return rv;
} else {
return "someView";
}
}

Resources