Send both JSON response and model in Grails - json

I'm new to Grails and I'm stuck up with a problem. I want to know if there is a way to send both JSON and view and model through "render" in Grails.
I'm using a jQuery Datatable to display data returned from server which is read from JSON returned by the controller. I also need to display error messages on the same view in case of validation failure in form fields. But I'm able to return either only the JSON or model and view using render. I also tried sending the JSON through model itself but it didn't work.
This is my code:-
def hierarchyBreakInstance = new HierarchyBreak(params);
String json = "{\"sEcho\":\"1\",\"iTotalRecords\":0,\"iTotalDisplayRecords\":0,\"aaData\":[]}";
hierarchyBreakInstance.errors.reject(message(code: 'hierarchyBreak.error.division.blank'));
render(view: "hierarchyBreak", model: [hierarchyBreakInstance: hierarchyBreakInstance]);
//render json;
The gsp code:-
<g:hasErrors bean="${hierarchyBreakInstance}">
<div class="errorMessage" role="alert">
<g:eachError bean="${hierarchyBreakInstance}" var="error">
<g:if test="${error in org.springframework.validation.FieldError}" > data-field-id="${error.field}"</g:if>
<g:message error="${error}"/>
</g:eachError>
</div>
</g:hasErrors>
Could you please let me know if there is a way to do this. Thanks!

You can use like this.
def hierarchyBreakInstance = new HierarchyBreak(params);
String json = "{\"sEcho\":\"1\",\"iTotalRecords\":0,\"iTotalDisplayRecords\":0,\"aaData\":[]}";
hierarchyBreakInstance.errors.reject(message(code: 'hierarchyBreak.error.division.blank'));
render(view: "hierarchyBreak", model: [hierarchyBreakInstance: hierarchyBreakInstance,json:json]);
//render json;

Assuming that you are doing a request with some parameters, and need to return if was succesfull or not, and the data to fill the table with ajax.
I will do on that way, use the statuses of the HTTP to mark if it was a problem with the validation(normally we return 400 Bad Request and the message)
Example :
return ErrorSender.sendBadRequest("error validating field $field with value $value")
And the errorsender has a sendBadRequest method
[response: ['message': message, error: "bad_request", status: 400, cause: []], status: 400]
If the request was OK, you only need to respond the data with something like
return [response: results, status: 200]
In the client side you have to have one function if the request was OK to parse result, and one function if request have some validated data problem, database problem or whatever that caused that the request didnĀ“t return a 200(in the example),there are more status codes, you can check on
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
PD: Initial validation should be done on client side.

Related

Text Response from Spring REST API endpoint, how to retrieve that on Angular Front end

Spring REST API is responding with following response:
On successful execution : It returns me a response of Text type.
On unsuccessful execution : It returns me JSON error object.
Front-End Service Class :
private detailsURL = 'http://localhost:8080/register';
constructor(private http:HttpClient){}
register(regisDetails): Observable<any>{
return this.http.post(this.detailsURL,regisDetails);
}
Front-End Component Class:
registerUser(){
this.service.register(this.regisForm.value).subscribe(
success => this.successMessage = success,
error => this.errorMessage = error.error.errorMessage
);
}
In case of error I'm getting the error message I'm supposed to get. But in case of success I'm not getting the successMessage.
Just wanted to know if there's any way to fetch the Text type response on front end. Or else I'll have to change my backend to send response of JSON Type for successful execution as well.
Please help me understand this thing.
You have to set the status for your response. In the controller part you have to mention consumes="application/json" in api request.
You should be doing your changes at the backend and provide the response in Json format response for both the success and backend. That would be the ideal solution.
It is really a bad design to provide a different response than what is expected. You could check the value of the header in request "accept:application/json" and provide response as was expected by the front end
Front End Fix :
However, in the front end you could always use
JSON.parse(success) to convert the text to Json object and use it further as required.

Express res.status(200).json(...) only sending json message. How to retrieve status code?

