Why do I have to specify an HTTP status code when providing a response model? - asp.net-mvc

What is the difference between Request.CreateResponse(HttpStatusCode.OK) and
Request.CreateResponse(HttpStatusCode.OK, object) in ASP.NET Web API?
If the model corresponding to object does not have a status, is it not going to set the HttpStatusCode to true or false?
I have come to this question because of the following scenario
public HttpResponseMessage Put(int id, ModelObject object)
{
if (ModelState.IsValid && id == object.objectID)
{
db.Entry(object).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
return Request.CreateResponse(HttpStatusCode.NotFound);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
**if i check httpresponsemessage.statuscode it shows httpresponsemessage is null in the calling method even if the line executes
Task response = httpClient.PutAsJsonAsync(uri, modelObject);
return JsonConvert.DeserializeObjectAsync<HttpResponseMessage>(response.Result.Content.ReadAsStringAsync().Result).Result;
is this is correct

Request.CreateResponse(HttpStatusCode.OK)
create only a response with httpStatusCode
Request.CreateResponse(HttpStatusCode.OK,"this test message")
create a response with httpStatusCode associated with HTTPResponseMessage

According to your phrasing, you seem to be confusing metadata and payload.
The status line and headers of an HTTP message describe what's going on on the HTTP level, so a client application ("user agent") knows how to interpret the response.
Then there's the payload, that which the server wishes to return to the client. While the headers describe the payload, the payload has no influence whatsoever on the HTTP side of things.
The following repsonse is entirely valid:
HTTP/1.1 404 Not Found
...
{
"found" : "true"
}
And so is the following:
HTTP/1.1 200 OK
...
{
"status" : "error"
}
WebAPI is not going to look at your payload to determine the status code (because there is no relation between the two whatsoever), so you can specify the response code and its payload separately.

Related

No errors are being raised when unsuccessfully writing to Azure service bus

When writing a message to the Azure Service Bus (using Microsoft.Azure.ServiceBus standard library, not the .Net Framework version) it works fine. However, when switching networks to a network that blocks that traffic and running it again I would expect an error being raised by SendAsync yet no error is thrown, therefor the function considers the send successful even though it is not.
Am I missing some logic to make sure that errors do get raised and trapped, it seems to be inline with all the examples I have seen.
I have tried this possible solution ..
Trouble catching exception on Azure Service Bus SendAsync method
.ContinueWith(t =>
{
Console.WriteLine(t.Status + "," + t.IsFaulted + "," + t.Exception.InnerException);
}, TaskContinuationOptions.OnlyOnFaulted);
.. and at no point does ContinueWith get hit.
[HttpPost]
[Consumes("application/json")]
[Produces("application/json")]
public ActionResult<Boolean> Post(Contract<T> contract)
{
Task.Run(() => SendMessage(contract));
// Other stuff
}
private async Task<ActionResult<Boolean>> SendMessage(Contract<T> contract)
{
JObject json = JObject.FromObject(contract);
Message message = new Message();
message.MessageId = Guid.NewGuid().ToString();
message.ContentType = ObjectType;
message.PartitionKey = ObjectType;
message.Body = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(contract));
foreach (KeyValuePair<String, String> route in DataRouting)
{
JToken jToken = json.SelectToken(route.Value);
if (jToken != null)
{
message.UserProperties[route.Key] = jToken.Value<String>();
}
else
{
String routeError = $"Could not find routing information in request for: {route.Key} in {route.Value}";
Logger.LogError(routeError);
return new UnprocessableEntityObjectResult(routeError);
}
}
// Send the message
try
{
await topicClient.SendAsync(message);
}
catch(Exception ex)
{
return new UnprocessableEntityObjectResult($"'Could not transmit message to service bus - {ex.Message}'");
}
return new OkObjectResult(true);
}
I expect that the error trap would be hit if the SendAsync fails to send the message. However it essentially fire and forgets, the message send is blocked by the firewall but is never reported to the caller by throwing an error.
Ok, found the answer, but I will leave this out there in case anyone else does this to themselves. It was down to my general muppetry when putting the MVC Controller together. Set async on the Post action and configure the await on the send. Obvious really but I missed it.
public virtual async Task<ActionResult<Boolean>> Post(Contract<T> contract){}
...
// Send the message
try
{
await topicClient.SendAsync(message).ConfigureAwait(false);
return new OkObjectResult(true); // Success if we got here
}
catch(Exception ex)
{
return new UnprocessableEntityObjectResult($"'Could not transmit message to service bus - {ex.Message}'");
}

ASP.NET MVC 5 JsonResult does not include payload for non-Http.OK responses

I am sending GET requests from AngularJs and I want to display actual server errors on failure (this is a proof-of-concept, so I can display technical errors to the testers). This works correctly on localhost, but fails for remote requests (when deployed on a server).
Note: irrelevant code is stripped for better readability
Client code
$http(loadReqData).success(function(data, status ) {
if (status !== 200) {
// non OK responses handling ...
return;
}
// ok handling
}).error(function(data, status, headers, config) {
// error handling ...
// here I do not receive expected information (in data variable)
}).finally(function() {
$loading.finish(loaderName);
});
Server-side
This is an MVC controller, not an Web.API one
[Route("GetEnvironmentTableRowCount")]
public JsonResult GetEnvironmentTableRowCount(int environmentId, string tableName, string whereClause)
{
try
{
long? rowCount = TeradataUtilsService.GetRowCount(environmentId, tableName, whereClause);
return Json(new { RowCount = rowCount }, JsonRequestBehavior.AllowGet);
}
catch (Exception exc)
{
Logger.Log(LogLevel.Error, exc, "Failed to get row count");
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json($"Failed to get row count - {exc.Message}", JsonRequestBehavior.AllowGet);
}
}
When running on localhost and I have an error data will receive the actual error:
Failed to get row count - ...
When running on a server and I have an error data will only contain
Bad request
I have allowed custom errors to be shown (web.config):
<system.web>
<customErrors mode="Off" />
</system.web>
Question: why don't I receive the http response content when deployed on a server?
Please try adding this to your web.config:
<httpErrors errorMode="DetailedLocalOnly" existingResponse="PassThrough" />
Note, this will apply to all error responses but you should achieve the desired result of setting the Response.Code and the custom response.

I am posting from angular2 to net core and getting: failed to load resource the server responded with a status code 415 (unsupported media type)

I am posting stop object from angular2, this is the code
addStop(stop: IStop): Observable<IStop> {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this._http.post(this._tripsUrl, stop, options)
.map(this.extractData)
.catch(this.handleError);
}
this is net core code that should get the object but is not activated,
when I remove [FromBody] attribute, the service activated- but I am getting null
[Route("api/trips/{tripName}/stops")]
[HttpPost("")]
public async Task<IActionResult> Post(string tripName, [FromBody]Stop theStop)
{
if (ModelState.IsValid)
{
//some code
if (await _repository.SaveChangesAsync())
{
return //some code
}
}
return BadRequest("Bad Request");
}
need help, I am not finding the error
It was cors issue, I already defined cors in my web.config of my ASP.NET Core server, and get function worked OK, but the post function didn't work, the right way to define cors is written in this article: https://weblog.west-wind.com/posts/2016/Sep/26/ASPNET-Core-and-CORS-Gotchas

How do you add CORS headers in Redstone interceptor?

I'm trying to add CORS headers to incoming requests but I've noticed that app.response.headers is an immutable map and app.request.response doesn't exist even though it appears in the documentation examples. So, to the OPTIONS request I'm replying using a new Shelf response, but I can't find a way to add any new headers to the response of the actual request. Any ideas?
#app.Interceptor(r"/api/.*", chainIdx: 1)
corsInterceptor() {
if (app.request.method == "OPTIONS") {
var response = new shelf.Response.ok("", headers: HEADERS);
app.chain.interrupt(statusCode: HttpStatus.OK, responseValue: response);
} else {
// app.request.response is not available
app.request.response.headers.add('Access-Control-Allow-Origin', '*');
app.chain.next();
}
}
I found the fix in the first piece of code inside the Interceptor documentation...:)
#app.Interceptor(r"/api/.*", chainIdx: 1)
corsInterceptor() {
if (app.request.method == "OPTIONS") {
var response = new shelf.Response.ok("", headers: HEADERS);
app.chain.interrupt(statusCode: HttpStatus.OK, responseValue: response);
} else {
app.chain.next(() => app.response.change(headers: HEADERS));
}
}
app.chain.next() can take a callback as argument, which is expected to return a Response object. In this case app.response.change() returns a response with the correct headers.

