NodeJs : Any way to bypass querystring.stringify with empty Object? - node.js

I am working currently on a project that requires to send custom GET HTTP requests.
I am using the default querystring builder : the Documentation
const querystring = require('querystring');
The problem is for Object (probably also for empty array) such as
extendTypes={}
is serialiazed as :
extendTypes=
The expected result :
extendTypes={}
or its URI encoded version :
extendTypes%3D%7B%7D
So , how can I ever hope to do that ? If It is impossible with the in-builded module, which one could do what I want.
Here is my full code if you want :
function generateGetRequest(dataMap, url) {
let queryParams = {};
let uriParams = {};
for (let [key, value] of dataMap) {
// if value is an object or an array
if (value instanceof Object || value instanceof Array) {
uriParams[key] = value;
} else {
// param working for superagent
queryParams[key] = value;
}
}
let queryParamsUri = querystring.stringify(uriParams);
console.log(queryParamsUri);
let finalUrl = url + ( (Object.keys(uriParams).length > 0) ? "?" + queryParamsUri : "");
}

I finally found a workaround , if someone wants to know :
let request = require("superagent");
function generateGetRequest(dataMap, url) {
let queryParams = {};
let queryParamsUri = "";
let isFirstParam = true;
for (let [key, value] of dataMap) {
// if value is an object or an array
if (value instanceof Object) {
// Workaround for empty object or array = https://github.com/nodejs/node/issues/12234
queryParamsUri += ((!isFirstParam) ? "&": "") + key + "=" + JSON.stringify(value);
// for next call
isFirstParam = false;
} else {
// param working for superagent
queryParams[key] = value;
}
}
let finalUrl = url + ( (!isFirstParam) ? "?" + queryParamsUri : "");
return request
.get(finalUrl)
.query(queryParams);
}

Related

using express node.js, call a function in a function and exports and require in router and hand in to ejs when rendering in router

