My development environment is.Net7 WebApi (out of the box)
Below is the relevant code. DataAnnotations I have implemented localization.
using System.ComponentModel.DataAnnotations;
namespace WebApi.Dtos
{
public class UserRegistrationDto
{
[Required(ErrorMessage = "UserNameRequiredError")]
[MinLength(6, ErrorMessage = "UserNameMinLengthError")]
[MaxLength(30, ErrorMessage = "UserNameMaxLengthError")]
public required string UserName { get; set; }
[Required(ErrorMessage = "PasswordRequiredError")]
public required string Password { get; set; }
}
}
[HttpPost]
public async Task<IActionResult> RegisterUser([FromBody] UserRegistrationDto userRegistration)
{
return Ok(1);
// IdentityResult userResult = await _userManager.CreateAsync(new IdentityUser { UserName = userRegistration.UserName }, userRegistration.Password);
// return userResult.Succeeded ? StatusCode(201) : BadRequest(userResult);
}
When the request body is invalid JSON.
curl -X 'POST' \
'https://localhost:7177/Authenticate/RegisterUser' \
-H 'accept: */*' \
-H 'Api-Version: 1.0' \
-H 'Content-Type: application/json' \
-d '{}'
{
"$": [
"JSON deserialization for type 'WebApi.Dtos.UserRegistrationDto' was missing required properties, including the following: userName, password"
],
"userRegistration": [
"The userRegistration field is required."
]
}
When the request body is Empty.
curl -X 'POST' \
'https://localhost:7177/Authenticate/RegisterUser' \
-H 'accept: */*' \
-H 'Api-Version: 1.0' \
-H 'Content-Type: application/json' \
-d ''
{
"": [
"The userRegistration field is required."
]
}
It throws exception information before binding to DTO, can this exception information be localized? If not, is it possible to capture this information for secondary processing, such as returning a fixed JSON format?
I've tried this in the Program.cs entry file, but it's not ideal.
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressModelStateInvalidFilter = false;
options.InvalidModelStateResponseFactory = context =>
{
bool knownExceptions = context.ModelState.Values.SelectMany(x => x.Errors).Where(x => x.Exception is JsonException || (x.Exception is null && String.IsNullOrWhiteSpace(x.ErrorMessage) == false)).Count() > 0;
if (knownExceptions)
{
return new BadRequestObjectResult(new { state = false, message = localizer["InvalidParameterError"].Value });
}
// ...
return new BadRequestObjectResult(context.ModelState);
};
})
I have also tried this method, but I can’t capture the exception information that failed when binding DTO alone. They will appear together with the ErrorMessage exception information in DTO like the above writing method.
.AddControllers(options =>
{
// options.Filters.Add(...);
// options.ModelBindingMessageProvider // This doesn't work either, it seems to support [FromForm]
})
Back to the topic, can it be localized? Or there is something wrong with the code. I just learned .Net not long ago. Most of the information I learned came from search engines and official documents. Thanks in advance.
Use the following method.
.AddControllers(options =>
{
// options.ModelBindingMessageProvider.Set...
})
It seems that the exception of JSON deserialization caused by passing invalid parameters can only be eliminated on the client side. So far it seems I haven't found a localization for this exception, but it's not very important to me at the moment.
Thanks #XinranShen for helping point me in the right direction.
Related
#GetMapping(produces = {
MediaType.APPLICATION_JSON_VALUE,
MediaType.APPLICATION_NDJSON_VALUE
})
public Flux<Some> read() {
}
When I curl with --header 'Accept: application/x-ndjson'
The outer array is gone but all new lines in each elements is not gone.
{
"some": "thing"
}
{
"some": "other"
}
How can I make them as single-line as possible?
There are similar questions under this topic, but none of them gave me an answer. I'm a beginner to laravel and trying to learn by myself.
When I try to connect laravel (version 5.6) with MySql it gives this error.
These are the code lines that working with.
CameraController.php
<?php
namespace App\Http\Controllers;
use App\Camera;
use Illuminate\Http\Request;
class CameraController extends Controller{
public function postCamera(Request $request){
$camera = new Camera();
$camera->email = $request->input('email');
$camera->password = $request->input('password');
$camera->save();
return response()->json([
'message'=>$camera
]);
}
}
CreateCamreasTable.php
public function up(){
Schema::create('cameras', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->text('email');
$table->text('password');
});
}
api.php
Route::post('/addCamera', ['as' => 'Camera', 'uses' => 'CameraController#postCamera']);
user.php
class User extends Authenticatable{
use Notifiable;
protected $fillable = [
'email',
];
protected $hidden = [
'password',
];
}
I couldn't found out what's wrong with my code..
PS- I'm trying with postman app that supports with sending requests and reading responses. what I'm sending is a json object
{
"email" : "rr#gmal.com",
"password" : "fjf"
}
The error that I receive is
i try to read a json data , so when the response with status ok (200) i can get data correctly in json format , but the webservice return a message if there is no item to return so he generate a message like that :
{"message " : "item not found" }
the problem is when symfony find that the response it not found he throw an exception not found while i want to just return the message that the webservice provide .
this is my controller code:
/**
*
* #Get("/getUserByUid/{uid}")
*/
public function getUserByUidAction($uid)
{
$url = self::Ws_URL . self::Ws_PORT . self::Ws_GetUserByUID . $uid;
$headers = array() ;
$headers[] = "auth_token: ".self::Ws_Token ;
$headers[] = "Content-Type: application/json" ;
$arrContextOptions=array(
"ssl"=>array(
"verify_peer"=>false,
"verify_peer_name"=>false,
),
"http" =>array(
"method" => "GET",
"header" => "auth_token: ".self::Ws_Token
)
);
$response = file_get_contents($url, true, stream_context_create($arrContextOptions));
return New Response($response) ;
}
If the web service is RESTFull then return a http code 404 with the above message {"message " : "item not found" }, then file_get_contents does not fetch the content of the file because the 404 is saying Does not exist. To get the full response and http code use curl instead.
I am writing a REST API in Symfony2, and I have my controller outputting JSON responses using the provided JsonResponse class:
$response = new JsonResponse(null, $status);
$response->setData($node['Content']);
return $response;
However, for debugging purposes, it would be nice to be able to pretty print the output. Is there an argument I can pass to the JsonResponse object to enable pretty-printing of the output?
Creating an event listener for that, as in Pawel's answer is overengineering.
To prettify, you just pass in the JSON_PRETTY_PRINT constant to the JsonResponse via the setEncodingOptions, like in this example:
$response = new JsonResponse( [ 'your' => 'data' ] );
$response->setEncodingOptions( $response->getEncodingOptions() | JSON_PRETTY_PRINT );
return $response;
You can see the Symfony API for more information:
Class JsonResponse:
http://api.symfony.com/3.2/Symfony/Component/HttpFoundation/JsonResponse.html
Method setEncodingOptions:
http://api.symfony.com/3.2/Symfony/Component/HttpFoundation/JsonResponse.html#method_setEncodingOptions
This is documentation for v3.2... but older versions like for example v2.7 also have this method.
You can create EventListener for that. Here is mine
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
/**
* Preetify json response.
*/
class FormatJsonResponseListener
{
public function onResponse(FilterResponseEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
$request = $event->getRequest();
if (APPLICATION_ENV === 'development' || APPLICATION_ENV === 'dev' || $request->query->get('pretty_json', false) == true) {
$response = $event->getResponse();
$responseData = $event->getResponse()->getContent();
$response->setContent(Json::indent($responseData));
$event->setResponse($response);
}
}
}
And register that service with:
#services.ym
services:
your.service.listener.format_json:
class: Your\Vendor\FormatJsonResponseListener
tags:
- { name: kernel.event_listener, event: kernel.response, method: onResponse }
My JSON class is here: https://github.com/sourcefabric/Newscoop/blob/master/newscoop/library/Newscoop/Gimme/Json.php
Instead APPLICATION_ENV you can pass to listener parameter kernel.debug.
You can also modify response with (PHP >= 5.4.0, HttpFoundation >= 2.5)
$response->setEncodingOptions($response->getEncodingOptions() | JSON_PRETTY_PRINT);
Grails 2.4 RESTful controller.
I have a basic question. I have a RESTful controller with simple domain class and my GET, POST works fine.
How do I send PUT JSON request?
I am using default RESTful generated controllers
url -i -X POST -H "Content-Type: application/json" -d '{"roleId":1,"username":"testuser5"}' http://localhost:8090/testapp/User
HTTP/1.1 201 Created
Server: Apache-Coyote/1.1
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Thu, 03 Jul 2014 02:07:13 GMT
{"id":null,"userId":79,"username":"testuser5"}
Then I tried PUT using same above JSON response (removed id:null and changed the username):
curl -i -X PUT -H "Content-Type: application/json" -d '{"userId":79,"username":"testuser6"}' http://localhost:8090/testapp/User
Request goes to index and I get list of users. What I am doing wrong? How do I invoke "update' method? If I add my own method and I do PUT, my own method gets invoked.
Domain class:
class User {
Integer userId
String username
static mapping = {
table 'user'
version false
id name:'userId', column: 'user_id'
}
static constraints = {
username blank:false, nullable:false
}
}
RESTful controller:
class UserController extends RestfulController {
static responseFormats = ['json', 'xml']
static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
respond User.list(params), model:[userInstanceCount: User.count()]
}
def show(User userInstance) {
respond userInstance
}
def create() {
respond new User(params)
}
#Transactional
def update(User userInstance) {
println "*** in update "
if (userInstance == null) {
notFound()
return
}
if (userInstance.hasErrors()) {
respond userInstance.errors, view:'edit'
return
}
userInstance.save flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.updated.message', args: [message(code: 'User.label', default: 'User'), userInstance.id])
redirect userInstance
}
'*'{ respond userInstance, [status: OK] }
}
}
protected void notFound() {
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'user.label', default: 'User'), params.id])
redirect action: "index", method: "GET"
}
'*'{ render status: NOT_FOUND }
}
}
}
You're missing the call to user.validate() prior to calling hasErrors(). See
https://github.com/grails/grails-core/blob/master/grails-plugin-rest/src/main/groovy/grails/rest/RestfulController.groovy#L99