How to retrieve exact reason of the error from async HttpRequest?

I am trying to figure out how to find out exact reason of (async) HttpRequest (from 'dart:html') failure, and, to be honest, I am a bit lost here.
The onError callback receives only HttpRequestProgressError object, which doesn't have anything useful, and the HttpRequest object itself has "status" set to "0" in case of failure, even console shows "Failed to load resource" with no details.
What I want is to know the exact reason - like "connection refused" or "host name not resolved".
Is this possible at all?
Thank you!
Unfortunately, there is no property to report the error as detailed as you'd like. The reason is that JavaScript doesn't support this.
There are the properties status and statusText on the HttpRequest object (which you could get from your HttpRequestProgressEvent with evt.target, but those represent HTTP status codes. Every other error has the status code 0 - request failed. This could be anything, and the only place to look at is the browser's console, because this is an Exception thrown by the browser.
If your request was synchronous, you could surround the send() with a try-catch. If your request is async, this won't work.
See here
#library('Request');
#import('dart:html');
#import("dart:json");
typedef void RequestHandler(String responseText);
typedef void ErrorHandler(String error);
class ResourceRequest {
XMLHttpRequest request;
RequestHandler _callbackOnSuccess;
ErrorHandler _callbackOnFailure;
ResourceRequest.openGet(String url, RequestHandler callbackOnSuccess, [ErrorHandler callbackOnFailure])
: request = new XMLHttpRequest(),
_callbackOnSuccess = callbackOnSuccess,
_callbackOnFailure = callbackOnFailure {
request.open("GET", url, async : true);
request.on.loadEnd.add((XMLHttpRequestProgressEvent e) => onLoadEnd(e));
}
void send() {
request.send();
}
void onLoadEnd(XMLHttpRequestProgressEvent event) {
if (request.readyState == 4 && request.status == 200) {
_callbackOnSuccess(request.responseText);
} else if (_callbackOnFailure != null) {
_callbackOnFailure(request.statusText);
}
}
}

Resources