Add custom text to AX 2012 drill-down links - axapta

I want to customize the standard drill-down functionality and add a text parameter to the drill-down URL. I will then parse and use the parameter in the SysStartUpCmdDrillDown or EventDrillDownPoller class like the solution provided by Jan B. Kjeldsen in this question.
The standard drill-down link is dynamics://Target/?DrillDown_RecID/ :
dynamics://0/?DrillDown_5637230378/
In previous versions of AX it was possible to modify the RecId to custom text and parse the text once the client is started:
dynamics://0/?DrillDown_0MenuItemName=PurchTable&FieldName=PurchId&FieldValue=P000044
Unfortunately, in AX 2012 the RecId is checked before the client is started and if it is not a valid int64, the drill-down event is not sent to the client. Since it is not possible to change the RecId to anything other than an integer, #Alex Kwitny suggested in the comments at that same question that you can add the custom text to the drill-down target like this:
dynamics://0MenuItemName=PurchTable/?DrillDown_5637230378/
The problem I experience with this is that the link now gets confused about which instance to start.
If the target is equal to the value in the System Admin -> system parameters -> Alerts ->Drill-down target, a client with the correct server instance is started. When I append the text with my custom text, it always starts the default instance(Which could be different from the instance I intended to start). While this is not ideal, I could work around this issue.
The bigger problem is that it now always starts a new session of the default instance, even if a client session is already started. As far as I can see I cannot write X++ code to solve this issue since the server instance is determined before any code in the client is executed.
My question is this - How can I add custom text to the drill-down link while preserving the way the client instance is started: If a client for the instance is already open, it should process the link in the open client, and not start up a new client of the default instance.

You should probably come up with another solution as mentioned in this post, but there could still be a way.
The URL has two objects that can be modified:
dynamics://[Drill-down target(str)]/?Drilldown_[Int64]
According to you, if you modify the [Drill-down target], then it launches AX using the default client config, and that is behavior that you don't want. If you have a matching [Drill-down target], it'll launch in the open client window, which is behavior I can't confirm, but I'll take it at face value and assume you're correct.
So that means the only thing you can modify in the URL is [int64]. This is actually a string that is converted to an int64 via str2int64(...), which in turn corresponds to a RecId. This is where it gets interesting.
This work all happens in \Classes\SysStartUpCmdDrillDown\infoRun.
Well, lucky for you the ranges for the objects are:
RecId - 0 to 9223372036854775807
Int64 - -9223372036854775808 to 9223372036854775807
You can call minRecId() and maxRecId() to confirm this.
So this means you have -9223372036854775808 to -1 numbers to work with by calling URLs in this range:
dynamics://0/?DrillDown_-1
to
dynamics://0/?DrillDown_-9223372036854775808
Then you would modify \Classes\SysStartUpCmdDrillDown\infoRun to look for negative numbers, and fork to your custom code.
HOW you decide to user these negative #'s is up to you. You can have the first n-digits be a table id or a look-up value for a custom table. You can't technically use a RecId as part of that negative number because in theory the RecId could get up that high (minus 1).

Related

BizTalk 2013 R2 - Decision Shape not following correct logic path

Issue with an old Biz app (not designed or developed by myself).
Its orchestration receives a particular message, which is then fed into a Decision shape. If the below logic applies (as directly copy/pasted from the shapes first branch expression), it should go that route.
msg_inputCanonical.CRUD == "D" && msg_inputCanonical.DbTable == "Staff"
I can see it terminating however (by using the Orchestration Debugger) as it follows the Else branch and eventually hits a terminate shape.
I've checked the msg_inputCanonical to confirm the values being passed through (as below extracted from the Tracked Message part), and can see it matches the string condition in accordance with its mapping - CRUD = ChOp;
<DbTable>Staff</DbTable>
<ChOp>D</ChOp>
There's nothing else that I can see that's influencing this re-route, so can anyone think of any quirks that might be causing it?
Note: I've amended the WCF-SQL Stored Procedure that generates the msg_inputCanonical as prior to this it wasn't trimming any of the CRUD/DbTable values and had been leaving deadspace in.
There is also a map that uses ltrim/rtrim functoids on the ChOp property, but again - can't see what harm trimming an already trim'd field would do.
I have also tried replicating the logic in a dev environment, and it works as expected going down the correct branch when I'm passing the message through.

Can't Edit/Update Certain Items In Database (Table)

I have database that I have multiple orders entered into. Everything seems to be working fine except for a few old entries which will not accept updates/changes to their Fields.
Note: The majority of the Fields are Strings with Possible Values entered via a DropDown Box.
So if I open Order A I can make adjustments just fine and those changes persist even after closing the page and coming back or refreshing.
But if I open Order B, I can make changes via the dropdowns and it looks like they have adjusted, however if I leave the page or refresh all the changes have reverted back.
One piece of info that may be helpful is that each of these orders has at least one Field that contains an entry that is no longer a Possible Value (the original entries were removed/changed per request of the client).
Maybe they are "locked" because of this? Is there a way to look at an error log for a Published app?
I can delete the "corrupt" entries and recreate them (since there are currently only a few), but I would prefer to find a better solution in case this happens again in the future.
Any help would be greatly appreciated.
It's a bug. Such field level value updates should get through.
As workaround you can update prohibited(not possible anymore) values with allowed ones in OnSave Model's Event like:
switch (record.Field) {
case "old_value_1":
record.Field = "new_value_1";
break;
case "old_value_2":
record.Field = "new_value_2";
break;
...
}
Sorry for the inconvenience.
Each deployment has its own log. Have you tried "App Settings > DEPLOYMENTS > (click on the desployment) > VIEW LOGS"?

