FOSRest validation form - fosrestbundle

What's the best way to obtain this response to invalid form?
Response example of an invalid form
Actually I have this action
public function postUserAction(Request $request)
{
...
$form->handleRequest($request);
if ($form->isValid()) {
...
return $this->handleView($view);
}
$errors = $form->getErrors(true);
$view = $this->view($errors);
return $this->handleView($view);
}
But the response is the next json object:
{ form: Object, errors: Array }
I work with JMSSerializerBundle. I saw in FormErrorNormalizer class the method normalize in FOSRestBundle.
Thanks,

Request's handleRequest is for html forms. You have to use submit instead for FOSREST.
$form->submit($Request->getContent());

Related

Ajax call not working when trying to send & return raw html

I am using Ajax call to invoke C# method that is processing user paste input by removing unwanted html tags and attributes.
When I paste in content with html formatting (tags & attributes), my Ajax call doesn't work. Can you please advise how Ajax parameters should be defined for such scenario (send raw html to server side code and get raw html returned)?
view:
#(Html.Kendo().Editor()
.Name("myEditor")
.PasteCleanup(p => p.Custom("myPasteCleanUp")
)
script:
function myPasteCleanUp(input) {
var response = null;
if (input != null) {
$.ajax({
type: "POST",
url: '/Home/htmlTagCleanUp',
data: { userInput: input },
async: false,
success: function (response) {
input = response;
},
});
}
return input;
}
controller:
[HttpPost]
[AllowAnonymous]
public ActionResult htmlTagCleanUp(string userInput)
{
userInput = userInput;
return Content(userInput, "text/html");
}
It turned out the missing part was sanitizing HTML:
var = document.createElement('div');
element.innerText = html;
var sanitizedHTML = element.innerHTML;
The thing that is preventing your AJAX call is because you have added if conditions:
if (html != null) {
}
Can you tell me where the html variable is defined. Nonetheless, I think you are trying to check the input null values and if we replace the html by input variable on the if the condition it should work:
if (input != null) {
}
I guess the issue is that MVC considers data with tags as a bad request.
Therefore would suggest you try it above the action method in your controller:
[ValidateInput(false)]
Looks like you need to add the [ValidateInput(false)] attribute to your method as it may treat as an XSS attack.
Ref: ValidateInput(false) vs AllowHtml

Parse request content json to object in Laravel

I have controller in Laravel:
public function addUserTesterPost(Request $request)
{
$requestContent = json_decode($request->getContent(), true);
$emil = $requestContent->email; //error: $requestContent is null
}
this is json that I received in $request->getContent():
{
'email': 'dean',
'psw': 'dean123',
}
How to parse above json to object to fetch email?
I send request from Postman, in header I have set content-type: application/json.
This is an array json_decode($request->getContent(), true);
The -> cannot be used for array, instead use [ ] $requestContent['email'];

How to validate params comming from GET request in Yii2 RESTful service

I have a language parameter that needs to be sent to my documents endpoint. So I have to validate that user has sent this parameter in his GET request.
Making rule in my model didn't do anything:
public function rules()
{
return [
[['language'], 'required'],
];
}
Because of that I have tried this:
1) I have created ParamsValidator class:
<?php
namespace app\modules\v1\components;
use yii\web\UnprocessableEntityHttpException;
use yii\base\Component;
use Yii;
/**
* Class that is responsible for validating input params.
*/
class ParamsValidator extends Component
{
public function validate($params)
{
if (!isset($params['language'])) {
throw new UnprocessableEntityHttpException("Language parameter is required");
}
}
}
I am invoking its validate() method inside my controllers init() method:
public function init()
{
$this->_params = Yii::$app->request->queryParams;
$validator = new ParamsValidator();
$validator->validate($this->_params);
}
And this sort of work. Code works, but I get ugly response back. Instead of nice JSON response, I get bunch of html starting like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Unprocessable entity (#422)</title>
<style>
body {
font: normal 9pt "Verdana";
color: #000;
background: #fff;
}
Instead of this html, I would like some nice JSON response like this:
{
"name": "Forbidden",
"message": "You are not authorized to do this.",
"code": 0,
"status": 403,
"type": "yii\\web\\ForbiddenHttpException"
}
This nice JSON error that you see is made by:
$behaviors['authenticator'] = [
'class' => HttpBasicAuth::className(),
'auth' => [$this, 'authenticate']
];
But obviously my Validator is not doing this.
Questions:
1) How to validate params that comes via GET request ?
2) If my method is right, how to get this nice JSON error response ?
A simple option is by overriding the ActiveController::checkAccess method by adding this inside controller:
public function checkAccess($action, $model = null, $params = [])
{
if ($action === 'index' or $action === 'view')
{
$params = Yii::$app->request->queryParams;
if (!isset($params['language'])) {
throw new \yii\web\ForbiddenHttpException('You are not authorized to do this.');
}
}
}
In case you need to do it at model level you'll need to use the addError() method instead of directly throwing the error. Your model instance will hold it when invoking its validate method. Then inside your action you can simply return it. it will be serialized and errors will be outputted in the right format. There is many ways to achieve this. A simple example may be by using the load method to pass both query and body params to the model before validating it (scenarios may be required):
$queryParams = Yii::$app->request->queryParams;
$bodyParams = Yii::$app->request->bodyParams;
$params = array_merge($queryParams,$bodyParams );
$model = new $modelClass;
$model->load($params , '');
if ($model->validate() === false) return $model;
else {
// do whatever you need
}