can a function be recognized inside a function when both would be exported?
this is my code
exports.generateUrlWithParam = function(idpUrl,subUrl,param){
var url = generateUrl(idpUrl, subUrl);
if(url == null) {
return null;
}
var paramStr = generateParam(param);
return url + "?" + paramStr;
}
and this function is to be used inside generateUrlWithParam
exports.generateUrl = function(idpUrl, subUrl) {
if((idpUrl == null || ""==idpUrl.trim()) && (subUrl == null || ""==subUrl.trim())) {
return null;
}
let url = idpUrl
if(!idpUrl.endsWith("/")) {
url += "/";
}
url += subUrl;
url = url.replace(/\/+/g, "/");
if(url.startsWith("http:/") && !url.startsWith("http://")) {
url = url.replace(/^http:\//, "http://");
} else if(url.startsWith("https:/") && !url.startsWith("https://")) {
url = url.replace(/^https:\//, "https://");
}
return url;
}
and they will be used in ejs file.
apparently generateUrl is not recognized
i'm using this js file by 'require' in my router file and hand to the ejs file
any ideas would be appreciated in advance thank you.
You can refer this function as var url = exports.generateUrl(idpUrl, subUrl);

How to change the default values when add link Sharepoint 2013

In Add Link page, is it possible to change the default values like title, address, show these links to, by using URL parameters?
According to this, it seems possible in sharepoint2010. Does anyone know whether it works in 2013??
If not, is it possible to add a link by post REST API??
This problem can be solved by the steps below.
Add a custom action. Just follow the steps here.
In my case code is as below
SP.SOD.executeFunc("callout.js", "Callout", function() {
var itemCtx = {};
itemCtx.Templates = {};
itemCtx.BaseViewID = 'Callout';
// Define the list template type
itemCtx.ListTemplateType = 101;
itemCtx.Templates.Footer = function(itemCtx) {
// context, custom action function, show the ECB menu (boolean)
return CalloutRenderFooterTemplate(itemCtx, AddCustomAction, true);
};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(itemCtx);
});
function AddCustomAction(renderCtx, calloutActionMenu) {
// Add your custom action
calloutActionMenu.addAction(new CalloutAction({
text: "FAVORITE",
// tooltip: 'This is your custom action',
onClickCallback: function() {
CreateCustomNewQuickLink(renderCtx.CurrentItem.FileLeafRef, renderCtx.CurrentItem.FileRef);
}
}));
// Show the default document library actions
CalloutOnPostRenderTemplate(renderCtx, calloutActionMenu);
}
function CreateCustomNewQuickLink(title, url) {
var urlAddress = $(location).attr('protocol') + "//" + $(location).attr('host') + '/_Layouts/quicklinksdialogformTEST.aspx?Mode=Link' +
'&title=' + encodeURIComponent(title) +
'&url=' + encodeURIComponent(url);
ShowNewQuicklinkPopup(urlAddress, PageRefreshOnDialogClose);
}
Create a new add link page which is copied from "quicklinksdialogform.aspx". I add some javascript as below.
$(init)
function init() {
var args = new Object();
args = GetUrlParms();
if (args["title"] != undefined) {
$(".ms-long")[0].value = decodeURIComponent(args["title"]);
}
if (args["url"] != undefined) {
$(".ms-long")[1].value = decodeURIComponent(args["url"]);
}
}
function GetUrlParms() {
var args = new Object();
var query = location.search.substring(1);
var pairs = query.split("&");
for (var i = 0; i < pairs.length; i++) {
var pos = pairs[i].indexOf('=');
if (pos == -1) continue;
var argname = pairs[i].substring(0, pos);
var value = pairs[i].substring(pos + 1);
args[argname] = unescape(value);
}
return args;
}
It works like below

how to return default value if no query string in url window.location.search

The code below will get the URL variables..
For example: http://www.example.com/index.php?id=1&image=awesome.jpg
Calling getQueryVariable(“id”) – would return “1”
Calling getQueryVariable(“image”) – would return “awesome.jpg”
function getQueryVariable(variable)
{
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if(pair[0] == variable){return pair[1];}
}
return(false);
}
What if i want to return default value with the URL without query parameters? http://www.example.com/index.php
I still want to return “id” value = “predefined value"
You can do something like:
function getQueryVariable(variable)
{
default_values= {'id':-1,'image':'123.jpg'}
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if(pair[0] == variable){return pair[1];}
}
return(default_values[variable] || false);
}
Two suggestions:
1) set a default options object and return the desired value of that key if the url contains no parameters.
function getQueryVariable(variable)
{
var defaultValues = {
id: 'predefined valie',
image: 'defaultimage.jpg'
}
var query = window.location.search.substring(1);
var vars = query.split("&");
if (vars.length == 0) return defaultValues[variable] || false;
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if(pair[0] == variable){return pair[1];}
}
return(false);
}
getQueryVariable('id'); //will return query parameter id or 'predefined value' if the url contains no parameters
2) or set the desired default value when calling the function.
function getQueryVariable(variable, defaultValue)
{
var query = window.location.search.substring(1);
var vars = query.split("&");
if (vars.length == 0) return defaultValue || false;
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if(pair[0] == variable){return pair[1];}
}
return(false);
}
getQueryVariable('id', 'predefined value'); //will return query parameter id or 'predefined value' if the url contains no parameters
getQueryVariable('image', 'defaultimage.jpg'); //will return query parameter image or 'defaultimage.jpg' if the url contains no parameters

querystring not passing values to controller

