Backbone model remains unchanged even the object is modified in backend - spring

I have a backbone model. I add the following attributes to the model
model.set('x',x);
model.set('y',y);
model.set('z',z);
and than i call model.save....
In the backend what i do is i set some more properties to brandDTO
But what i see is that the error attribute is not there in the error callback model
app.Model.BrandModel = Backbone.Model.extend({
url : '/brand/cu'
});
var brand = new app.Model.BrandModel();
brand.save(null, {
success : function(model, response) {
},
error : function(model, response) {
}
});
#RequestMapping(value = "/brand/cu", method = RequestMethod.POST, produces = "application/json")
#ResponseBody
public BrandDTO createBrand(#RequestBody BrandDTO brandDTO,
HttpServletResponse response) {
brandDTO.setErro("error", error)
This error field is not there in the error callback model..
I am not sure if i am thinking right....

You are thinking right, just need to arrange this both on client and server.
I see you are using Java, is this SpringMvc?
First, you should serialize your response:
On server:
1.)Create an object/class called SerializedResponse which has "data", "success", "exception" properties.
2.)Then you can wrap a try{}catch{} on the create brand business logic, and if it succeeded set the "success" to true, if it failed to "false", if theres an exception, put it in the exception object.
Note that even if you have an error in your logic, you will always get success, as long as the operation was performed and you have recieved a response, and unless the http status code is not 200, this is handled by the jqXhr object so you can handle the callbacks from there, meaning:
success : function(model, response) {
var data = JSON.parse(response);
if(data.success){
//ALL OK
}
else {
//Fail
}
},
error: function(){
//Error
}

Related

ASP.NET Core API response headers not in expected place

I have an ASP.NET Core API that adds two headers to its response callback_uri and redirect_uri.
The strange thing (to me) is that in my AJAX call to the service, the headers are part of the JSON data, as a headers array, rather than the request object itself. I cannot use jqxhr.getResponseHeader(...) and therefore must interrogate the headers array manually within the response data.
Because the StatusCode is also part of the data it means my AJAX success callback is always called, even when I'm testing for a 400 bad request response, which makes testing less simple.
Web API controller action:
[HttpGet, Route("Authenticate")]
public HttpResponseMessage Authenticate(string applicationId)
{
HttpResponseMessage response;
if(!_security.IsApplicationIdValid(applicationId))
{
response = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest);
response.ReasonPhrase = ErrorMessages.INVALID_APPLICATION_ID;
return response;
}
IAuthenticationProvider authProvider = _security.GetAuthenticationProvider();
response = new HttpResponseMessage(System.Net.HttpStatusCode.Redirect);
response.Headers.Add(HeaderKeyNames.CALLBACK_URI_KEY_NAME, authProvider.GetCallbackUrl());
response.Headers.Add(HeaderKeyNames.AUTHENTICATION_SERVICE_REDIRECT_URI_KEY_NAME, authProvider.GetUrl());
return response;
}
AJAX code:
var settings = {
data: { "applicationId": applicationId },
success: successCallback, // at the moment just writes to console
error: errorCallback, // at the moment just writes to console
method: "GET"
};
$.ajax(url, settings);
Am I doing something wrong on the server-side?
You can use a combination of ResultFilters and ServiceFilterAttribute to add your custom headers. This is particularly useful because:
ServiceFilter enables you to have DI access in your ResultFilter.
You can apply it as an Attribute in the actions you want
You can test it.
Putting all together:
Create the custom result filter class
public class CustomHeadersResultFilter : IResultFilter
{
private readonly IMyService _myService;
public CustomHeadersResultFilter(IMyService myService)
{
_myService = myService;
}
public void OnResultExecuting(ResultExecutingContext context)
{
context.HttpContext.Response.Headers.Add("my-header", _myService.GetData());
// if under CORS, this need to be added otherwise you can't read the headers using xhr.getResponseHeader('my-header')
context.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "my-header");
}
public void OnResultExecuted(ResultExecutedContext context)
{
// can't add headers here, since it's too late in the pipeline
}
}
Register it in your Startup.ConfigureServices
services.AddTransient<IMyService, MyService>();
// our custom result filter
services.AddTransient<CustomHeadersResultFilter>();
Apply the attribute in the action you want to return the custom headers
[HttpGet("{id}")]
[ServiceFilter(typeof(CustomHeadersResultFilter))]
public ActionResult Get(string id)
{
if (id == "something-bad")
{
return BadRequest("invalid application id");
}
// return a 200 Ok. Check the other types if you want something different
return Ok();
}
Testing all of this with a separate web application, doing an ajax request to the API, you can access the headers:
<script>
var settings = { method: "GET" };
$.ajax('http://localhost:61284/api/values/test', settings)
.done(function (data, textStatus, xhr) {
alert(xhr.getResponseHeader('my-header'));
})
.fail(function () {
alert("error");
});
</script>
Add headers like this: (ofc change the type if needed or define your own)
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
What you're doing is creating a HttpResponseMessage object, serializing it to json and then returning it.
This is why the headers are in the json content, instead of the http response.
What you can do is someting like this:
[HttpGet, Route("Authenticate")]
public IActionResult Authenticate(string applicationId)
{
if(!_security.IsApplicationIdValid(applicationId))
{
return BadRequest(ErrorMessages.INVALID_APPLICATION_ID);
}
IAuthenticationProvider authProvider = _security.GetAuthenticationProvider();
this.Response.Headers.Add(HeaderKeyNames.CALLBACK_URI_KEY_NAME, authProvider.GetCallbackUrl());
this.Response.Headers.Add(HeaderKeyNames.AUTHENTICATION_SERVICE_REDIRECT_URI_KEY_NAME, authProvider.GetUrl());
return StatusCode(302);
}