Handle json array CAKEPHP

Here's my javascript snipet
<script type="text/javascript">
$(document).ready(function() {
$('form#FormId button.btn').click(function(event){
$.ajax({
type: "POST",
url: "/controller/edit",
data: $("#FormId").serialize(),
success: function(response) {
alert(response.message);
alert(response['message']);
}
});
});
});
Here's my controller action
public function edit() {
$this->autoRender = false; // We don't render a view in this example
$this->request->onlyAllow('ajax'); // No direct access via browser URL
echo json_encode(array('message'=>'Welcome','type'=>'success'));
exit;
}
Both alerts on the javascript are returning "undefined" how to handle?
So nobody is getting this correct.
You need to use the JSON view
See how to enable with this section
class PostsController extends AppController {
public $components = array('RequestHandler');
public function index() {
$this->request->onlyAllow('ajax');
$this->set(array(
'data' => array('message'=>'Welcome','type'=>'success'),
'_serialize' => 'data',
));
}
}
Cake will now automatically set the correct headers, serialize as JSON and not render the layout.
As a side note, your code alert(response.message); does not work beacuse response is a string. your header is text/html not application/json. Try console.log(response) and you will see it is just a string.
I get this to work using the following code in the controller
public function edit()
{
$this->RequestHandler->respondAs('json'); // Very important without this it will not work
$this->autoRender = false;
$data = array('message'=>'Welcome','type'=>'success');
return json_encode($data);
}
try add
dataType: 'json',
to your ajax method.
if it not work, try this:
add
$this->response->type('text/plain');
to your index method.
ie brower did not know json format text.
and what broswer did you used for this test? use F12 open the developer kit to check what the server response, is it a objct
From my experience echoing content doesn't work. You should instead return the json_encoded data.
This will make your edit() function look like this:
public function edit()
{
$this->autoRender = false;
$this->request->onlyAllow('ajax');
return json_encode(array('message' => 'Welcome', 'type' => 'success'));
}
To make sure it works; just alert the whole response object to see what is returned.

Can i return a Partial view and a Json object from my action method at the same time

i have the following action method, that returns a partial view _create. but is there a way to pass a Json object such as return Json(new { IsSuccess = "True" }, with the Partial view.
My Action method looks as follow:-
try
{
if (ModelState.IsValid)
{
var v = repository.GetVisit(visitid);
if (!(v.EligableToStart(User.Identity.Name)))
{
return View("NotFound");
}
vlr.VisitID = visitid;
repository.AddVisitLabResult(vlr);
repository.Save();
ViewBag.LabTestID = new SelectList(repository.FindAllLabTest(), "LabTestID", "Description", vlr.LabTestID);
// return Json(new { IsSuccess = "True" }, JsonRequestBehavior.AllowGet);
#ViewBag.status = "Added Succsfully";
return PartialView("_create",vlr) ;
}
}
::-UPDATED-::
what i am trying to do as follow:-
i am calling the action method using ajax.beginform
using (Ajax.BeginForm("CreateAll", "VisitLabResult", new AjaxOptions
{
HttpMethod = "Post",
UpdateTargetId = item.ToString(),
InsertionMode = InsertionMode.Replace,
OnSuccess = string.Format("disableform({0})", Json.Encode(item)),
}))
after successfully receiving the response from the server ,, the Onsuccess script will be executed,,, the script simply disable the form:-
function disableform(id) {
$('#' + id + ' :input').prop("disabled", true);
}
The problem is that the script will always disable the form even is some validation error occurs,, so what i was trying to achieve is to return a JSON with the partial view that indicate if the ModelState.IsValid was valid or not,, and if it was not valid to keep the form enabled to allow the user to correct the validation errors.
BR
You can return ONLY ONE view from action method, if at all you want to pass other information,make use of ViewData or ViewBag
ViewBag.IsSuccess = "True";
Or
ViewData["IsSuccess"] = "True";
No, you can return only the view and pass JSON as the model, or ViewBag (I recommend model.)
Why not simply extend the model that you are already passing to the View adding the property IsSuccess?
ViewBag or ViewData are evil in my opinion. Try to always use a ViewModel when returning data to the view.
In such cases I used following solution:
In your ajax form definition set:
OnComplete = "yourCallback"
Then:
yourCallback = function(response){
var json = response.responseJSON;
if(json.success){
alert('Well done!');
} else {
var form = $('#formId');
form.html(json.html);
form.removeData("validator").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse(form);
}
}
Your controller should return something like this:
var result = new { success = false, html = helper.Partial("_YourPartial", model) };
return Json(result);
Where helper helps you to add validation to your partial view. (Described here: https://stackoverflow.com/a/4270511/952023)