Passing few values through querystring, to testFn() in controller using below code. But in testFn, I am getting null values. When I keep alert on companyName, rdVal,etc. it is showing correct values. but those are not passing to controller. Please let me know what went wrong.
View:
#Html.ActionLink("Search", null, null, new { id = "lnkSearchMaster", #class = "btn btn-success", onclick = "return lnkgotoAction();" })
function lnkgotoAction() {
$('#grdSearchResults').show();
$('#searchdetails').show();
var rdVal = $("input[name = SearchType]:checked").attr("id");
if (rdVal == "CompanyList" || rdVal == "CompanyHistory" || rdVal == "ApplicationSatatus" || rdVal == "Certificates") {
$('#grdSearchResults').show();
var companyName = $('#companyname').val();
var status = $('#status').val();
var regNo = $('#registrationno').val();
var appRegNo = $('#applicationrefferenceno').val();
var url = '#Url.Content("~/")' + "Search/testFn?test='" + rdVal + "'&companyName='" + $('#companyname').val() +
"'&regNum='" + $('#registrationno').val() + "'&appRegNum='" + $('#applicationrefferenceno').val() + "'";
alert(url);
}
$('#grdSearchResults').load(url + ' #grdSearchResults');
TempData.clear();
$('#grdSearchResults').show();
$('#searchdetails').show();
return false;
}
Controller:
public ActionResult testFn(string test, string companyName, string regNum, string appRegNum)
{}
Try as below, it will help you, also always take care the variable name passed to querystring must match controller action parameter names.
#Html.Raw(Url.Action("testFn", "Search"), new{ test= rdVal , companyName= companyName , regNum= regNo , appRegNum= appRegNo })

Asynchronous calls using Async and Await