Why is asp.net webAPI always returning text/html?

I would like to create webservices returning json. However, I'm always getting 'text/html' as the responses content type.
First shot:
public StringContent Get()
{
List<Cell> list = new List<Cell>();
Cell c = new Cell("Cell1");
Cell c2 = new Cell("Cell2");
list.Add(c);
list.Add(c2);
return new StringContent(
Newtonsoft.Json.JsonConvert.SerializeObject(list),
Encoding.UTF8,
"application/json");
}
Responsecontent: System.Net.Http.StringContent
second shot:
public List<Cell> Get()
{
Cell c = new Models.Cell("Cell1");
List<Cell> list = new List<Cell>();
list.Add(c);
return list;
}
Responsecontent: System.Collections.Generic.List`1[TestApp.Models.Cell]
This is how I access the endpoint:
$.ajax({
url: "http://localhost:54787/Cell/Get",
type: "GET",
contentType:"application/json",
accepts: {
text: "application/json"
},
success: function (response) {
$("#result").html(JSON.parse(response));
},
error: function (xhr, status) {
alert("error");
}
});
If you have no good reason to do serialization manually, you should use Web API default mechanism by returning object instead of StringContent. For example, you can change your method to return List<Cell> directly.
public List<Cell> Get()
{
// return List<Cell> just like you write a typical method
}
This way, you will not get text/html anymore. However, you will still get XML in Chrome. It is because Chrome's default HTTP Accept header contains application/xml, and it is supported by default in Web API. If you have no need to support XML result, so you can remove it by the following code during startup (maybe in Global.asax)
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
PS: If you don't know whether you need XML or not, then you don't need it.

spring 400 bad request. How can I fix it or at least see what is causing it?

I am having a real tough time with this. I have done a ton a research and nothing has worked. Please help. I have a spring REST call and a jquery ajax PUT and POST method that both give a 400 bad request. I have done JSON.stringify, raw object data, everything. I can't seem to find what is wrong and the ONLY clue I have is one 400 bad request error with no stack trace, nothing about how it SHOULD be formatted...nothing. Is there a way I can get more information as to what is wrong? It does not even get to the first line in the spring REST method below.
Spring REST code:
#RequestMapping(value = "/supervisor/agent", method=RequestMethod.PUT)
public void updateAgent(#RequestBody AgentDTO agent)
{
try {
AgentDTO sessionAgent = (AgentDTO) session.getAttribute(ADAuthenticationSuccessHandler.SESSION_AGENT);
RestTemplate restTemplate = new RestTemplate();
log.debug("Supervisor updating agent:"+agent);
String allURL = acrURL+"/company/"+sessionAgent.getCompanyGuid()+"/supervisor/"+sessionAgent.getAgentGuid()+"/agent/"+agent.getAgentGuid();
log.debug("Supervisor updating agent url:"+allURL);
agent.setEnabled(Mytime.ENABLED);
restTemplate.put(allURL, agent);
log.debug("Supervisor Agent updated");
} catch (Exception e) {
log.error("Error supervisor updating agent");
e.printStackTrace();
}
}
Here is the JQuery ajax call:
function editAgent()
{
console.log("edit agent");
console.log("chosenAgent:"+chosenAgent);
var anAgent = myAgents[chosenAgent];
anAgent.firstName = $('#SDEAFirstName').val();
anAgent.lastName = $('#SDEALastName').val();
anAgent.addressEmail = $('#SDEAEmail').val();
console.log(anAgent);
console.log(anAgent.agentGuid);
// var testData = '{"addressEmail": "agent7#csi.com","agentGuid": "EC165F8A-28F4-4765-BDC5-893722FCF6AA","firstName": "Agent","lastName": "0071","workStatus": "Offline}';
$.ajax({
type : 'PUT',
url : "/mytime.agentdesktop/supervisor/agent",
contentType : "application/json; charset=utf-8",
data: JSON.stringify(anAgent),
dataType : 'json',
success : function(result)
{
console.log("Agent edited:",anAgent.agentGuid);
init = false; // needed to reload agent data. Otherwise, it just grabs it but doesn't update gui
getMyAgents(); // reload agent data now that this agent was deleted
},
error : function(jqXHR, textStatus, errorThrown)
{
console.error("editAgent:status:"+textStatus+" error:", errorThrown);
}
});
editAgentDialog.dialog('close');
}
#RequestMapping(value = "/supervisor/agent", method=RequestMethod.PUT, consumes = "application/json")
You need to state which type of data you would be receiving in controller.
consumes = "application/json" does this.

Spring MVC - Return view with Ajax using POST and sending data

I am trying to develop a simple component which job is to render particular portion of the data using a template.
I am using a Spring-Data-Rest-MVC so I've got a ready and working OOTB source of the data that suits my requirements (AJAX-based web app).
So, with what I am having problem with.
The problem lies here:
{
"panels":[
{
"id":"panel-BASIC",
"el":"panel-BASIC",
"attributes":[
{
"position":"0",
"key":"id",
"display":"value",
"dataUtility":"",
"value":"2"
},
{
"position":"1",
"key":"begin",
"display":"value",
"dataUtility":"",
"value":1384518600000
},
{
"position":"2",
"key":"end",
"display":"value",
"dataUtility":"",
"value":1384518600000
},
{
"position":"3",
"key":"interval",
"display":"value",
"dataUtility":"intervalCalculationDataUtility"
}
]
},
{
"id":"panel-ONE_TO_MANY",
"el":"panel-ONE_TO_MANY",
"attributes":[
{
"position":"0",
"key":"tasks",
"display":"table",
"dataUtility":"",
"value":"http://localhost:8080/rest/appointment/2/tasks"
}
]
},
{
"id":"panel-MANY_TO_ONE",
"el":"panel-MANY_TO_ONE",
"attributes":[
{
"position":"0",
"key":"car",
"display":"infopage",
"dataUtility":"",
"value":"http://localhost:8080/rest/appointment/2/car"
},
{
"position":"1",
"key":"assignee",
"display":"infopage",
"dataUtility":"",
"value":"http://localhost:8080/rest/appointment/2/assignee"
},
{
"position":"2",
"key":"reporter",
"display":"infopage",
"dataUtility":"",
"value":"http://localhost:8080/rest/appointment/2/reporter"
}
]
}
],
"container":"ip-SAppointment"
}
It's the descriptor which is being sent to the server, previously built in the client side using retrieved data and template descriptor.
Using a JSON I've posted I need to sent a POST request with it and than return rendered view.
The job of a controller method is rather simple:
#RequestMapping(
value = "/template/render",
method = RequestMethod.POST,
produces = MediaType.TEXT_PLAIN_VALUE,
consumes = MediaType.APPLICATION_JSON_VALUE
)
public ModelAndView getInfoPageViewData(
#RequestBody final InfoPageDescriptor body
) {
LOGGER.trace(String.format("/getInfoPageViewData -> %s", body));
final ModelMap modelMap = new ModelMap();
modelMap.put("dd", body);
return new ModelAndView(DATA_VIEW_NAME, modelMap);
}
So as You can see it wraps the sent JSON into the InfoPageDescriptor bean which is placed than into ModelMap.
The returned view will process the bean from the model map and acts accordingly to entries.
Anyway I can get this method working. With the jQuery (AJAX-POST) call like this:
function loadRenderedView(url, data, callback) {
return $.ajax({
headers : {
'Accept' : 'text/plain',
'Content-Type': 'application/json'
},
url : url,
data : JSON.stringify(data),
dataType: 'json',
type : 'post',
success : function (data) {
callback.apply(this, [data, true]);
},
failure : function () {
callback.apply(this, [data, false]);
}
});
}
I get an error: The request sent by the client was syntactically incorrect..
Could You give some hints of how I should built a request or controller-server method to make it work ?
Ok, will post it as an answer, because I need to to have a formatting here.
#vzamanillo, Your assumption may be correct here, because I've checked the logs and got these exceptions:
2013-12-14 17:15:14 DEBUG ExceptionHandlerExceptionResolver:132 - Resolving exception from handler [null]: org.springframework.web.HttpMediaTypeNotSupportedException: Invalid media type "json": does not contain '/'
2013-12-14 17:15:14 DEBUG ResponseStatusExceptionResolver:132 - Resolving exception from handler [null]: org.springframework.web.HttpMediaTypeNotSupportedException: Invalid media type "json": does not contain '/'
2013-12-14 17:15:14 DEBUG DefaultHandlerExceptionResolver:132 - Resolving exception from handler [null]: org.springframework.web.HttpMediaTypeNotSupportedException: Invalid media type "json": does not contain '/'
I think it can be about an URLs that are sent in the JSON, so I will investigate that.
Add
Log4j.logger.org.springframework = INFO, yourlogger
to your log4j.properties and check traces, it seems you are sending a Json that does not match with the InfoPageDescriptor class.
EDIT:
change the dataType of stringify to "application/json" It maybe fix the issue and change the Accept header of the ajax request to
'Accept': 'application/json',

JSON Representation of a Backbone Model

Forking a json file using fetch method triggers error in my code. Seems the response from the server is not right. Into the details, for the ads model below
//Advertisement model
App.Tasks.Model.Ads = Backbone.Model.extend({
url: "ads/ads.json",
intialize: function () {
},
Next: function () {
var ads = this.get("ads");
return ads[Math.ceil(Math.random(0, ads.legth) * 10)];
}
});
how should the server response be when calling fetch(). Right now it is as below
{ads: ["1.png", "2.png", "3.png"]}
and doing this triggers the error callback
//Advertisement model
App.Tasks.Ads = new App.Tasks.Model.Ads();
App.Tasks.Ads.fetch({
success: function (model, response) {
console.log("Success", arguments);
},
error: function (model, response) {
console.log("Error", arguments);
}
});
Your server responds with an invalid JSON, the left part in a name/value pair must be a string, which means that ads should be wrapped in double quotes:
{"ads": ["1.png", "2.png", "3.png"]}
For the complete reference, check http://www.json.org/

Resources