How to jsonify "Add" post/parameters for jqGrid - web-services

This one's killing me. I've read through a lot of Oleg's comments, and through the documentation, but I think I'm overlooking something really simple.
I have a jqGrid populated by calling a webmethod that returns JSON. We're good there. I'm using the Navigator for my "Add" button, and using onSelectRow w/ jqGrid.editRow() for my editing.
I get the dialog box when clicking the "Add" button, and can fill everything in. However, I get a error Status: 'Internal Server Error'. Error code: 500 return message after clicking the Submit button. Using Firebug, the Response is {"Message":"Invalid JSON primitive: FileType.","StackTrace":..... and the Post is FileType=3&ExportDate=12%2F29%2F2010&oper=add&id=_empty.
Obviously, my post is not getting "jsonified". I have tried using serializeEditData, and beforeSubmit in an attempt to manually return JSON.stringify(eparams);, but nothing has worked. Please see my code below.
Webmethod
<WebMethod()> _
<ScriptMethod()> _
Public Sub ModifyFileLog(ByVal FileType As String, _
ByVal ExportDate As Nullable(Of Date), _
ByVal oper As String, ByVal id As String)
Try
' blah
Catch ex As Exception
Throw New Exception(ex.Message)
End Try
End Sub
JS - Globals
jQuery.extend(
jQuery.jgrid.defaults, {
type: "POST",
mtype: "POST",
datatype: "json",
ajaxGridOptions: { contentType: "application/json" },
ajaxRowOptions: { contentType: "application/json" },
rowNum: 10,
rowList: [10, 20, 30],
serializeGridData: function(data) {
return JSON.stringify(data);
},
gridview: true,
viewrecords: true,
sortorder: "asc"
},
jQuery.jgrid.edit, {
ajaxEditOptions: { contentType: "application/json" },
recreateForm: true,
serializeEditData: function(postData) {
return JSON.stringify(postData);
}
}
);
JS - jqGrid
var tblName = "tblFiles";
var pager1 = '#pagerFiles';
var grid = $("#" + tblName);
grid.jqGrid({
url: 'WebService.asmx/GetFileLog',
colNames: ['ID', 'File Type', 'Report Date', 'Export Date', 'EE Count'],
ajaxGridOptions: {
success: function(data, textStatus) {
if (textStatus == "success") {
ReceivedClientData(JSON.parse(getMain(data)).rows, grid); // populates grid
endGridRequest(tblName); // hides the loading panel
}
},
error: function(data, textStatus) {
alert(textStatus);
alert('An error has occured retrieving data!');
}
},
editurl: "WebService.asmx/ModifyFileLog",
serializeEditData: function(postData) {
return JSON.stringify(postData);
},
recreateForm: true,
pager: pager1,
...
}); // end .jqGrid()
grid.jqGrid('navGrid', pager1, { add: true, del: false, edit: true, view: false, refresh: true, search: false },
{}, // use default settings for edit
{
//beforeSubmit: submitAddFileLog,
closeAfterAdd: false,
closeAfterEdit: true
}, // use default settings for add
{}, // delete instead that del:false we need this
{multipleSearch: false }, // enable the advanced searching
{closeOnEscape: true} /* allow the view dialog to be closed when user press ESC key*/
); // end grid/jqGrid('navGrid')
NOTE: I started out populating by using $.ajax() by way of datatype: function(data), but thought I would return to the simplest example to get this to work. If you care to offer your thoughts on the advantages of using $.ajax() over simply using grid.jqGrid({ url: blah });, I'd love to learn more. Otherwise, please let me know if it would be more appropriate to post it as a separate question.
Also, please let me know if I'm just flat out doing this the wrong way. I'm not locked in to any one way of getting this done. I would prefer to be wrong and to learn how to do this the right way, than to be "right" in my own mind and continue to hack my way through it.
Any help, along w/ examples, would be hugely appreciated.

In my opinion your main problem is in JS - Globals. You use jQuery.extend function in a wrong way. You should replace one call
jQuery.extend(
jQuery.jgrid.defaults, {
// ...
},
jQuery.jgrid.edit, {
// ...
}
);
to two separate calls:
jQuery.extend(
jQuery.jgrid.defaults, {
// ...
}
);
jQuery.extend(
jQuery.jgrid.edit, {
// ...
}
);
After that the edit request to the server will be {"FileType":3,"ExportDate"="12/29/2010","oper":"add","id":"_empty"} instead of FileType=3&ExportDate=12%2F29%2F2010&oper=add&id=_empty.
Next, I am not sure that you can use ExportDate as a Date (DateTime ???) type. Probably you should start with String type and then convert the input data to the datatype which you need.
Next remark. Be sure that ModifyFileLog return JSON data. For example you can use <ScriptMethod(ResponseFormat:=ResponseFormat.Xml)> instead of <ScriptMethod()>. If you use .NET 4.0 you can achieve the same in many other ways.
One more thing. The ModifyFileLog should be Function instead of Sub and return the Id of new added object. In case of edit or del operations the return value will be ignored.
Because ModifyFileLog Function will be returned JSON data you have to decode/parse it. You can do this almost in the same way which I described here. In case of ASMX web service you can do about following:
jQuery.extend(
jQuery.jgrid.edit, {
ajaxEditOptions: { contentType: "application/json" },
recreateForm: true,
serializeEditData: function(postData) {
return JSON.stringify(postData);
},
afterSubmit: function (response, postdata) {
var res = jQuery.parseJSON(response.responseText);
return [true, "", res.d];
}
}
);

Related

Postman - How to replace values for all specific properties in the JSON Response, to use it later as another Request's Body

I have 2 API requests. 1st one is GET, that returns a response. This response is used as a Body/Payload in the 2nd request (POST). BUT the Payload should have certain values to be replaced before used in the 2nd request (in my case below it should be value for "Status" property).
How can I do it?
Here is my example Response:
{
"Variations":[
{
"ItemIds":[
"xxx"
],
"Items":[
{
"Id":"67-V1",
"GuId":"xxx",
"Type":"Unit",
"Status":"Active"
}
],
"Name":"VAR 1",
"Id":"67-V1"
},
{
"ItemIds":[
"yyy"
],
"Items":[
{
"Id":"67-V2",
"GuId":"yyy",
"Type":"Unit",
"Status":"Active"
}
],
"Name":"VAR 2",
"Id":"67-V2"
},
{
"ItemIds":[
"zzz"
],
"Items":[
{
"Id":"67-V3",
"GuId":"zzz",
"Type":"Unit",
"Status":"Active"
}
],
"Name":"VAR 3",
"Id":"67-V3"
}
],
"ItemIds":[
],
"Items":[
],
"Name":"MAINP",
"Id":"67",
"Color":null
}
Here is my code, but it does not seem to work (the replacement part):
var jsonData = pm.response.json();
function replaceStatus() {
_.each(jsonData.Variations, (arrayItem) => {
if(arrayItem.Items.Status !== "NonActive") {
arrayItem.Items.Status == "NonActive";
console.log("arrayItem " + arrayItem);
}
});
}
pm.test("Run Function", replaceStatus ());
pm.sendRequest({
url: 'localhost:3000/post',
method: 'POST',
headers: {
"Content-Type": "application/json"
},
body: {
mode: 'raw',
raw: JSON.stringify(jsonData)
}
}, (err, res) => {
console.log(res)
})
I guess you are trying to replace all NonActive values with Active. In that case, you should use = for assignment not ==. The JSON file you provided is not valid and couldn't run your code on my machine. I am happy to have a closer look if that didn't work
Based on your updates these changes need to be made
1- in order to deal with JSON object you need to parse the response as it is string and you can't call sth like JsonData.Variations on that.make sure jsonData is a JSON object. if not add sth like this to parse it
var parsedJson = JSON.parse(jsonData)
2- It seems that you missed one array layer in your function to iterate over items. As you have two nested arrays to reach Status the replaceStatus function should be as below
function replaceStatus() {
_.each(parsedJson.Variations, (arrayItem) => {
_.each(arrayItem.Items, (item) => {
if(item.Status !== "NonActive") {
item.Status = "NonActive";
console.log("arrayItem " + item.Status);
}
});
});
}
Have you posted your entire code in the tests section or only a part of it?
I saw from one of your comments that you cannot see the output logged to the console.
This may be very trivial, but, if you did post your entire code, it looks like you may have forgotten to call your replaceStatus() function before your post call.

How dis you get oauth-1.0a and crypto to work with WP-API

I am using crypto and oauth-1.0a from nmp in ionic2 application. I want to access WP-API which is correctly set to handle authentication, I tested this using Postman.
Http.Get results in the following error:
{
"_body": {
"isTrusted": true
},
"status": 0,
"ok": false,
"statusText": "",
"headers": {},
"type": 3,
"url": null
}
The options generated that I pass as argument to Http.Get are as follows:
{“method”:0,“headers”:{“Authorization”:“OAuth oauth_consumer_key=”",
oauth_nonce=“jSZGPwkj4quRGMb0bhBLYKwmc3BGfrQw”, oauth_signature=“x3zseS3XTFBLMsNDLXC4byn2UDI%3D”,
oauth_signature_method=“HMAC-SHA1”, oauth_timestamp=“1522414816”,
oauth_token="",
oauth_version=“1.0"”},“body”:null,“url”:"",“params”:{“rawParams”:"",“queryEncoder”:{},“paramsMap”:{}},“withCredentials”:null,“responseType”:null}
Part of code:
this.oauth = new OAuth({
consumer: {
key: this.apiconstant.consumerkey,
secret: this.apiconstant.consumersecret
},
signature_method: ‘HMAC-SHA1’,
hash_function: hash_function_sha1,
realm:’’
});
let request_data = {
url: ‘’,
method: ‘GET’
};
let token={
key: this.apiconstant.token,
secret: this.apiconstant.tokensecret
}
//This part doesn’t seem to work
this.authkey = this.oauth.authorize(request_data,token);
this.keyoauth = new URLSearchParams();
for (let param in this.authkey) {
this.keyoauth.set(param, this.authkey[param]);
}
let options = new RequestOptions({
method: ‘GET’,//request_data.method
url: ‘’,
headers: this.oauth.toHeader(this.oauth.authorize(request_data,token)),
search: this.keyoauth
});
this.http.get(’’,options)
.map(res => res.json()).subscribe(data=>{
console.log(‘Resulting data’ + JSON.stringify(data));
},
error=>{
console.log(‘Got error’+JSON.stringify(error));
});
//Error part executed
What am I missing here? I’m testing my app on android device. Without authentication I get desired results from the WP-API (Wordpress), that is if the Oauth is disabled on WP-API.
Please help! This is my second day on this. I should also let you know I’m new on these technologies but I’m able to research and understand how they work.

Loading Remote Data using Select2 and Webservice

I am using Select2 4.0.3 in my web forms .net application. I am trying to Load Remote data using a webservice, but its not working as expected.
First Issue am facing is that the webservice method is not getting called and am getting a console error:
System.InvalidOperationException: Missing parameter: text.
at System.Web.Services.Protocols.ValueCollectionParameterReader.Read(NameValueCollection collection)
at System.Web.Services.Protocols.HtmlFormParameterReader.Read(HttpRequest request)
at System.Web.Services.Protocols.HttpServerProtocol.ReadParameters()
at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()
So I tried removing the paremeter from the webservice call
<WebMethod()> _
Public Function GetDataFromService() As String
Doing this the method got fired, but still the items in the select2 did not get populated (screenshot atached).
Can someone help me to figure out where am I making a mistake.
Here are the details:
Select2 Code in the Webform:
$("#ddlEntity").select2({
ajax: {
url: "Service/InvoiceHTMLService.asmx/GetDataFromService",
type: 'POST',
delay: 250,
params: {
contentType: 'application/json; charset=utf-8'
},
dataType: 'json',
data: function (term, page) {
return {
text: term,
};
},
processResults: function (data, params) {
// parse the results into the format expected by Select2
// since we are using custom formatting functions we do not need to
// alter the remote JSON data, except to indicate that infinite
// scrolling can be used
params.page = params.page || 1;
return {
results: data.items,
pagination: {
more: (params.page * 30) < data.total_count
}
};
},
cache: true
},
escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
minimumInputLength: 1,
templateResult: formatRepo, // omitted for brevity, see the source of this page
templateSelection: formatRepoSelection // omitted for brevity, see the source of this page
});
WebService Method:
<WebMethod()> _
Public Function GetDataFromService(text As String) As String
Return "{['id':1, 'text':'Test1'],['id':2, 'text':'Test2']}"
End Function
Try this please
var fd = new FormData();
fd.append("text",term);
ajax: {
url: "Service/InvoiceHTMLService.asmx/GetDataFromService",
type: 'POST',
delay: 250,
params: {
contentType: 'application/json; charset=utf-8'
},
dataType: 'json',
data: fd
...
I think you did not create template for this select2. since you are using templateResult and templateSelection it requires template or you can remove those two options.
For your reference : https://select2.github.io/examples.html#templating
Updated:
they have changed query callback from
data: function (term, page) {
return {
text: term,
};
},
into
data: function (params) {
return {
q: params.term, // search term
page: params.page
};
},

Optimistic UI Not Updating - Apollo

After making a mutation the UI does not update with a newly added item until the page is refreshed. I suspect the problem is in the update section of the mutation but I'm not sure how to troubleshoot further. Any advice is much appreciated.
Query (separate file)
//List.js
export const AllItemsQuery = gql`
query AllItemsQuery {
allItems {
id,
name,
type,
room
}
}
`;
Mutation
import {AllItemsQuery} from './List'
const AddItemWithMutation = graphql(createItemMutation, {
props: ({ownProps, mutate}) => ({
createItem: ({name, type, room}) =>
mutate({
variables: {name, type, room},
optimisticResponse: {
__typename: 'Mutation',
createItem: {
__typename: 'Item',
name,
type,
room
},
},
update: (store, { data: { submitItem } }) => {
// Read the data from the cache for this query.
const data = store.readQuery({ query: AllItemsQuery });
// Add the item from the mutation to the end.
data.allItems.push(submitItem);
// Write the data back to the cache.
store.writeQuery({ query: AllItemsQuery, data });
}
}),
}),
})(AddItem);
Looks promising, one thing that is wrong is the name of the result of the mutation data: { submitItem }. Because in the optimistic Response you declare it as createItem. Did you console.log and how does the mutation look like?
update: (store, {
data: {
submitItem // should be createItem
}
}) => {
// Read the data from our cache for this query.
const data = store.readQuery({
query: AllItemsQuery
});
// Add our comment from the mutation to the end.
data.allItems.push(submitItem); // also here
// Write our data back to the cache.
store.writeQuery({
query: AllItemsQuery,
data
});
}
I'm not entirely sure that the problem is with the optimisticResponse function you have above (that is the right approach), but I would guess that you're using the wrong return value. For example, here is a response that we're using:
optimisticResponse: {
__typename: 'Mutation',
updateThing: {
__typename: 'Thing',
thing: result,
},
},
So if I had to take a wild guess, I would say that you might want to try using the type within your return value:
optimisticResponse: {
__typename: 'Mutation',
createItem: {
__typename: 'Item',
item: { // This was updated
name,
type,
room
}
},
},
As an alternative, you can just refetch. There have been a few times in our codebase where things just don't update the way we want them to and we can't figure out why so we punt and just refetch after the mutation resolves (mutations return a promise!). For example:
this.props.createItem({
... // variables go here
}).then(() => this.props.data.refetch())
The second approach should work every time. It's not exactly optimistic, but it will cause your data to update.

extjs 4.1 pagingtoolbar displays correctly but grid loads all records

Okay, so I've been at this all day and can't figure out why the grid is loading all records instead of the pageSize: 25 limit I configured on the store. The paging toolbar is rendering the correct pages, but the grid is what is autoloading all records. I'm thinking it is because of the way my controller is loading the view. I have my .cfc server side processing setup correctly using the paging_on, start, limit, sort and dir in my arguments. If anyone can help me out, it would be greatly appreciated.
Here is my controller:
onAccountActivityListAfterrender: function(pnl, eOpts) {
var store = this.getStore("AccountSessions");
store.load({
params : {
start : 0,
limit : 25
},
callback: function (recs, op, success) {
if (!success) {
Ext.Msg.alert("Error!", op.error[0].ERROR);
}
var grid = Ext.getCmp('pnl-accountactivity-list');
grid.getStore().add(store.getRange());
this.showApp(pnl);
},
scope: this
});
},
and here is my store:
Ext.define("EXAMPLE.store.AccountSessions", {
alias: "store.AccountSessions",
extend: "Ext.data.Store",
model: "EXAMPLE.model.AccountSession",
pageSize: 25,
proxy: {
api: {
create : undefined,
read : "ajax/account.cfc?method=account_sessions",
update : undefined,
destroy : undefined
},
extraParams: {
account_id: account
},
reader: {
messageProperty: "ERRORS",
root: "DATA",
successProperty: "SUCCESS",
totalProperty: "TOTAL",
type: "json"
},
type: "ajax"
}
});
You'd better to show the server-side codes.
Make sure the values that returned correctly~