Error when passing parameters to report URL in business central - report

I have a custom report involving 3 dataitems in 1 dataset, the main dataitem is the "Customer" table and the only filter on the report is "No." as you can see below
report 50105 CustomerHistory
{
Caption = 'Customer Sales History';
UsageCategory = Administration;
ApplicationArea = All;
RDLCLayout = 'CustomerHistoryRpt.rdlc';
WordLayout = 'CustomerHistoryRpt.docx';
dataset
{
dataitem(Customer; Customer)
{
RequestFilterFields = "No.";
column(CustomerNumber; "No.") { }
column(Name; Name) { }
column(Balance; "Balance (LCY)") { }
column(E_Mail; "E-Mail") { }
column(Phone_No_; "Phone No.") { }
}
The report runs fine when I use the URL with report id:
https://businesscentral.dynamics.com/<tenant id>/?report=50105
but I cannot pass a customer No. in the URL I am always getting "the filter string contains invalid parameters"
I followed the below link for examples:
https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/developer/devenv-web-client-urls
I tried the below combinations and none of them works:
https://businesscentral.dynamics.com/<tenant id>/?report=50105&filter=%27No.%27%20IS%20%271452%27
https://businesscentral.dynamics.com/<tenant id>/?report=50105&filter=%27Customer.No.%27%20IS%20%271452%27
https://businesscentral.dynamics.com/<tenant id>/?report=50105&filter=%27CustomerNumber%27%20IS%20%271452%27
https://businesscentral.dynamics.com/<tenant id>/?report=50105&filter=%27Customer.CustomerNumber%27%20IS%20%271452%27
https://businesscentral.dynamics.com/<tenant id>/?report=50105&filter=%27No.%27%20:%20%271452%27

I found out that this is still not supported in BC similar to NAV:
https://learn.microsoft.com/en-us/dynamics-nav/feature-limitations-of-the-microsoft-dynamics-nav-web-client#Report
the workaround I did is to create a custom page with list parts and access the page through URL.

Related

D365FO: Update non-editable table field with data entity

I have a following problem: I have a tableA (standard FO table) that has a fieldA (string) with the Allow Edit property set to to No. Now the user would like to have several fieldA values changed with an added suffix, for example: FOO -> FOO_bar.
Can I do some sort of an CSV import that has old and new values or what would be the best way for start solving this?
You can by code update the field irrespective of the fields AllowEdit property. This only affects its use in forms.
You can import a file as described here.
public void UploadFileData()
{
var fileUpload = File::GetFileFromUser() as FileUploadTemporaryStorageResult;
var file = AsciiStreamIo::constructForRead(fileUpload.openResult());
if (!file || file.status())
{
throw error("#SYS52680");
}
file.inFieldDelimiter(',');
file.inRecordDelimiter('\r\n');
for (var record = file.read(); !file.status(); record = file.read())
{
record = file.read();
if (record)
{
info(strFmt("%1 - %2",conPeek(record,1),conPeek(record,2)));
}
}
}

Unable to recieve value of getquery parameter in Firebase Dynamic Links

I have to add an extra parameter as "meetingToken" in firebase deeplink .
But On adding an extra parameter "meetingtoken" as queryparameter im not recieving the value and getting error in joinmeeting(it) : No value passed for parameter meetingToken.
While the same works fine on passing a single parameter, What changes do i need to recieve both the parameters value.
Currently its giving me error at:
deepLink?.getQueryParameter("meetingCode")?.let { joinMeeting(it) }
No value passed for parameter 'meetingToken'
Link = https://example.in/?meetingCode=myuser?meetingToken=rtgdhh.tywufgsioqpp
private fun handleDynamicLink() {
Firebase.dynamicLinks
.getDynamicLink(intent)
.addOnSuccessListener { pendingDynamicLinkData ->
val deepLink: Uri?
if (pendingDynamicLinkData != null) {
deepLink = pendingDynamicLinkData.link
on android debugging its generating the following firebase Link = https://example.in/?meetingCode=userroom?meetingToken%3DeyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1Ni
deepLink?.getQueryParameter("meetingToken")
deepLink?.getQueryParameter("meetingCode")?.let { joinMeeting(it) }
}
}
.addOnFailureListener { _ ->
toast(getString(R.string.main_error_fetch_dynamic_link))
}
}
private fun joinMeeting (meetingCode:String, meetingToken:String) {
MeetingUtils.startMeeting(
this, meetingCode,
meetingToken)
}
meeting Utils.kt file to start meeting
object MeetingUtils {
fun startMeeting(context: Context, meetingCode: String, meetingToken: String)
app deep link url string
<string name="app_deep_link_url">https://example.in/?meetingCode=%1$s?meetingToken=%2$s</string>
this is the share code
private fun onShareMeetingCodeClick() {
tilCodeCreateMeeting.setEndIconOnClickListener {
binding.tilCodeCreateMeeting.error = null
toast(getString(R.string.main_creating_dynamic_link))
Firebase.dynamicLinks.shortLinkAsync {
link = Uri.parse(getString(R.string.app_deep_link_url, getCreateMeetingCode(), getCreateMeetingToken() ))
domainUriPrefix = getString(R.string.app_dynamic_link_url_prefix)
androidParameters {}
navigationInfoParameters {
forcedRedirectEnabled = true // Directly open the link in the app
}
}.addOnSuccessListener { result ->
val shortDynamicLink = result.shortLink.toString()
startShareTextIntent(
getString(R.string.main_share_meeting_code_title),
getString(R.string.main_share_meeting_code_desc, shortDynamicLink)
)
}.addOnFailureListener {
toast(getString(R.string.main_error_create_dynamic_link))
}
Can Someone guide me how to recieve value of getQueryparameter for more than 1 parameter. Thanks in Advance
You should use & instead of ? on appending the second parameter on your deep link. Also, the deep link configured should be URL-encoded since multiple parameters are configured in the deep link. Your sample deep link should look like this.
link=https%3A%2F%2Fexample.in%2F%3FmeetingCode%3Dmyuser%26meetingToken%3Drtgdhh.tywufgsioqpp
By URL-encoding the deep link, FDL will able to distinguish which parameters belongs to the deep link.
Uri.parse(getString(R.string.app_deep_link_url, getCreateMeetingCode(), getCreateMeetingToken()))
I'm not sure on what you're trying to achieve passing multiple parameters on getString for the deep link value.
Won't it make sense to create a StringBuilder or append it manually?
val deepLink = getString(R.string.app_deep_link_url)+ "%2F%3FmeetingCode%3D$meetingCode%26meetingToken%3D$meetingToken";
link = Uri.parse(deepLink);
where "app_deep_link_url" in strings.xml is
<string name="app_deep_link_url">https%3A%2F%2Fexample.in</string>

testNG: customize test name within created report

Is it possible ( of course it is) and how to customize the test name displayed in the report?
For example, I have a login test that run 4 times ( 4 different browsers) but reported test name is always login.
I'd like to attach the browser at the end , to see something like login_FF,login_IE,.....
Any idea?
I use testNG!
TestNG does provide options to customize the reporting, refer their site directly. But it does involve pretty good amount of effort........
If you test extends ITest you can set it there. Here is an example I'm currently using:
private final ThreadLocal<String> testName = new ThreadLocal<>();
...
#BeforeMethod(alwaysRun = true)
public void prepare(Method method, Object[] testData) {
if (testData == null || testData.length == 0) {
testName.set(String.format("%s.%s", getClass().getSimpleName(), method.getName()));
} else {
testName.set(
String.format(
"%s.%s %s", getClass().getSimpleName(), method.getName(), Arrays.toString(testData)));
}
}

Tridion 2009 SP1: Broker how to get Binary Url?

I am trying to retrieve the Binary Url of a multimedia component's file that is published as a dynamic Component Presentation.
I can see the Url in the Binaries table within the Broker database but I can't seem to get the binary url using either of the following bits of code:
using SQLBinaryMetaHome:
using (var sqlBinMetaHome = new Com.Tridion.Broker.Binaries.Meta.SQLBinaryMetaHome())
{
int componentItemId = int.Parse(queryStringId.Split('-')[1]);
var binaryMeta = sqlBinMetaHome.FindByPrimaryKey(new TCDURI(publicationId, 16, componentItemId));
if (binaryMeta != null)
{
VideoBinaryUrl = binaryMeta.GetURLPath();
}
else
{
Logger.Log.ErrorFormat("Failed ot load via SQL Binary Meta {0}", queryStringId);
}
}
Using Binary Meta factory:
using (var b = new BinaryMetaFactory())
{
var binaryMeta = b.GetMeta(queryStringId);
if (binaryMeta != null)
{
VideoBinaryUrl = binaryMeta.UrlPath;
}
else
{
Logger.Log.ErrorFormat("Failed to load binary meta {0}", queryStringId);
}
}
I can load the Component Meta data using the ComponentMetaFactory.
Any ideas on why I can't load the Binary Meta? Am I on the right track?
Rob
It looks like your first example is importing (auto-generated) methods from an internal DLL (Tridion.ContentDelivery.Interop.dll). Please don't use those and stick to the ones in the Tridion.ContentDelivery namespace (Tridion.ContentDelivery.dll).
You can find the official documentation for the Content Delivery .NET API in CHM format on SDL Tridion World (click the link, log in to the site and click the link again). From that documentation comes this example:
//create a new BinaryMetaFactory instance:
BinaryMetaFactory binaryMetaFactory = new BinaryMetaFactory();
//find the metadata for the specified binary
BinaryMeta binaryMeta = binaryMetaFactory.GetBinaryMeta("tcm:1-123");
//print the path to the output stream:
if(binaryMeta!=null) {
Response.Write("Path of the binary: " + binaryMeta.UrlPath);
}
//Dispose the BinaryMetaFactory
binaryMetaFactory.Dispose();
The factory class is Tridion.ContentDelivery.Meta.BinaryMetaFactory from Tridion.ContentDelivery.dll. I indeed also can't find a GetBinaryMeta method in that class, so it seems there is a mistake in the code sample. The most likely method that you should use is GetMeta.
Is there a reason you are not using a Binary Link to get a Link object to the specific Variant of the binary you want? Keep in mind that any DCP may render multiple variations of your multimedia component. From the Link object you can then get the URL to the binary.
Look for BinaryLink in the documentation for more details.
Try this:-
BinaryMeta binaryMeta = b.GetBinaryMeta(queryStringId);
if(binaryMeta != null) {
VideoBinaryUrl = binaryMeta.URLPath;
}
I did a SQL Profiler on the code and noticed that it was because I deployed my test app it wasn't calling the broker. Running the code within the actual Tridion Published site did hit the database but it was passing the value "[#def#]" for the variantId column.
I have now got it working with the following code:
IComponentMeta cm = cmf.GetMeta(queryStringId);
if (cm != null)
{
TcmId = queryStringId;
Title = cm.TryGetValue("title");
Summary = cm.TryGetValue("summary");
Product = cm.TryGetValue("product");
if (cm.SchemaId == StreamingContentSchemaId)
{
VideoId = cm.TryGetValue("video_url");
IsVimeo = true;
}
else if (cm.SchemaId == WebcastSchemaId)
{
using (var b = new BinaryMetaFactory())
{
var binaryMeta = b.GetMeta(queryStringId, "tcm:0-" + cm.OwningPublicationId + "-1");
if (binaryMeta != null)
{
VideoBinaryUrl = binaryMeta.UrlPath;
}
else
{
Logger.Log.ErrorFormat("Failed to load binary meta {0}", queryStringId);
}
}
}

Multiple TrackingParticipants not working, have funny side effects?

We are rying to use WF with multiple tracking participants which essentially listen to different queries - one for activity states, one for custom tracknig records which are a subclass of CustomTrackingRecord.
The problem is that we can use both TrackingParticipants indivisually, but not together - we never get our subclass from CustomTrackingRecord but A CustomTrackingRecord.
If I put bopth queries into one TrackingParticipant and then handle everythign in one, both work perfectly (which indicates teh error is not where we throw them).
The code in question for the combined one is:
public WorkflowServiceTrackingParticipant ()
{
this.TrackingProfile = new TrackingProfile()
{
ActivityDefinitionId = "*",
ImplementationVisibility = ImplementationVisibility.All,
Name = "WorkflowServiceTrackingProfile",
Queries = {
new CustomTrackingQuery() { Name = "*", ActivityName = "*" },
new ActivityStateQuery() {
States = {
ActivityStates.Canceled,
ActivityStates.Closed,
ActivityStates.Executing,
ActivityStates.Faulted
}
},
}
};
}
When using two TrackingParticipants we have two TrackingProfile (with different names) that each have one of the queries.
in the track method, when using both separate, the lines:
protected override void Track(TrackingRecord record, TimeSpan timeout)
{
Console.WriteLine("*** ActivityTracking: " + record.GetType());
if (record is ActivityBasedTrackingRecord)
{
System.Diagnostics.Debugger.Break();
}
never result in the debugger hitting, when using only the one to track our CustomTrackingRecord subclass (ActivityBasedTrackingRecord) then it works.
Anyone else knows about this? For now we have combined both TrackingParticipants into one, but this has the bad side effect that we can not dynamically expand the logging possibilities, which we would love to. Is this a known issue with WWF somewhere?
Version used: 4.0 Sp1 Feature Update 1.
I guess I encounterad the exact same problem.
This problem occurs due to the restrictions of the extension mechanism. There can be only one instance per extension type per workflow instance (according to Microsoft's documentation). Interesting enough though, one can add multiple instances of the same type to one workflow's extensions which - in case of TrackingParticipant derivates - causes weird behavior, because only one of their tracking profiles is used for all participants of the respective type, but all their overrides of the Track method are getting invoked.
There is a (imho) ugly workaround to this: derive a new participant class from TrackingParticipant for each task (task1, task2, logging ...)
Regards,
Jacob
I think that this problem isn't caused by extension mechanism, since DerivedParticipant 1 and DerivedParticipant 2 are not the same type(WF internals just use polymorphism on the base class).
I was running on the same issue, my Derived1 was tracking records that weren't described in its profile.
Derived1.TrackingProfile.Name was "Foo" and Derived2.TrackingProfile.Name was null
I changed the name from null to "Bar" and it worked as expected.
Here is a WF internal reference code, describing how is the Profile selected
// System.Activities.Tracking.RuntimeTrackingProfile.RuntimeTrackingProfileCache
public RuntimeTrackingProfile GetRuntimeTrackingProfile(TrackingProfile profile, Activity rootElement)
{
RuntimeTrackingProfile runtimeTrackingProfile = null;
HybridCollection<RuntimeTrackingProfile> hybridCollection = null;
lock (this.cache)
{
if (!this.cache.TryGetValue(rootElement, out hybridCollection))
{
runtimeTrackingProfile = new RuntimeTrackingProfile(profile, rootElement);
hybridCollection = new HybridCollection<RuntimeTrackingProfile>();
hybridCollection.Add(runtimeTrackingProfile);
this.cache.Add(rootElement, hybridCollection);
}
else
{
ReadOnlyCollection<RuntimeTrackingProfile> readOnlyCollection = hybridCollection.AsReadOnly();
foreach (RuntimeTrackingProfile current in readOnlyCollection)
{
if (string.CompareOrdinal(profile.Name, current.associatedProfile.Name) == 0 && string.CompareOrdinal(profile.ActivityDefinitionId, current.associatedProfile.ActivityDefinitionId) == 0)
{
runtimeTrackingProfile = current;
break;
}
}
if (runtimeTrackingProfile == null)
{
runtimeTrackingProfile = new RuntimeTrackingProfile(profile, rootElement);
hybridCollection.Add(runtimeTrackingProfile);
}
}
}
return runtimeTrackingProfile;
}

Resources