I have two different variable which are defined in Server-side, Visual studio says me "The name 'PopupShowDelay' does not exist in the current context" and "The name 'QuotedTimeOutUrl' does not exist in the current context"
Javascript:
var schedulePopup = function() {
stopTimers();
var myVar = '<%= PopupShowDelay %>';
_popupTimer = window.setTimeout(showPopup, myVar);
};
Server-Side:
public int PopupShowDelay
{
get { return 60000 * (Session.Timeout - 2); }
}
public string QuotedTimeOutUrl
{
get { return '"' + GetEntry().BasarSettings.Where(a => a.Ad == "WebApplication").Select(a => a.Deger).FirstOrDefault() + '"'; }
}
Ps: Code is working well, problem is just VS gives me an error.
Microsoft has been release 15.4.2 version of visual studio for solve thi issue.
Related
I am trying to pass 2 parameters in Handler call in codebehind but I can't get it to work. Here is my code:
X.Msg.Confirm("Confirm", "The field has " + dependency.Count() + " dependent fields. Are you sure you want to proceed? (The dependent fields will be deleted also)", new MessageBoxButtonsConfig
{
Yes = new MessageBoxButtonConfig
{
Handler = "App.direct.UC.DoYesDeleteDepField('" + fieldname + "," + dependency + "')", //ERROR LINE
Text = "Yes"
},
No = new MessageBoxButtonConfig
{
Handler = "",
Text = "No"
}
}).Show();
Error:
System.ArgumentException: DirectMethod: 'DoYesDeleteDepField', The parameter 'dep' is undefined at Ext.Net.DirectMethod.Invoke(Object target, HttpContext context, ParameterCollection args) at Ext.Net.DirectMethod.Invoke(Object target, ParameterCollection args) at Ext.Net.ResourceManager.RaisePostBackEvent(String eventArgument)
[DirectMethod]
public void DoYesDeleteDepField<T>(string fieldname, List<MyDependenciesClass> dep)
{....
You are passing:
App.direct.UC.DoYesDeleteDepField('fieldname,dependency')
the way you written it.
To pass this:
App.direct.UC.DoYesDeleteDepField('fieldname', 'dependency')
you should draw the line like this:
"App.direct.UC.DoYesDeleteDepField('" + fieldname + "', '" + dependency + "')"
For further information on this answer: the initial parameters were being read as a string, thus the javascript threw 'undefined'.
The solution works due to String Concatenation, which is a very important concept on OOP.
For more on string concatenation consult: How to Concatenate Multiple Strings (C# Programming Guide)
I'm working on a feature where user defined, anonymous, javascript functions retrieved from a database need to be executed server side in the context of ASP.Net application.
I'm evaluating Jint for this purpose (Latest version from NuGet). I have been able to run functions that do basic operations and return values without an issue as below.
public void Do()
{
var jint = new Engine();
var add = jint.Execute(#"var f = " + GetJsFunction()).GetValue("f");
var value = add.Invoke(5, 4);
Console.Write("Result: " + value);
}
private string GetJsFunction()
{
return "function (x,y) {" +
" return x+y;" +
"}";
}
My question is whether Jint facilitates the execution of javascript functions which uses third party libraries like lodash? If so, how would I go about making the Jint engine aware of it (i.e third party library)?
An example would be the execution of following function.
private string GetFunction()
{
return "function (valueJson) { " +
" var value = JSON.parse(valueJson);" +
" var poi = _.find(value,{'Name' : 'Mike'});" +
" return poi; " +
"}";
}
Thanks a lot in advance.
I think I have figured this out. It's no different to executing a custom function. You just read the third party library from a file (project resource) and invoke execute on Jint engine. See below;
private void ImportLibrary(Engine jint, string file)
{
const string prefix = "JintApp.Lib."; //Project location where libraries like lodash are located
var assembly = Assembly.GetExecutingAssembly();
var scriptPath = prefix + file; //file is the name of the library file
using (var stream = assembly.GetManifestResourceStream(scriptPath))
{
if (stream != null)
{
using (var sr = new StreamReader(stream))
{
var source = sr.ReadToEnd();
jint.Execute(source);
}
}
}
}
We can call this function for all the third party libraries that needs to be added.
This question isn't new here, but still I cannot get it where I go wrong. I just want to evaluate some javascript.
My simple code looks like:
WebView wv = new WebView(context);
WebSettings settings = wv.getSettings();
settings.setJavaScriptEnabled(true);
JavaBridgeToJS bridgeToJS = new JavaBridgeToJS();
wv.addJavascriptInterface(bridgeToJS, "javaCallback");
String src = "javascript: var result= 3 + 3; window.javaCallback.resultOfAdd(result)";
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
Log.d(TAG, "Newer than JellyBean.");
ValueCallback<String> result = new ValueCallback<String>() {
#Override
public void onReceiveValue(String value) {
Log.d(TAG, "Got in onReceiveValue: " + value);
}
};
wv.evaluateJavascript(src, result);
}else {
Log.d(TAG, "Older than Kitkat");
wv.loadUrl(src);
}
and
public class JavaBridgeToJS {
#JavascriptInterface
public void resultOfAdd(String result) {
Log.d(TAG, "Here is: " + result);
}
}
It is working good for API 19+, even without if with checking of version (I mean that it works with loadUrl as well as with evaluateJavascript)
But when I try API 18, the callback in java is not called.
I have looked around (remove line break, or quotes missing (possibly infected, watched on phone), and so on...)
So far I have no luck. Any idea?
EDIT
Well, I have added code for handling errors inside of JS in case, that I have missed something.
wv.setWebChromeClient(new CustomWebChromeClient());
as
public class CustomWebChromeClient extends WebChromeClient {
private CustomWebChromeClient() {
super();
}
#Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
UILog.d(TAG, consoleMessage.message());
return super.onConsoleMessage(consoleMessage);
}
}
and I was suprised with:
E/dalvikvm: Could not find class 'android.webkit.PermissionRequest', referenced from method com.example.WebViewDoll$CustomWebChromeClient.access$super
VFY: unable to resolve check-cast 1896 (Landroid/webkit/PermissionRequest;) in Lcom/example/WebViewDoll$CustomWebChromeClient;
E/dalvikvm: Could not find class 'android.webkit.WebChromeClient$FileChooserParams', referenced from method com.example.WebViewDoll$CustomWebChromeClient.access$super
VFY: unable to resolve check-cast 1899 (Landroid/webkit/WebChromeClient$FileChooserParams;) in Lcom/example/WebViewDoll$CustomWebChromeClient;
E/dalvikvm: Could not find class 'android.webkit.PermissionRequest', referenced from method com.example.WebViewDoll$CustomWebChromeClient.access$super
D/WebViewDoll: Uncaught TypeError: Cannot call method 'resultOfAdd' of undefined
E/Web Console: Uncaught TypeError: Cannot call method 'resultOfAdd' of undefined at null:1
I did not find an answer why this is not working, but with help of this using js in webview I was able to make a workaround ...
I have to inject my js into a html page. So my wrapper arround js looks like:
String src = "<html><head><script type=\"text/javascript\">" +
"function myFunction()" +
"{" +
" javaCallback.resultOfAdd(3+3);" +
"}" +
"</script></head><body onload=\"myFunction()\"/>" +
"</html>";
and instead of wv.loadUrl I have used:
wv.loadData(src, "text/html", "UTF-8");
This combination have same result as needed.
the github API sends the pagination data for the json results in the http link header:
Link: <https://api.github.com/repos?page=3&per_page=100>; rel="next",
<https://api.github.com/repos?page=50&per_page=100>; rel="last"
since the github API is not the only API using this method (i think) i wanted to ask if someone has a useful little snippet to parse the link header (and convert it to an array for example) so that i can use it for my js app.
i googled around but found nothing useful regarding how to parse pagination from json APIs
The parse-link-header NPM module exists for this purpose; its source can be found on github under a MIT license (free for commercial use).
Installation is as simple as:
npm install parse-link-header
Usage looks like the following:
var parse = require('parse-link-header');
var parsed = parse('<https://api.github.com/repos?page=3&per_page=100>; rel="next", <https://api.github.com/repos?page=50&per_page=100>; rel="last"')
...after which one has parsed.next, parsed.last, etc:
{ next:
{ page: '3',
per_page: '100',
rel: 'next',
url: 'https://api.github.com/repos?page=3&per_page=100' },
last:
{ page: '50',
per_page: '100',
rel: 'last',
url: ' https://api.github.com/repos?page=50&per_page=100' } }
There is a PageLinks class in the GitHub Java API that shows how to parse the Link header.
I found this Gist that:
Parse Github Links header in JavaScript
Tested it out on the Github API and it returns an object like:
var results = {
last: "https://api.github.com/repositories/123456/issues?access_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&state=open&since=2013-07-24T02%3A12%3A30.309Z&direction=asc&page=4"
next: "https://api.github.com/repositories/123456/issues?access_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&state=open&since=2013-07-24T02%3A12%3A30.309Z&direction=asc&page=2"
};
I found wombleton/link-headers on github. It appears to be made for the browser, as opposed to being an npm module, but it seems like it wouldn't be hard to modify it to work in a server-side environment. It uses pegjs to generate a real RFC 5988 parser rather than string splits, so it should work well for any link header, rather than just Github's.
I completely understand this is "technically" a JavaScript thread. But, if you're like me and arrived here by Google'ing "how to parse Link header" I thought I'd share my solution for my envinronment (C#).
public class LinkHeader
{
public string FirstLink { get; set; }
public string PrevLink { get; set; }
public string NextLink { get; set; }
public string LastLink { get; set;}
public static LinkHeader FromHeader(string linkHeader)
{
LinkHeader linkHeader = null;
if (!string.IsNullOrWhiteSpace(linkHeader))
{
string[] linkStrings = linkHeader.Split("\",");
if (linkStrings != null && linkStrings.Any())
{
linkHeader = new LinkHeader();
foreach (string linkString in linkStrings)
{
var relMatch = Regex.Match(linkString, "(?<=rel=\").+?(?=\")", RegexOptions.IgnoreCase);
var linkMatch = Regex.Match(linkString, "(?<=<).+?(?=>)", RegexOptions.IgnoreCase);
if (relMatch.Success && linkMatch.Success)
{
string rel = relMatch.Value.ToUpper();
string link = linkMatch.Value;
switch (rel)
{
case "FIRST":
linkHeader.FirstLink = link;
break;
case "PREV":
linkHeader.PrevLink = link;
break;
case "NEXT":
linkHeader.NextLink = link;
break;
case "LAST":
linkHeader.LastLink = link;
break;
}
}
}
}
}
return linkHeader;
}
}
Testing in a console app, using GitHub's example Link header:
void Main()
{
string link = "<https://api.github.com/user/repos?page=3&per_page=100>; rel=\"next\",< https://api.github.com/user/repos?page=50&per_page=100>; rel=\"last\"";
LinkHeader linkHeader = LinkHeader.FromHeader(link);
}
Here is a simple javascript function that extracts the useful info from the link in a nice object notation.
var linkParser = (linkHeader) => {
let re = /<([^\?]+\?[a-z]+=([\d]+))>;[\s]*rel="([a-z]+)"/g;
let arrRes = [];
let obj = {};
while ((arrRes = re.exec(linkHeader)) !== null) {
obj[arrRes[3]] = {
url: arrRes[1],
page: arrRes[2]
};
}
return obj;
}
It will output the result like this ==>
{
"next": {
"url": "https://api.github.com/user/9919/repos?page=2",
"page": "2"
},
"last": {
"url": "https://api.github.com/user/9919/repos?page=10",
"page": "10"
}
}
If you can use Python and don't want to implement full specification, but need to have something what work for Github API, then here we go:
import re
header_link = '<https://api.github.com/repos?page=3&per_page=100>; rel="next", <https://api.github.com/repos?page=50&per_page=100>; rel="last"'
if re.search(r'; rel="next"', header_link):
print re.sub(r'.*<(.*)>; rel="next".*', r'\1', header_link)
Here's a simple bash script with curl and sed to get all pages from a long query
url="https://api.github.com/repos/$GIT_USER/$GIT_REPO/issues"
while [ "$url" ]; do
echo "$url" >&2
curl -Ss -n "$url"
url="$(curl -Ss -I -n "$url" | sed -n -E 's/Link:.*<(.*?)>; rel="next".*/\1/p')"
done > issues.json
For someone who ended up here searching for Link Header Parser in Java, you can use javax.ws.rs.core.Link. Refer below for example:
import javax.ws.rs.core.Link
String linkHeaderValue = "<https://api.github.com/repos?page=3&per_page=100>; rel='next'";
Link link = Link.valueOf(linkHeaderValue);
Instead of using the original parse-link-header package, another option would be #web3-storage/parse-link-header. It's the forked version of the original NPM package. The API is the same but it comes with advantages like:
TypeScript support
Zero dependencies
No Node.js globals and ESM
Installation:
npm install #web3-storage/parse-link-header
Usage:
import { parseLinkHeader } from '#web3-storage/parse-link-header'
const linkHeader =
'<https://api.github.com/user/9287/repos?page=3&per_page=100>; rel="next", ' +
'<https://api.github.com/user/9287/repos?page=1&per_page=100>; rel="prev"; pet="cat", ' +
'<https://api.github.com/user/9287/repos?page=5&per_page=100>; rel="last"'
const parsed = parseLinkHeader(linkHeader)
console.log(parsed)
Output:
{
"next":{
"page":"3",
"per_page":"100",
"rel":"next",
"url":"https://api.github.com/user/9287/repos?page=3&per_page=100"
},
"prev":{
"page":"1",
"per_page":"100",
"rel":"prev",
"pet":"cat",
"url":"https://api.github.com/user/9287/repos?page=1&per_page=100"
},
"last":{
"page":"5",
"per_page":"100",
"rel":"last",
"url":"https://api.github.com/user/9287/repos?page=5&per_page=100"
}
}
Here is a Python solution to get contributors count for any github repo.
import requests
from urllib.parse import parse_qs
rsp = requests.head('https://api.github.com/repos/fabric8-analytics/fabric8-analytics-server/contributors?per_page=1')
contributors_count = parse_qs(rsp.links['last']['url'])['page'][0]
Here is a simple code to parse link header from GitHub in Java Script
var parse = require('parse-link-header');
var parsed = parse(res.headers.link);
no_of_pages = parsed.last.page;
This is a Java function which will serve the purpose, you can find a link for the provided parameter key and parameter value.
Please Note: This is something that I made for personal purpose, it might not be fool proof for your scenario, so review it and make changes accordingly
https://github.com/akshaysom/LinkExtract/blob/main/LinkExtract.java
public static String getLinkFromLinkHeaderByParamAndValue(String header, String param, String value) {
if (header != null && param != null && value != null && !"".equals(header.trim()) && !"".equals(param.trim())
&& !"".equals(value)) {
String[] links = header.split(",");
LINKS_LOOP: for (String link : links) {
String[] segments = link.split(";");
if (segments != null) {
String segmentLink = "";
SEGMENT_LOOP: for (String segment : segments) {
segment = segment.trim();
if (segment.startsWith("<") && segment.endsWith(">")) {
segmentLink = segment.substring(1, segment.length() - 1);
continue SEGMENT_LOOP;
} else {
if (segment.split("=").length > 1) {
String currentSegmentParam = segment.split("=")[0].trim();
String currentSegmentValue = segment.split("=")[1].trim();
if (param.equals(currentSegmentParam) && value.equals(currentSegmentValue)) {
return segmentLink;
}
}
}
}
}
}
}
return null;
}
I've written this common function to basically clone the attributes on a form, and pass them into itself...
/*
Opens a new window, copying the current page, and loading the new item with the current values
* Sample call *
var url = "main.aspx?etn=task&pagetype=entityrecord";
var features = 'location=no,status=yes,scrollbars=no,menubar=no,toolbar=no,width=900,height=600';
CommonLib.openClone(url, '_blank', features, Xrm.Page.getAttribute(null));
*/
openClone: function (url, windowName, features, attributes) {
var qsParams = "";
var qs;
for (var i = 0; i < attributes.length; i++) {
qs = CommonLib.getExtraQS(attributes[i]);
if (qs.length > 0) {
qsParams += qs + "&";
}
} //end for
// Remove extra &
qsParams = qsParams.substring(0, qsParams.length - 1);
window.open("/" + Xrm.Page.context.getOrgUniqueName() + "/" + url + "&extraqs=" + encodeURIComponent(qsParams), windowName, features, false);
},
/*
returns the extraqs value for the attribute, non-encodURIComponent-ed
*/
getExtraQS: function (attribute) {
var extraQS = "";
if (attribute != null && attribute.getValue() != null) {
// Set name value based on type and id
switch (attribute.getAttributeType()) {
case "lookup":
var value = attribute.getValue();
var name = attribute.getName();
if (value != null && value.length > 0) {
value = value[0];
extraQS = name + "=" + value.id + "&" + name + "name=" + value.name;
switch(value.typename){
case 'account':
case 'contact':
case 'systemuser':
case 'team':
extraQS += "&" + name + "type=" + value.typename;
break;
}
}
break;
case "datetime":
extraQS = attribute.getName() + "=" + CommonLib.getCRMDateFormat(attribute.getValue());
break;
default:
extraQS = attribute.getName() + "=" + attribute.getValue();
break;
}
}
return extraQS;
}
Everything works fine unless I try to pass an attribute of type account. I get the standard "Error. An error has occurred." If I skip the second switch statement, then I don't get a CRM Sever error, but a CRM javascript error attempting to deserialize the object because it doesn't have a type set, which results in a null pointer error.
Any ideas how to get this to work?
Edit: Turning on CRM server trace logging results in this exception which lists the regardingobjectidtype as an invalid parameter, even though it's exactly what the SDK says to use (http://msdn.microsoft.com/en-us/library/gg334375.aspx), and if I pass everything but that parameter, I get a javascript exception in the CRM javascript because the typename is null.
[2011-11-04 08:27:53.961] Process: w3wp |Organization:306a6cd8-f599-df11-b324-005056bb527b |Thread: 14 |Category: Application |User: 00000000-0000-0000-0000-000000000000 |Level: Error | ErrorInformation.LogError
at ErrorInformation.LogError()
at ErrorInformation..ctor(Exception exception, Uri requestUrl, Boolean logError)
at MainApplication.Application_Error(Object sender, EventArgs eventArguments)
at EventHandler.Invoke(Object sender, EventArgs e)
at HttpApplication.RaiseOnError()
at ApplicationStepManager.ResumeSteps(Exception error)
at HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)
at HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr)
at ISAPIRuntime.ProcessRequest(IntPtr ecb, Int32 iWRType)
>MSCRM Error Report:
--------------------------------------------------------------------------------------------------------
Error: Exception of type 'System.Web.HttpUnhandledException' was thrown.
Error Message: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Error Details: Exception of type 'System.Web.HttpUnhandledException' was thrown.
Source File: Not available
Line Number: Not available
Request URL: http://dev-crmapp03.abc.com/TestOrg/userdefined/edit.aspx?actualdurationminutes=1&etc=4212&abc_category=9&abc_contactmade=false&abc_pointofcontactid=%7b7E599729-1923-E011-858E-005056BB527B%7d&abc_pointofcontactidname=Human%20Resources&abc_result=11&ownerid=%7bCAA79C99-0E9C-DF11-9D85-005056BB728E%7d&owneridname=Rachel%20Richardson&owneridtype=systemuser&pagemode=iframe®ardingobjectid=%7b58949706-1923-E011-858E-005056BB527B%7d®ardingobjectidname=Cold%20Emails%20-%20016®ardingobjectidtype=account&sitemappath=Workplace%7cMyWork%7cnav_dashboards&subject=%2a%20Security%20Alarm%20Installer%20%2f%20Technician%20%2a%20%28St.Louis%29
Stack Trace Info: [InvalidOperationException: CRM Parameter Filter - Invalid parameter 'regardingobjectidtype=account' in Request.QueryString on page /TestOrg/userdefined/edit.aspx
The raw request was 'GET /TestOrg/userdefined/edit.aspx?actualdurationminutes=1&etc=4212&abc_category=9&abc_contactmade=false&abc_pointofcontactid=%7b7E599729-1923-E011-858E-005056BB527B%7d&abc_pointofcontactidname=Human%20Resources&abc_result=11&ownerid=%7bCAA79C99-0E9C-DF11-9D85-005056BB728E%7d&owneridname=Rachel%20Richardson&owneridtype=systemuser&pagemode=iframe®ardingobjectid=%7b58949706-1923-E011-858E-005056BB527B%7d®ardingobjectidname=Cold%20Emails%20-%20016®ardingobjectidtype=account&sitemappath=Workplace%7cMyWork%7cnav_dashboards&subject=%2a%20Security%20Alarm%20Installer%20%2f%20Technician%20%2a%20%28St.Louis%29' called from http://dev-crmapp03.abc.com/TestOrg/main.aspx?etn=task&pagetype=entityrecord&extraqs=subject%3D*%20Security%20Alarm%20Installer%20%2F%20Technician%20*%20(St.Louis)%26abc_category%3D9%26regardingobjectid%3D%7B58949706-1923-E011-858E-005056BB527B%7D%26regardingobjectidname%3DCold%20Emails%20-%20016%26regardingobjectidtype%3Daccount%26abc_pointofcontactid%3D%7B7E599729-1923-E011-858E-005056BB527B%7D%26abc_pointofcontactidname%3DHuman%20Resources%26ownerid%3D%7BCAA79C99-0E9C-DF11-9D85-005056BB728E%7D%26owneridname%3DRachel%20Richardson%26owneridtype%3Dsystemuser%26abc_contactmade%3Dfalse%26abc_result%3D11%26actualdurationminutes%3D1.]
at Microsoft.Crm.Application.ParameterFilter.ValidateParameter(HttpRequest request, ArrayList parameterCollection, String key, String value, ParameterSources source, EntityType pageEntityType, FormAdditionalAllowedParameters additionalAllowedParameters)
at Microsoft.Crm.Application.ParameterFilter.ValidateParameters(Page page, EntityType pageEntityType, Boolean alwaysEnableParameterChecking, FormAdditionalAllowedParameters formAdditionalAllowedParametersTemp)
at Microsoft.Crm.Application.ParameterFilter.ValidateParameters(Page page, EntityType pageEntityType, FormAdditionalAllowedParameters formAdditionalAllowedParametersTemp)
at Microsoft.Crm.Application.Controls.AppPage.ValidatePageParameters()
at Microsoft.Crm.Application.Controls.PageManager.OnPreRender(EventArgs e)
at System.Web.UI.Control.PreRenderRecursiveInternal()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
Ok, so I must be retarted or something... Looks like my lookup was a regarding lookup, not a customer lookup and according to the SDK link I've referenced in the question, CRM doesn't support setting this value through the extraqs.
See here for a more detailed answer: CRM 2011: Populating email entity form fields with URL parameter