ASP.NET Core Return JSON with Status Code

ASP.NET Core return JSON with status code

The most basic version responding with a JsonResult is:

// GET: api/authors
[HttpGet]
public JsonResult Get()
{
return Json(_authorRepository.List());
}

However, this isn't going to help with your issue because you can't explicitly deal with your own response code.

The way to get control over the status results, is you need to return a ActionResult which is where you can then take advantage of the StatusCodeResult type.

for example:

// GET: api/authors/search?namelike=foo
[HttpGet("Search")]
public IActionResult Search(string namelike)
{
var result = _authorRepository.GetByNameSubstring(namelike);
if (!result.Any())
{
return NotFound(namelike);
}
return Ok(result);
}

Note both of these above examples came from a great guide available from Microsoft Documentation: Formatting Response Data


Extra Stuff

The issue I come across quite often is that I wanted more granular control over my WebAPI rather than just go with the defaults configuration from the "New Project" template in VS.

Let's make sure you have some of the basics down...

Step 1: Configure your Service

In order to get your ASP.NET Core WebAPI to respond with a JSON Serialized Object along full control of the status code, you should start off by making sure that you have included the AddMvc() service in your ConfigureServices method usually found in Startup.cs.

It's important to note thatAddMvc() will automatically include the Input/Output Formatter for JSON along with responding to other request types.

If your project requires full control and you want to strictly define your services, such as how your WebAPI will behave to various request types including application/json and not respond to other request types (such as a standard browser request), you can define it manually with the following code:

public void ConfigureServices(IServiceCollection services)
{
// Build a customized MVC implementation, without using the default AddMvc(), instead use AddMvcCore().
// https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc/MvcServiceCollectionExtensions.cs

services
.AddMvcCore(options =>
{
options.RequireHttpsPermanent = true; // does not affect api requests
options.RespectBrowserAcceptHeader = true; // false by default
//options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();

//remove these two below, but added so you know where to place them...
options.OutputFormatters.Add(new YourCustomOutputFormatter());
options.InputFormatters.Add(new YourCustomInputFormatter());
})
//.AddApiExplorer()
//.AddAuthorization()
.AddFormatterMappings()
//.AddCacheTagHelper()
//.AddDataAnnotations()
//.AddCors()
.AddJsonFormatters(); // JSON, or you can build your own custom one (above)
}

You will notice that I have also included a way for you to add your own custom Input/Output formatters, in the event you may want to respond to another serialization format (protobuf, thrift, etc).

The chunk of code above is mostly a duplicate of the AddMvc() method. However, we are implementing each "default" service on our own by defining each and every service instead of going with the pre-shipped one with the template. I have added the repository link in the code block, or you can check out AddMvc() from the GitHub repository..

Note that there are some guides that will try to solve this by "undoing" the defaults, rather than just not implementing it in the first place... If you factor in that we're now working with Open Source, this is redundant work, bad code and frankly an old habit that will disappear soon.


Step 2: Create a Controller

I'm going to show you a really straight-forward one just to get your question sorted.

public class FooController
{
[HttpPost]
public async Task<IActionResult> Create([FromBody] Object item)
{
if (item == null) return BadRequest();

var newItem = new Object(); // create the object to return
if (newItem != null) return Ok(newItem);

else return NotFound();
}
}

Step 3: Check your Content-Type and Accept

You need to make sure that your Content-Type and Accept headers in your request are set properly. In your case (JSON), you will want to set it up to be application/json.

If you want your WebAPI to respond as JSON as default, regardless of what the request header is specifying you can do that in a couple ways.

Way 1
As shown in the article I recommended earlier (Formatting Response Data) you could force a particular format at the Controller/Action level. I personally don't like this approach... but here it is for completeness:

Forcing a Particular Format If you would like to restrict the response formats for a specific action you can, you can apply the
[Produces] filter. The [Produces] filter specifies the response
formats for a specific action (or controller). Like most Filters, this
can be applied at the action, controller, or global scope.

[Produces("application/json")]
public class AuthorsController

The [Produces] filter will force all actions within the
AuthorsController to return JSON-formatted responses, even if other
formatters were configured for the application and the client provided
an Accept header requesting a different, available format.

Way 2
My preferred method is for the WebAPI to respond to all requests with the format requested. However, in the event that it doesn't accept the requested format, then fall-back to a default (ie. JSON)

First, you'll need to register that in your options (we need to rework the default behavior, as noted earlier)

options.RespectBrowserAcceptHeader = true; // false by default

Finally, by simply re-ordering the list of the formatters that were defined in the services builder, the web host will default to the formatter you position at the top of the list (ie position 0).

More information can be found in this .NET Web Development and Tools Blog entry