Why does the url property key in Firebase snapshot keep changing?

I have not seen any discussion or awareness so far that Firebase does in fact make available a unique identifier--in fact the full URL--to each specific data record via their "snapshot" which they return, i.e. the wrapper around the data record (accessed via snapshot.val()). By doing a basic property examination of the snapshot I discovered that the unique URL is available (see examples below). However, it seems that, for some reason, Firebase keeps changing the name of the key every few days, causing my application to break. I have to go in and re-discover the new URL property key and change it so that it will work again.
Here are three examples of how I have seen the key change so far. Each value is the same, but the key keeps changing over time (i.e.: "Wb", "Xb", "bc").:
getMemberBySnapshot - snapshot has prop Wb with value https://prototype1.firebaseio.com/users/-IwohKfw1l5F3gFqyJJ5
getMemberBySnapshot - snapshot has prop Xb with value https://prototype1.firebaseio.com/users/-IwohKfw1l5F3gFqyJJ5
getMemberBySnapshot - snapshot has prop bc with value https://prototype1.firebaseio.com/users/-IwohKfw1l5F3gFqyJJ5
I have read Firebase's suggestions that developers should use an email address if they want a unique key (what if my model does not use an email field? What if a user wants to change their email?), or Firebase suggests altenatively to retrieve all existing records and then search through them on the client. Neither of these solutions are satisfying. But I'm seeing that they do provide the unique URL to each data record in the 'snapshot'. Why do they not provide a stabilized key so that a developer can call it consistently???
Firebase.js is a compiled script. The names of internal variables will change every time we compile it and release a new version, so you should definitely not be relying on any properties that are not documented on our website.
For your specific case, you should be using:
snapshot.ref().toString()
in order to get the URL.

Applying more than one sort on a Tridion broker query

I have a broker query where I need to sort by 2 different fields (using JSP and 2011 SP1)
The API has the method "addSorting" which I am applying.
It appears, however, that the second addSorting call is overwriting the first addSorting call - rather than adding the second sort:
// Sort by Date
CustomMetaKeyColumn customMetaKeyColumnDate = new CustomMetaKeyColumn("date", MetadataType.DATE);
query.addSorting(new SortParameter(customMetaKeyColumnDate, SortParameter.DESCENDING));
// Sort by Owner
CustomMetaKeyColumn customMetaKeyColumnOwner = new CustomMetaKeyColumn("owner", MetadataType.STRING);
query.addSorting(new SortParameter(customMetaKeyColumnOwner, SortParameter.ASCENDING));
They sorts work fine individually.
Is this expected? Is addSorting really a setSorting - where only 1 sort can be specified or am I missing a way to combine 2 sorts?
The addSorting method works just fine. However, it simply does not work for CustomMeta columns!!! There is already a confirmed defect regarding this subject with the following summary: "SortParameter does not work with two metadata fields". This is still an open defect for 2011SP1 and is scheduled to be fixed only for the next release.
Cheers,
Daniel.

How to track custom parameter with Google Analytics and utm.gif

The situation
I'd like to use GA to track some serverside operations. That's why I cant make use of the GA JavaScript functions. But, as you might know, you can request the utm.gif right from your server. This already works fine.
The Problem
I'd like to trackt custom parameters. But I have no idea how to add them in the right format to the url-request
This one should do the custom parms. But I didn't get any results in GA.
utme=5(Init*load_success*http://www.mydomain.de)8(userstatus)9(fan)11(2)
Full list of params:
ref ts
utmac UA-XXXXXX-5
utmcc __utma=186215409.1789216404.1265552708.1280074861.1280493144.21;+__utmz=;
utmcs ISO-8859-1
utmdt Button
utme 5(Init*load_success*http://www.mydomain.de)8(mycustomvar)9(mycustomvalue)11(2)
utmfl -
utmhn mydomain.de
utmje -
utmn 1114675642
utmp button
utmr http://www.mydomain.de
utmsc -
utmsr -
utmul de-de
utmwv 4.5.7
not sure what's going wrong, given what you posted, but how about you write out what you want to send the traditional way (with javascript) and put it on a test page. Use firebug or whatever to grab the requested url that's built and compare it to what you have now.
The value of the utme gif Request parameter is encoded by ga.js--it's the only one that is, as far as i know.
Calling __trackEvent is the usual way to set the value of utme. These are client-side events though, which is no doubt why you are trying to set utme directly.
So if you just want to bind 5(Initload_successhttp://www.mydomain.de)8(userstatus)9(fan)11(2) to the variable utme, and you can't rely on user-behavior to trigger that binding, then here's what i suggest:
Pack your data into a 'custom variable' scoped to the page--this way, when the __trackPageview() is called, the value will be set.
Here's the analytics code required in your HTML to implement that:
The method signature for a custom variable:
pageTracker._setCustomVar(slot, // integer between 1 and 5, inclusive (just use '1')
name, // user-defined name for the custom variable
value, // string representing the value for the custom variable
scope, // you want '3' for page-level (an int, not a string though)
);
Within the HTML (order matter, of course):
pageTracker.__setCustomvar(1, "A Name", "A Value", 3);
pageTracker.__trackPageview();
A key point here is that the parameter 'value' can be set dynamically, so for the 'value' parameter, i guess you want to pass in 5(Initload_successhttp://www.mydomain.de)8(userstatus)9(fan)11(2)
Finally, here are the two key sources (Implementation Guide, Usage Guide) on Custom Variables from the GA Team

Resources