Mashup quality control #6

Here is the code to find hard-coded values in the MForms Automation URIs in Mashups; in this sixth episode of Mashup quality control for Infor Smart Office.

MForms Automation   @deprecated

MForms Automation are the predecessor of MForms Bookmarks; they are used to execute steps in Smart Office, such as run M3 programs and set values in fields. But they are unstable compared to Bookmarks, so they are now deprecated.

We create them with the MForms Automation Builder, but the tool has been discontinued and is not available anymore the tool is available in the Smart Office SDK > External > M3 > Tools:

The result in Mashups is an MForms Automation URI in <mashup:Event LinkUri=…> or <mashup:Link Uri=…> such as:

<mashup:Event SourceEventName="Click" LinkUri="mforms://_automation?data=%3c%3fxml+version%3d%221.0%22+encoding%3d%22utf-8%22%3f%3e%3csequence%3e%3cstep+command%3d%22RUN%22+value%3d%22CRS610%22+%2f%3e%3cstep+command%3d%22KEY%22+value%3d%22ENTER%22%3e%3cfield+name%3d%22WWQTTP%22%3e1%3c%2ffield%3e%3c%2fstep%3e%3cstep+command%3d%22KEY%22+value%3d%22ENTER%22%3e%3cfield+name%3d%22W1OBKV%22%3eTHIBAUD%3c%2ffield%3e%3c%2fstep%3e%3cstep+command%3d%22LSTOPT%22+value%3d%225%22+%2f%3e%3c%2fsequence%3e" />

We can also create the automations with scripts as illustrated in the Infor Smart Office M3 Developers Guide:

I use the method FromXml(String) to parse the automation from an XML string:

Source code

Here is the source code that will search in all Mashups, all XAML, all MForms Automation URIs, all steps, all fields, and will list the hard-coded values:

import System;
import System.Collections.Specialized;
import System.IO;
import System.Text.RegularExpressions;
import System.Web;
import System.Xml;
import Mango.Core.Util;
import Mango.UI.Core.Util;
import Mango.UI.Services.Mashup;
import Mango.UI.Services.Mashup.Internal;

package MForms.JScript {
    class Test {
        public function Init(element: Object, args: Object, controller : Object, debug : Object) {
            var regex: Regex = StringUtil.GetRegex(ParameterBracket.Curly); // {(?<param>[\u0000-\uFFFF-[}]]*)}
            var mashups /*IList<FileInfo>*/ = PackageHelper.GetSharedMashupList();
            for (var mashup: FileInfo in mashups) {
                var baseUri: Uri = UriHelper.CreateBaseUri(new Uri(mashup.Name, UriKind.RelativeOrAbsolute));
                var manifest: Manifest = PackageHelper.GetManifest(mashup);
                var list /*IList<FileInformation>*/ = manifest.CreateFileInformationList();
                for (var information: FileInformation in list) {
                    if (information.MimeType == Defines.MimeTypeXAML) {
                        var relativeUri: String = information.Path;
                        var stream: Stream = PackageHelper.GetStream(baseUri, new Uri(relativeUri, UriKind.Relative));
                        var document: XmlDocument = new XmlDocument();
                        var nodes: XmlNodeList = document.SelectNodes(" //@*[name()='Uri' or name()='LinkUri'] ");
                        for (var attribute: XmlAttribute in nodes) {
                            if (!attribute.Value.StartsWith("{Binding") && !attribute.Value.EndsWith(".xaml")) {
                                try {
                                    var uri: Uri = new Uri(attribute.Value);
                                    if (uri.Scheme == "mforms" && (uri.Host == "_automation" || uri.Host == "automation")) {
                                        var collection: NameValueCollection = HttpUtility.ParseQueryString(new Uri(uri).Query);
                                        var automation: MFormsAutomation = new MFormsAutomation();
                                        for (var step: MFormsAutomation.Step in automation.Steps) {
                                            for (var field: MFormsAutomation.Field in step.Fields) {
                                                if (!String.IsNullOrEmpty(field.Value)) {
                                                    if (!regex.IsMatch(field.Value)) {
                                                        debug.WriteLine([mashup.Name, relativeUri, attribute.OwnerElement.Name, attribute.Name, field.Name, field.Value]);
                                } catch (ex: UriFormatException) {
                                    debug.WriteLine([ex, attribute.Value]); 


The result is a list of hard-coded values:

In my case I have several hard-coded values: company (CONO), attribute model (ATMO), userid (OBKV), and dates (DATE); I will need to review those in priority. Then, there are other hard-coded values: priority (PREX), inquiry type (QTTP), panel view (PAVR), facility range from/to (FACI), action keys (CMDVAL), and order type (ORTP); they are probably OK.

The metrics are:

  • 13 Mashups
  • 178 XAML files
  • 35,195 lines of code
  • 339 URIs
  • 41 of them are MForms Automation URIs
  • 96 automation steps
  • 157 automation fields
  • 44 hard-coded values
  • 7 of them to un-hard-code (16% of above)

The tool helped me quickly scan over 35,000 lines of code and identify 7 hard-coded values to un-hard-code. I would not have been able to do it so fast and so accurately by visual inspection only.

That’s it!

Please comment, like, subscribe, share, author. Thanks for your support.

Related posts

Published by


ex- M3 Technical Consultant

9 thoughts on “Mashup quality control #6”

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s