Doesn't ASP.NET Core have an InternalServerError()? - asp.net-core

The Microsoft.AspNetCore.Mvc.Controller base class doesn't have an equivalent of BadRequest(), Ok(), NoContent(), etc. for returning HTTP 500 status codes.
Why can't we do?
try{
oops();
}
catch(Excpetion e){
//some handling
return InternalServerError(e);
}
I know can do return StatusCode(500);, but we are trying to be more consistent with our HTTP codes and would like to know if there is something more consistent with Ok() for returning a 500 code?

ASP.NET Core 2.x doesn't have InternalServerError method. Instead you can include the following library.
using Microsoft.AspNetCore.Http;
And then use the following code.
return new StatusCodeResult(StatusCodes.Status500InternalServerError);
Or if you want to add the exception along with the response, try the following code
var result = StatusCode(StatusCodes.Status500InternalServerError, exception);
return result;

If just like me you didn't understand where the StatusCode method is coming from in Karim's answer, this code will work just as well:
var errorObjectResult = new ObjectResult(exceptionMessage);
errorObjectResult.StatusCode = StatusCodes.Status500InternalServerError;
return errorObjectResult;

Related

In Blazor dealing with unexpected results from the api web server

I'm developing a fairly simple Blazor app using a lot of default template functionality, and I can't figure out how to handle an ActionResult from the server that isn't the normal return value.
On the server side I've slightly modified the default controller template to look something like this:
public async Task<ActionResult<MyData>> GetSession(int id)
{
var myData= await FetchMyData(id);
if (myData== null)
{
return NotFound();
}
return myData;
}
That check for a null value was in the original template - it seems like a good idea so I kept it. On the client side my code looks like this:
public async Task<MyData> GetMyData(int id)
{
return await Http.GetJsonAsync<MyData>("/api/MyData/" + id);
}
It all works quite well, except the client side code doesn't handle the case where the server side returns a "NotFound()" result. It's not a show stopper, but it's driving me crazy that I don't know how to do it.
It seems that the GetJsonAsync() call on the client is silently unwrapping the return Value from the ActionResult wrapper (I guess?). Does that mean if I want to handle a NotFound condition I should be using a different httpclient function and maybe deserializing the object Value myself? If so, anyone want to volunteer an example?
Or am I missing something and there's an easier way?
It seems stupid to check for a condition on the server side just to send the client a warning that ultimately results in an unhandled exception.
I tried Henk Holterman's suggestion of just adding a try/catch, and it turns out the exception that was thrown had the information I wanted - that is the status being returned by the server. So what I should have done was this:
public async Task<MyData> GetMyData(int id)
{
try
{
return await Http.GetJsonAsync<MyData>("/api/MyData/" + id);
}
catch (System.Net.Http.HttpRequestException e)
{
.... process the exception
}
}
Turns out HttpRequestException has the HResult, which is what I was looking for.
Thanks Henk.

What is the replacement of FormDataCollection in Asp.Net core?

I am trying to use FormDataCOllection in Asp.Net core web api project. As per the documentation it is not there in .net core.
How can I still use it? Or What has replaced it?
You can use the Form property of HttpContext.Request which will return an IFormCollection instance.
FormDataCollection is normally type of the information/class/model sent by forms or grid edit or sumbit links. You can simply use the string as input parameter and then using Json, convert it to the class type you've expected.
Here is an example:
public string NewUser(string values)
{
var message = "";
try
{
var newUser = new User_Detail();
JsonConvert.PopulateObject(values, newUser);
db.User_Detail.Add(newUser);
db.SaveChanges();
message = "User cretaed successfully";
}
catch (Exception ex)
{
message = "An error happened in this method.";
}
return JsonConvert.SerializeObject(message);
}
So, PopulateObject converts your input string (values in this example) to the class you've expected, something similar to FormDataCollection you've needed.
Note: JsonConvert is in Newtonsoft.Json namespace

How do I get the message from an API using Flurl?

