can.Model destroy with multiple parameters - canjs

I'm working with an API over which I have no control. I would like to do something like this:
var Page = can.Model.extend({
destroy: 'DELETE /api/{account_id}/{page_id}'
})
This doesn't work - canjs simply doesn't use the destroy URL. I tried creating a function, but the only param passed is the 'id'. I'm sure you'll say that this is not really REST, but I'm stuck with the API. Any time I put more than one param into the url, the url is not used.
Any ideas?

You're actually setting the prototype destroy property to a string here, because the first object passed to extend() is interpreted as the prototype properties if a second object is not passed. You actually need to do this:
var Page = can.Model.extend({
destroy: 'DELETE /api/{account_id}/{page_id}'
}, {})
(NB: CanJS internally converts destroy and some other properties from AJAX specs to functions when you extend can.Model, but only in the static properties)

It seems this is OK (took a while to figure out that the 2nd parameter is the instance... didn't see that documented anywhere):
var Page = can.Model.extend({
destroy: function(id, page) {
return $.get('/api/'+page.account_id+'/'+page.id);
}
})
Which seems a bit weird, but I'll get over it!

Related

How to post part of the viewmodel to a Web API controller

I have a VB Web API app.
I have a VB class/model like so.
Imports System.ComponentModel.DataAnnotations
Imports System.Web.Http
Public Class MSLDestinationInput
<HttpBindRequired>
<Required>
Public Property ShpmntCntrlNbr() As String
Get
Return m_ShpmntCntrlNbr
End Get
Set(value As String)
m_ShpmntCntrlNbr = value
End Set
End Property
Private m_ShpmntCntrlNbr As String
End Class
This is the controller:
Public Async Function GeneratePDF(data As MSLDestinationInput) As Task(Of IHttpActionResult)
If Not ModelState.IsValid Then
Return BadRequest(ModelState)
End If
Dim oMSLOutput As New MSLOutput
oMSLOutput.url = "api/PrintGenerateMSL"
Return Ok(oMSLOutput)
End Function
I am posting to the controller using jQuery.ajax with this parameters:
url: 'api/PrintGenerateMSL',
data: ko.toJSON(self),
type: "POST",
and everything is working well. However I don't really need to send the entire knockout model. I just need to send some of the properties. I've tried to send this data:
data: {ShpmntCntrlNbr : self.ShpmntCntrlNbr() };
instead of ko.toJSON(self). When the request reaches my controller, I find the parmeter data is empty.
How can I send only the required data to my controller instead of the whole ko view model?
You need to stringify the data. One way to do it is by using JSON.stringify, as you've done.
Most, but not all browsers, include the JSON manipulation functions. The problem is that if someones tries to use your application in a browser that doesn't have this methods, it will crash. Or you'll have to suplly a polyfill.
The good news is that you don't need to worry about it if you use ko.toJSON. In fact ko.toJSON does two things:
unwraps all the observables, if they exist
convert to JSON, by using JSON.stringify
That means that both of this options would work fine:
data: ko.ToJSON({ShpmntCntrlNbr : self.ShpmntCntrlNbr() })
data: ko.ToJSON({ShpmntCntrlNbr : self.ShpmntCntrlNbr })
Note that the property on the second one would be automatically unwrapped. If you took a piece of your viewmodel which is an object tree that includes some observable properties at any level, ko would also unwrap them automatically.
And, best of all, if the browser does not implement JSON.stringify, ko provieds its own implementation.
yes stringify took care of it. it is working now with.
data: JSON.stringify({ShpmntCntrlNbr : self.ShpmntCntrlNbr() }),

Post Data Getting Lost during Ajax Post Request in Razor

I am working on an ASP.net MVC 3.0 Application with razor view engine.
I am making an ajax post as follows:
$.ajax({
type: "post", contentType: "application/json;charset=utf-8",
url: GetErrorCountUrl,
success: function (data) {
});
Here, the URL is as follows:
var GetErrorCountUrl = '#Url.Action("GetErrorCount", "WError", new { Id= "Token", id1 = "Token1", id2= "Token2" })';
GetErrorCountUrl = GetErrorCountUrl.replace('Token',pkid).replace('Token1',cid).replace('Token2',itemclass);
I am building the correct URL . I checked by using alert(url). It is hitting that controller action.
In my controller action,
If i do : Request.params["Id"] --> I was getting the correct value
Reuqest.params["id1"] --> I am getting null values
but, when i do:
reuqest.Params[0] --> correct value
request.params[1] ---> Correct value
I was getting correct values when using index instead of name.
I need get those values based on Parameter name not on index.
Please help.
Except for the first parameter..i was not able to get the values of other parameters
First of all the name of variabeles should start with low letter in JavaScript. Names with the first capital variable should be used only for classes (functions used in constructors). Prettify formatting of the code used on stackoverflow uses other colors for JavaScript classes. For example to define data in JavaScript one should use var d = new Date(); instead of var d = new Date();. So the code like var GetErrorCountUrl = "some string"; looks in JavaScript very strange. I understand that JavaScript is not your main language, but it's really better the name conversion used in the language which one uses.
Now back to your main question. It seems to me that
GetErrorCountUrl.replace('Token',pkid).replace('Token1',cid).replace('Token2',itemclass);
Isn't what you really want. If the string GetErrorCountUrl contains 'Token1' then the 'Token' part of the substring 'Token1' will be first replaced to pkid and the next replacement (to cid) will never work.
To fix the problem you can change the order or replacements to the following for example:
GetErrorCountUrl.replace('Token1',cid)
.replace('Token2',itemclass)
.replace('Token',pkid);

Ajax request, should it be POST or PUT

I have created a Spring MVC web app.
The app makes a few calls to the controller. These calls are close/open/end game.
I make these calls using Ajax, so I can handle a response on the top of the page.
ajaxPost = function (url, action, id, onSuccess, onError) {
$.ajax({
type: "POST",
url: url + "?" + action + "=" + id,
success: function(response) {
if(onSuccess !== null) {
onSuccess(response);
}
},
error: function(e) {
if(onError !== null) {
onError(e);
}
}
});
};
The question I have is that I'm using 'POST' for the Ajax request, is that correct, or should it be 'PUT'?
My controller has a default URL, and I'm using the param attribute to decide which method to call, as I have many buttons on the page.
#RequestMapping(params = "open", method = RequestMethod.POST)
#RequestMapping(params = "close", method = RequestMethod.POST)
It doesn't sit well with me that I'm using 'POST' for these calls. Maybe it should be 'PUT'...
Any suggestions? Does it matter?
It depends on what your request should do. So there's no general rule that you should use one over the other, they have different use cases.
POST for creating a record.
PUT for updating an existing record (or putting a record at a specified location/id).
See this wikipedia article for the definitions.
One thing to note is that PUT should be idempotent, doing the same PUT request multiple times should ideally produce the same result as doing a single PUT request. However, POST is not idempotent, so doing several POST requests should (or will) create multiple new records.
So after having read this you should check what your method does, and select the corresponding request method.
Both PUT and POST may create a new record; PUT may also update/change an existing record.
The difference between POST and PUT is that PUT is expected to address the record with it's ID, so that the server knows what ID to use when creating (or updating) the record, while POST expects the server to generate an ID for the record and return it to the client after the record has been created.
Thus, a POST is addressed to the resource as a collection: POST /resource, while PUT is addressed to a single item in the collection: PUT /resource/1
Use POST. Always use POST, unless you're absolutely rock-solid certain that PUT is properly supported by your hosting system.

dojo.io.script.get vs dojo.xhrGet

I have spent days working on this and really feel dumb. I have been working on demos and samples that never work when I try it locally with my own url. I have a web service that returns results back in json and am just basically trying to call it using dojo and for now just view the results. I took the search google example and just substituted the url and parameters. Now perhaps I still do not understand the basics so:
- io.script.get vs xhrGet
if using cross domain urls it is better to use io.script.get? correct?
now what is the callbackparam? is this the function that is being called in the webservice?
My webservice url is as follows:
http://xxx.xxx.x.xxx/WcfServices/WcfInstance/Service1.svc/RetrievData?query=Word
when I use the following code I get nothing displayed.
function searchGoogle() {
// Look up the node we'll stick the text under.
var targetNode = dojo.byId("rules");
// The parameters to pass to xhrGet, the url, how to handle it, and the callbacks.
var jsonpArgs = {
url: "http://xxx.xxx.x.xxx/WcfServices/WcfInstance/Service1.svc/RetrieveData?",
callbackParamName: "callback",
content: {
query:"dojowords"
},
load: function (data) {
// Set the data from the search into the viewbox in nicely formatted JSON
targetNode.innerHTML = "<pre>" + dojo.toJson(data, true) + "</pre>";
},
error: function (error) {
targetNode.innerHTML = "An unexpected error occurred: " + error;
}
};
dojo.io.script.get(jsonpArgs);
}
dojo.ready(searchGoogle);
Here is what the webservice results look like:
"{\"rules\":[{\"value\":\"AllState\"},
{\"value\":\"Cidade de Goa beach\"},{\"value\":\"Euro 2012\"},
{\"value\":\"Euro2012\"},{\"value\":\"European&Championship\"},
{\"value\":\"Holiday Inn Resort\"},
{\"value\":\"Holiday Inn Resort goa\"},
{\"value\":\"Hotel Goa\"},{\"value\":\"Hyatt Goa\"},{\"value\":\"I buy car\"},...
If I get this part correct then at least I know I have data which I can then bind to a datagrid or chart.
dojo.io.script.get is for all cross domain requests.
xhrGet is for same domain requests.
dojo.io.script.get uses a hack which expects jsonp or json padding as a result. This wraps the response of the web service call inside a self executing function. The function name is the callback name. This has to be wired before the call so it knows what already defined function to call when a response comes back.
All of the arguments are well documented http://dojotoolkit.org/reference-guide/1.7/dojo/io/script.html
My guess as to why your service isn't working is because you wrote the web service and it does not handle jsonp. It is not wrapping its response inside the callbackparamname.
your results should look something like
callback({json});
where callback is whatever you set up in callbackParamName
you can also remove the ? from your url, that should be handled for you.

Make Wordpress Ajax calls work with global variables to reduce database queries

I posted this earlier on wordpress.stackexchange.com. However, never got a reply. Hence, trying my luck here.
I am hereby providing a detailed description of what I need and what I have done for this issue of mine. I am open to any workable solution around what I have done or maybe new suggestions.
I need to make use of user data that is retrieved using the following:
$user_data = get_user_by('login', get_query_var('user_login'));
The above code uses the username passed as a query_var in the URL. All works until here.
I make use of the above code in several Ajax callbacks (handled by admin-ajax.php) on single page load. Since, the site is targeted as a high volume site. All these Ajax requests lead to several database query for the same data. So the obvious idea to save some database queries is to pass the data to a global variable like below:
$_GLOBALS['user_data'] = get_user_by('login', get_query_var('user_login'));
And then use the same in the Ajax callbacks. Here's problem. None of the Ajax callback functions see the global $user_data variable. Before you ask, yes I have declared the global inside callback as well.
So, the obvious answer would be: why not use wp_localize_script and pass the $user_data to the Ajax callback via javascript like bellow:
In PHP:
wp_localize_script('jquery', 'ajaxVars', array( 'ajaxurl' => admin_url('admin-ajax.php'), 'user_data' => $user_data));
In Javascript:
jQuery.ajax({
url: ajaxVars.ajaxurl,
type:'POST',
async: false,
cache: false,
timeout: 10000,
data: 'action=ajax_callback&user_data=' + ajaxVars.user_data,
success: function(value) {
alert(value);
},
error: function() {
alert(error);
}
});
However, this poses two questions:
Can an object that get_user_by('login', get_query_var('user_login')); returns be handled by wp_localize_script()?
If the answer to above question is yes, then would it not pose a security threat since the object would contain sensitive user information?
To overcome the global variable being not available to Ajax callbacks, I declared it directly in functions.php (without wrapping it inside a function). However, get_query_var('user_login') does not return any data when used directly inside functions.php making this futile exercise (You have to add it inside a function and call it via an action).
So, the question remains: how do I stop making $user_data = get_user_by('login', get_query_var('user_login')); calls for every Ajax request? Or is there a way I could get get_query_var('user_login') to work inside functions.php directly (without wrapping it inside a function) or a workaround?
Or maybe some completely new out of the box thinking?
All these Ajax requests lead to several database query for the same
data. So the obvious idea to save some database queries is to pass the
data to a global variable like below:
$_GLOBALS['user_data'] = get_user_by('login', get_query_var('user_login'));
And then use the same in the Ajax callbacks.
Each request that your application receives, AJAX or otherwise, lives completely in isolation: the code handling the requests does not share any state between them (besides whatever is persisted to a database). A global (or constant, or property, or variable, or anything) you define in one request will never be available to subsequent requests unless you store it somewhere.
There are a number of approaches to reducing the number of queries these requests are creating. One would be to retrieve the required user data on page load and pass it to subsequent requests. E.g.:
var user = 'someUser';
$.get('user-data.php?user=' + user, function(user_data) {
$.ajax('some-endpoint.php', {
type: 'POST',
data: { user: user_data },
success: function() { /* ... */ }
});
$.ajax('some-other-endpoint.php', {
type: 'POST',
data: { user: user_data },
success: function() { /* ... */ }
});
});
Alternatively, if it's the currently logged in user you're working with you can write their details to a JavaScript object on initial page load for use later.
var userData = <?php get_currentuserinfo(); echo json_encode($current_user); ?>;
Another option would be to ensure that the get_user_by results were being cached, either by Wordpress, MySQL or some other caching layer. That way it doesn't particularly matter how many times your code calls the method.
In general if lots of your endpoints are sharing functionality, you could probably stand to refactor some of that code.

Resources