undefinedman
undefinedman

Reputation: 670

FOSRestBundle posting json data to a form not working

I am stack with posting JSON data to a form in the controller. The entity is not filled in with properties that I am sending, here it's how it looks like:

// Controller

class UserApiController extends FOSRestController
{
    // works fine
    public function cgetAction()
    {
        return $this->get('model.user')->getAllUsers();
    }

    // works fine
    public function getAction($id)
    {
        return $this->get('model.user')->getUserById($id);
    }

    // this method fails
    public function postAction(Request $request)
    {
        $form = $this->createForm(new UserType(), new User());
        $form->bind($request);

        if($form->isValid())
        {
            die('are you valid or not??');
        }

        return $this->view($form, 400);
    }
}

Entity looks like a regular one and form as well.

I have a test controller that sends the json data to the api:

public function testJsonPostAction()
    {
        $client = static::createClient();
        $client->request(
            'POST',
            '/api/1.0/users',
            array(),
            array(),
            array('CONTENT_TYPE' => 'application/json'),
            '{"firstName": "John", "lastName": "Doe", "emailAddress": "[email protected]", "sex": "1"}'
        );

        var_dump($client->getResponse()->getContent());
    }

And the validation:

Software\Bundle\Entity\User:
    properties:
        firstName:
            - NotBlank: ~
            - Length:
                min: 2
                max: 255
        lastName:
            - NotBlank: ~
            - Length:
                min: 2
                max: 255

Ok, the problem is that $form is always not valid. When I dump the $form->getData() content I got my User entity but firstName, lastName etc is not filled in. Instead I got validation errors obviously but here's another but:

Why $form->bind($request) (I know it's deprecated) returns this (which is more less good):

{"code":400,"message":"Validation Failed","errors":{"children":{"firstName":{"errors":["This value should not be blank."]},"lastName":{"errors":["This value should not be blank."]},"emailAddress":{"errors":["This value should not be blank."]},"sex
":[],"locale":[]}}}

and the same code but with $form->handleRequest($request) returns this:

{"children":{"firstName":[],"lastName":[],"emailAddress":[],"sex":[],"locale":[]}}

What's the difference? Since I thought handleRequest is a replacement for bind. I tried already I think all the solutions on the Internet and every time is something different and I can't get it work. Documentation of FOSRestBundle is very poor, it says all about getting stuff, but almost nothing about posting.

Any help much appreciated.

Upvotes: 4

Views: 5187

Answers (2)

i solved it like this:

    $user = new User;
    $form = $this->createForm(UserType::class, $user);
    $view = View::create();

    $form->submit($request->request->all());
    if ($form->isValid()) {
        $em = $this->getDoctrine()->getManager();

        $em->persist($user);
        $em->flush();

        $view->setData($form->getData());
    } else {
        $view->setData($form);
    }

    return $this->handleView($view);

Don't forget to disable CSRF validation (https://symfony.com/doc/master/bundles/FOSRestBundle/2-the-view-layer.html#csrf-validation)

fos_rest:
    disable_csrf_role: ROLE_API
    #disable_csrf_role: IS_AUTHENTICATED_ANONYMOUSLY #just for testing

Then you get a nice output like this:

{
"code": 400,
"message": "Validation Failed",
"errors": {
    "children": {
        "name": {
            "errors": [
                "This value should not be blank."
            ]
        },
        "role": {
            "errors": [
                "This value should not be blank."
            ]
        }
    }
  }
}

Upvotes: 0

undefinedman
undefinedman

Reputation: 670

Since nobody replied, I am going to answer myself in this question.

First of all, sent JSON must start with form name, so instead:

{"firstName": "John", "lastName": "Doe", "emailAddress": "[email protected]", "sex": "1"

must be:

{"user": {"firstName": "John", "lastName": "Doe", "emailAddress": "[email protected]", "sex": "1"}}

In my case, form name was "user".

I have used CURL to test it:

curl -v -H "Accept: application/json" -H "Content-type: application/json" -XPOST -d "{\"user\":{\"firstName\":\"John\", \"emailAddress\": \"[email protected]\", \"password\":\"verystrongmuchpower\"}}" http://localhost.software.com/app_dev.php/api/1.0/users

Since I am testing the API with CURL, a difference in response in bind and handleRequest is gone.

I will update this answer soon if I get more conclusions.

Upvotes: 5

Related Questions