I've created an API in .NET Core 2 using C#. It returns an ActionResult with a status code and string message. In another application, I call the API using Flurl. I can get the status code number, but I can't find a way to get the message. How do I get the message or what do I need to change in the API to put the message someway Flurl can get it?
Here's the code for the API. The "message" in this example is "Sorry!".
[HttpPost("{orderID}/SendEmail")]
[Produces("application/json", Type = typeof(string))]
public ActionResult Post(int orderID)
{
return StatusCode(500, "Sorry!");
}
Here's the code in another app calling the API. I can get the status code number (500) using (int)getRespParams.StatusCode and the status code text (InternalError) using getRespParams.StatusCode, but how do I get the "Sorry!" message?
var getRespParams = await $"http://localhost:1234/api/Orders/{orderID}/SendEmail".PostUrlEncodedAsync();
int statusCodeNumber = (int)getRespParams.StatusCode;
PostUrlEncodedAsync returns an HttpResponseMessage object. To get the body as a string, just do this:
var message = await getRespParams.Content.ReadAsStringAsync();
One thing to note is that Flurl throws an exception on non-2XX responses by default. (This is configurable). Often you only care about the status code if the call is unsuccessful, so a typical pattern is to use a try/catch block:
try {
var obj = await url
.PostAsync(...)
.ReceiveJson<MyResponseType>();
}
catch (FlurlHttpException ex) {
var status = ex.Call.HttpStatus;
var message = await ex.GetResponseStringAsync();
}
One advantage here is you can use Flurl's ReceiveJson to get the response body directly in successful cases, and get the error body (which is a different shape) separately in the catch block. That way you're not dealing with deserializing a "raw" HttpResponseMessage at all.

REST GET api - what to return when resource not found

I am using jersey to create rest api. I have GET api which returns xml or json representation of an object instance using JaXB. Everything is fine as long as I can get this instance based on id and return it. But when I don't find instance what should I return. I know 404 response has to be returned. But my method already returns a given type. So how do I setup 404 status is response?
Here is simplified version of my method
#GET
#Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public GameDAO getGameState(#PathParam("gameId") String gameId)
{
//code to get game instance based on gameId
if(game != null)
{
GameDAO d = new GameDAO(game);
return d; //gets auto converted to xml or json
}
return null; //how to return not found response ?
}
A 404 response is what you want, and I think the best way to get there is by throwing a "not found" WebApplicationException. Here's an example:
throw new WebApplicationException(Response.Status.NOT_FOUND);
There are plenty of ways to customize the error handling; you can find more details in the Jersey docs: https://jersey.java.net/documentation/latest/representations.html

Passing values in Header

We are consuming an external web service (WCF) in our AX2012 project. We followed the procedure described in the following blog.
We are implementing security by passing the token in the header. However, what i am not sure of is how to do this in AX2012.
the sample code for getting the token is
static void myTestServiceWSDL(Args _args)
{
myServiceWSDL.Proxies.Service.ServiceClient service;
myServiceWSDL.Proxies.Service.LoginData LoginData;
str token;
System.Exception ex;
System.Type type;
try
{
type = CLRInterop::getType('myServiceWSDL.Proxies.Service.ServiceClient');
service = AifUtil::createServiceClient(type);
LoginData = new myServiceWSDL.Proxies.Service.LoginData();
LoginData.set_uName("test");
LoginData.set_pwd("test");
token=service.Login(LoginData);
info(token);
}
catch(Exception::CLRError)
{
ex = CLRInterop::getLastException();
info(CLRInterop::getAnyTypeForObject(ex.ToString()));
}
}
The token comes back fine which confirms the code is working.
Now the question is how to do i set header values for the message.
If it was C# i would have done
using (MemberMasterClient proxy = new MemberMasterClient())
{
using (OperationContextScope scope
= new OperationContextScope(proxy.InnerChannel))
{
// set the message in header
MessageHeader header =
MessageHeader.CreateHeader("SourceApplication",
"urn:spike.WCFHeaderExample:v1",
"WCFClient Application 2");
OperationContext.Current.OutgoingMessageHeaders.Add(header);
Console.WriteLine("Membership Details");
Console.WriteLine("Henry's - {0}", proxy.GetMembership("Henry"));
}
}
}
Could any one let me know how to do the equivalent in X++
One idea which has been on my mind is to write an assembly in C# which can then be called in AX2012. Will give that a go, but the idea is to code this in X++ in AX2012
The only thing you do differently in X++ is creating the proxy using the Aif utility. So basically, your C# example you listed, the only difference would be the proxy = new MemberMasterClient() which goes through AIF. All the other code you can take into X++ as-is (except for the "using"). You just need to have the right assemblies reference in the AOT, and use the full namespace in the code.
Alternatively, as you mentioned, you can just code it all in C# and call that from AX :-)