In .Net framework 4.5 async and await keywords are introduced to do async calls.
I have used them in web applications too. I came to know that it can also be done using doing delegates.
Below are my sample snippet showing how async calls are done
Public void binddata()
{
certificate = HelperMethods.GetStoreCertifcate(Thumbprint);
ListHostedServices(SubscriptionId, certificate, Version);
hostedservicesview.ActiveViewIndex = 0;
ListStorageAccounts(SubscriptionId, certificate, Version);
}
public async void ListHostedServices(string subscriptionId, X509Certificate2 certificate, string version)
{
string hittingUri = String.Format("https://management.core.windows.net/{0}/" + "services/hostedservices",SubscriptionId);
XmlDocument responsebody= await HelperMethods.GetXmlDocument(hittingUri, certificate, version);
if (responsebody != null)
{
var result = responsebody.GetElementsByTagName("HostedServiceProperties");
hostedservices = new DataTable();
hostedservices.Columns.Add("Url");
hostedservices.Columns.Add("ServiceName");
hostedservices.Columns.Add("Location");
hostedservices.Columns.Add("Label");
hostedservices.Columns.Add("Status");
hostedservices.Columns.Add("DateCreated");
hostedservices.Columns.Add("DateLastModified");
foreach (XmlNode hsnode in result)
{
DataRow hsrow = hostedservices.NewRow();
hsrow["Url"] = hsnode.ParentNode.ChildNodes.OfType<XmlElement>().Where(x => x.Name == "Url").Any() ?
hsnode.ParentNode.ChildNodes.OfType<XmlElement>().Where(x => x.Name == "Url").First().InnerText : string.Empty;
hsrow["ServiceName"] = hsnode.ParentNode.ChildNodes.OfType<XmlElement>().Where(x => x.Name == "ServiceName").Any() ?
hsnode.ParentNode.ChildNodes.OfType<XmlElement>().Where(x => x.Name == "ServiceName").First().InnerText : string.Empty;
hsrow["Location"] = hsnode.ChildNodes.OfType<XmlElement>().Where(x => x.Name == "Location").Any() ?
hsnode.ChildNodes.OfType<XmlElement>().Where(x => x.Name == "Location").First().InnerText : string.Empty;
// IF location is empty, it means affinity group is returned, Pull location from affinity group
if (String.IsNullOrEmpty(hsrow["Location"].ToString()))
{
string affnitygroup = hsnode.ChildNodes.OfType<XmlElement>().Where(x => x.Name == "AffinityGroup").Any() ?
hsnode.ChildNodes.OfType<XmlElement>().Where(x => x.Name == "AffinityGroup").First().InnerText : string.Empty;
certificate = HelperMethods.GetStoreCertifcate(Thumbprint);
hsrow["Location"] = await HelperMethods.GetAffinityGroupLocation(subscriptionId, certificate, Version, affnitygroup);
}
hsrow["Label"] = hsnode.ChildNodes.OfType<XmlElement>().Where(x => x.Name == "Label").Any() ?
hsnode.ChildNodes.OfType<XmlElement>().Where(x => x.Name == "Label").First().InnerText : string.Empty;
hsrow["Status"] = hsnode.ChildNodes.OfType<XmlElement>().Where(x => x.Name == "Status").Any() ?
hsnode.ChildNodes.OfType<XmlElement>().Where(x => x.Name == "Status").First().InnerText : string.Empty;
hsrow["DateCreated"] = hsnode.ChildNodes.OfType<XmlElement>().Where(x => x.Name == "DateCreated").Any() ?
hsnode.ChildNodes.OfType<XmlElement>().Where(x => x.Name == "DateCreated").First().InnerText : string.Empty;
hsrow["DateLastModified"] = hsnode.ChildNodes.OfType<XmlElement>().Where(x => x.Name == "DateLastModified").Any() ?
hsnode.ChildNodes.OfType<XmlElement>().Where(x => x.Name == "DateLastModified").First().InnerText : string.Empty;
hostedservices.Rows.Add(hsrow);
}
lbl_count.Text = hostedservices.Rows.Count.ToString();
HostedServicesList.DataSource = hostedservices;
HostedServicesList.DataBind();
}
else
{
}
}
**XmlDocument responsebody= await HelperMethods.GetXmlDocument(hittingUri, certificate, version);**
The method definition is as follows
public static async Task<XmlDocument> GetXmlDocument(string hittingUrl, X509Certificate2 certificate, string Version)
{
HttpWebRequest request;
XmlDocument responsebody = new XmlDocument();
// string hittingUri = "https://management.core.windows.net/{0}/" + "services/hostedservices";
Uri uri = new Uri(hittingUrl);
request = (HttpWebRequest)HttpWebRequest.Create(uri);
request.Method = "GET";
request.Headers.Add("x-ms-version", Version);
request.ClientCertificates.Add(certificate);
request.ContentType = "application/xml";
HttpWebResponse webresponse= null;
try
{
webresponse = (HttpWebResponse)await request.GetResponseAsync();
}
catch (Exception)
{
}
HttpStatusCode statuscode = webresponse.StatusCode;
if (webresponse.ContentLength > 0)
{
using (XmlReader reader =XmlReader.Create(webresponse.GetResponseStream()))
{
responsebody.Load(reader);
}
}
if (statuscode.Equals(HttpStatusCode.OK))
{
return responsebody;
}
else
{
return null;
}
}
Similarly above 2 methods also have same kind of listing.
Its taking me approximately 12-15 seconds to retrieve data of 11+19+6 records.
Could you guys help me in optimizing this code so that it will be much faster.
First you need to profile your code to see where exactly are you loosing your time. If the GetXMLDocument is taking up most of the time then it may be that the server is not as responsive
Outside of that my guess would be that your foreach loop is taking the most amount of time because you are essentially searching through all the elements in each statement in here.
Another way of doing this could be
Dictionary<string, string> nvpairsForColumns = new Dictionary { "Url", String.Empty }; // add all valid column headers here
foreach(var xelement in hsnode.ParentNode.ChildNodes.OfType<XmlElement>)
{
if(nvparisForColumns.ContainsKey(xelement.Name)
&& String.IsNullOrEmpty(nvpairsForColumns[xlement.Name])) // assumption String.Empty is not a valid entry else keep another Dictionary<string,bool> to tag when done with first
{
nvpairsForColumns[xelement.Name] = xelement.InnerText;
}
}

Resources