How to return error status in JsonResult in Asp.Net Core?

You don't have to create you own implementation in ASP.NET Core.

ASP.NET Core introduces a new StatusCode Property for JsonResult class.

So simply change your code to :


catch (Exception ex)
{
return new JsonResult(ex.Message){
StatusCode = (int)HttpStatusCode.InternalServerError
};
}

How to return response JSON data with status code?

You can return a JsonResult from a Razor Page handler method, and set the HTTP status code for the response:

public IActionResult OnGet()
{
Response.StatusCode = 400;
return new JsonResult(new { message = "Error" } );
}

How to return a Json object error on ASP.Net Core Restful Cotroller?

Add NewtonsoftJson support

  public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddNewtonsoftJson();
}

Return JsonObject

       if (agendamentosJaExistentes != null)
{
return new ObjectResult(Error("You can't do that.")); //???JSON OBJECT???
}

400 Bad Request response status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error.

    public class ReturnJson
{
public string Status { get; set; }
public string Message { get; set; }
}

public static ReturnJson Error(string responseMessage, string responseCode = "400")
{
ReturnJson returnJson = new ReturnJson()
{
Status = responseCode,
Message = responseMessage ?? string.Empty
};
return returnJson;
}

Test Result:

Sample Image

Return JSON with error status code MVC

I found the solution here

I had to create a action filter to override the default behaviour of MVC

Here is my exception class

class ValidationException : ApplicationException
{
public JsonResult exceptionDetails;
public ValidationException(JsonResult exceptionDetails)
{
this.exceptionDetails = exceptionDetails;
}
public ValidationException(string message) : base(message) { }
public ValidationException(string message, Exception inner) : base(message, inner) { }
protected ValidationException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
: base(info, context) { }
}

Note that I have constructor which initializes my JSON. Here is the action filter

public class HandleUIExceptionAttribute : FilterAttribute, IExceptionFilter
{
public virtual void OnException(ExceptionContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (filterContext.Exception != null)
{
filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
filterContext.Result = ((ValidationException)filterContext.Exception).myJsonError;
}
}

Now that I have the action filter, I will decorate my controller with the filter attribute

[HandleUIException]
public JsonResult UpdateName(string objectToUpdate)
{
var response = myClient.ValidateObject(objectToUpdate);
if (response.errors.Length > 0)
throw new ValidationException(Json(response));
}

When the error is thrown the action filter which implements IExceptionFilter get called and I get back the Json on the client on error callback.

How to return a Json response from a service layer (Dot net core 3.1)

To return a Json response you should change the return Type of the function/ method used as the endpoint. This is the first function that gets called by the front-end.

I'd recommend creating a custom class in this case. This will make it easy to implement more specific handling of the response. And will make it more accessible for different parts of your application.

The class would look like this (you can manipulate it to fit your needs):

public class Response
{
public int StatusCode { get; set; }
public string Message { get; set; }
}

Your Validate function should look like this:

public async Task<Response> Validate(type objectToValidate)
{
// validation process
if (!validated) return response;
}

Don't forget to set the Type in the parameters to whatever you need to validate.
Your Validate function is not responsible for talking to the front-end. So you wouldn't want it to return Json.

Your Endpoint will look like this:

public async Task<JsonResult> MyEndpoint()
{
// your code
var response = await _validateService.Validate(objectToValidate);
return Json(response);
}

You might need to reference Microsoft.AspNetCore.Mvc.

How to convert String response (Text) to JSON response in .net core

Please have a read over Format response data in ASP.NET Core Web API. There are multiple possibilities, depending on what your exact requirements are.

The simplest option is to add [Produces] attribute to the controller action, specifying the type that's returned from the aciton:

[Produces("application/json")]
public IActionResult YourAction(int id) { ... }

The above action will return application/json even when the return type of the action is string.


However, it looks like you're returning two values in the string (InterfaceRecordId and ReceiptId). You can use built-in methods (such as Ok(), BadRequest(), Created(), NotFound(), etc) which convert the object to JSON and return a specific status code.

I would recommend returning an object containing both values, and use a convenience return method (Created() or CreatedAtAction()). The following returns an anonymous object and status code 201:

var successResponse = new 
{
InterfaceRecordId = order.WMWDATA.Receipts.Receipt.InterfaceRecordId,
ReceiptId = order.WMWDATA.Receipts.Receipt.ReceiptId
}

return CreatedAtAction(nameof(YourAction), successResponse);

The CreatedAtAction (and Created) convenience methods return a 201 (created) HTTP Code - so the client will be able to infer that from the status code. And since it's returning an object (rather than a string), the return type defaults to application/json, so there's no need for the [Produces] attribute.



Related Topics



Leave a reply



Submit