After a successful creation of new item in my database I send:
res.status(201).json({message:"Successfully Registered"});
On my angular front end I am able to console.log(res) and receive:
{message: "Successfully Registered"}
1) How do I get the status code on the front end? res.status returns undefined. The only response I'm getting is the JSON.
2) What would be the best way to confirm successful desired api calls? For example, when I log in and credentials are correct, should I check for a 200 and then proceed? Or send a custom JSON message and check if the message for example says "Successful login" then proceed?
A little bit late, but another option is to include the status in the JSON object:
res.status(201).json({message: "Successfully Registered", status: 201})
Now you can check the status in the front end doing res.status and use this to proceed with another action.
1- You can do res.status(200).send("You message here");
2- I would say your best option when doing the login and authenticating credentials is to create a session as such
req.session.user = req.body.username //username is the name attribute of the textfield
and then redirect to any page you'd like/you can also set status to 200
res.status(200);
I'm not familiar with Angular, but looking at the docs:
See https://angular.io/api/http/Response
You'll need to do something like:
http
.request('example.com')
.subscribe(response => console.log(response.status));
Sure, checking for 200 is fine. Typically with a REST API (inferred from what you've shown), after a login you're given back a JWT along with 200 OK. And any subsequent API all with that JWT will also yield a 200 OK along with the response body which is usually JSON.
You should tell your angular http client that you want to get the response status. By default, angular deserialize the response body, but you can set request option.observe:'response' to do so.
postData(model: MyModel): Observable<HttpResponse<{status: string}>> {
return this.http.post<{status: string}>(
model, { observe: 'response' });
}
See https://angular.io/guide/http#reading-the-full-response for details.
PS: sending a { status: 'message' } is not very useful, you may return an { id } or even nothing.
res.status(200).json({
status: 'success',
results: tours.length,
data:{
tour:tours
}
});
Usually, Jsend is a good choice to response, and also by convention. Absolutely you can see the 'status' in response data and the actually data you want in the data.
according to the angular guide, we can add observe in the options of our request.
getforgetpassword(email: string): Observable<any> {
const url = this.gatewayUrl + `newPasswordFor/${email}`;
return this.http.get(url, {observe: "response"});
}
using observe type as response will give total response along with request status, which you can use in your logic of controller.

Using and further parsing of form.errors.as_json to return http response in Django

I am relatively new to both JSON and Django forms. And I wonder how Djagno's user_form.errors.as_json() should be used to transfer error messages to client-slde. Right now, I have the following code:
On the server-side. I have:
if form.is_valid():
# some code
else:
return JsonResponse(user_form.errors.as_json(), status = 400, safe = False)
Client:
$.post('/url/', data, function(response){
// Success
}).fail(function(response){
var errors = $.parseJSON($.parseJSON(response.responseText)); // looks stupid
The akward line $.parseJSON($.parseJSON(response.responseText)); proves that I am doing something wrong. Can anyone provide a best-practice code pattern for sending and parsing jsonified form errors ?
The problem is that you are You are converting to JSON twice - once when you call as_json, then again when you use JsonResponse.
You could use HttpResponse with form.errors.as_json():
return HttpResponse(user_form.errors.as_json(), status = 400, content_type='application/json')
Note the warnings in the as_json docs about escaping results to avoid a cross site scripting attack. You should ensure the results are escaped if you use JsonResponse as well.

getting parameters from httppost in android to grails

I am using the following code to convert json to StringEntity
StringEntity se = new StringEntity(json,"UTF-8");
se.setContentType("application/json");
httpPost.setEntity(se);
at the server side. i am using grails. I am unable to parse the data.
Say i have a controller : http://example.com/login
and login have following definition.
def login(params){
String email = params.email;
//validaton logic
}
it is unable to get the 'email' from post request. please anyone can guide me how to get the values.
I am passing two values in json objec i.e. email and password.
You should use request.JSON.email since it's a JSON request.

No MediaTypeFormatter error when trying to parse ReadAsFormDataAsync result in WebAPI

I have created a WebAPI project to help capture statements from a TinCan learning course but I am having extreme difficulty in retrieving any of the Request payload details. Within this payload I pass the whole statement that I am trying to capture but upon trying to read using:
var test = Request.Content.ReadAsFormDataAsync().Result.ToString();
I get the following error message:
No MediaTypeFormatter is available to read an object of type 'FormDataCollection' from content with media type 'application/json'.
I have tried Converting the result object to JSON to overcome this problem but it has not been any use. Do I need to configure json somewhere in the configuration? I have tried adding
var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
and also:
var jsonFormatter = config.Formatters.JsonFormatter;
config.Formatters.Insert(0, jsonFormatter);
to my WebApiConfig.cs file as answered in another question of how to return json but I cannot seem to pass this error. I have also set config.formatter to accept application/json but this also has not worked
CONTROLLER CODE
public void Put([FromBody]string statementId)
{
var test = Request.Content.ReadAsFormDataAsync().Result;
System.Diagnostics.EventLog.WriteEntry("Application", "/xAPI/PUT has been called", System.Diagnostics.EventLogEntryType.Error);
}
From the error message you have provided, it seems like request content is in application/json. ReadAsFormDataAsync() can only read content of type application/x-www-form-urlencoded.
In this case, you can use ReadAsAsync<> if you have the type you want to be deserialized defined or simply use ReadAsStringAsync<> if you just want to read the content as a string.