Management Client: Roles Issue for Programmatically Created Items

Hi,

We have developed a plugin with a component that works within the Management Client. As part of this plugin, we have an item under the Servers entry in the tree. Under this item is a series of items (e.g. Encoders) which have child items (e.g. Encoder Inputs). For this application, the child items are tightly tied to the parent and have limited configuration requirements; therefore, we are creating the child items (Encoder Inputs) programmatically rather than from the tree and displaying the configuration for them in the parent form (Encoder) rather than a separate configuration screen. All of this works as expected.

When we attempt to set roles for accessing the devices. We get an error when setting the role for the child devices that are created programmatically. This error is:

TITLE: OnAfterCheck ()

------------------------------

VMO60021: Could not create the access entry. The object with the ID 9c11af98-5943-4d33-aa91-f17c55198592 does not exist.

------------------------------

ADDITIONAL INFORMATION:

VMO60021: Could not create the access entry. The object with the ID 9c11af98-5943-4d33-aa91-f17c55198592 does not exist. (mscorlib)

------------------------------

BUTTONS:

OK

------------------------------

The error seem to indicate that the item does not exist; however, this is the item that was created and has been verified to exist.

If we create them via the tree (which is possible though not the typical way in which it is done), we do not get this error when setting the roles.

Sample code for the programmatic creation of the device is below:

                   EncoderInputUserControl \_userControl = new EncoderInputUserControl("EncoderInput");

                   Guid guid = Guid.NewGuid();

                   ServerId serverId = new ServerId(\_item.FQID.ServerId.ServerType, \_item.FQID.ServerId.ServerHostname, \_item.FQID.ServerId.Serverport, \_item.[FQID.ServerId.Id](https://FQID.ServerId.Id));

                   FQID suggestedFQID = new FQID(serverId, \_item.FQID.ObjectId, guid, [FolderType.No](https://FolderType.No), PAGuids.EncoderInputKind);

                   CurrentItem = new EncoderInputItem(suggestedFQID, "Enter a name", \_item);

                   if (\_userControl != null)

                   {

                       \_userControl.FillContent(CurrentItem);

                       CurrentItem.Properties\["EncoderInputNumber"\] = i.ToString();

                       [CurrentItem.Name](https://CurrentItem.Name) = "Enter a name ...";

                   }

                   if (CurrentItem != null)

                   {

                       Configuration.Instance.SaveItemConfiguration(PluginGuids.PluginId, CurrentItem);

                       SecurityAccess.RegisterItem(CurrentItem);

                   }

As part of this code we are creating the item, saving the configuration, and registering the item. Also, we have compared the programmatically created item with the tree created item and they appear to be identical except for information that should be different (e.g. objectId).

Can you tell us what part of the programmatic creation process is missing as compared to what the tree created process does for items?

Thanks

When using SecurityAccess, you also need to define how the security is used. This is done in ItemNode definition.

Check what you have in the SecurityActions property..

Hi,

Below is the itemNodes definition being used. I believe we have the correct security actions defined for the Server (upper level), Encoder (mid level) ,and Encoder Inputs (lowest level, programmatically generated) which are all Manage/Read.

       \_itemNodes = new List<ItemNode>

        {

          new ItemNode(Guids.ServerKind, Guid.Empty,"Server",                \_serverImage, "Servers", \_serverImage,Category.Text, true,ItemsAllowed.One, new ServerItemManager(Guids.ServerKind),

          new List<ItemNode> {

             new ItemNode(Guids.EncoderKind, Guids.ServerKind,"Encoder", \_treeNodeEncoderImage,"Encoders", \_treeNodeEncoderImage,Category.Text, true,ItemsAllowed.Many,new EncoderItemManager(Guids.EncoderKind),

 new List<ItemNode>

  {  new ItemNode(Guids.EncoderInputKind,Guids.EncoderKind,"Encoder Input", \_treeNodeEncoderInputImage,"Encoder Inputs", \_treeNodeEncoderInputImage,

Category.Text, true,ItemsAllowed.Many,

new EncoderInputItemManager(Guids.EncoderInputKind),null) {

SecurityActions = securityActionsEncInp,

MapIconDictionary=EncoderInputMapIcon,MapIcon=EncoderInputMapIcon[Guids.EncoderInputKind],

ContextMenu = _EncoderInputCM,

}

}

)

{

SecurityActions = securityActionsEnc,

MapIconDictionary = motionMonMapIcon,

MapIcon=motionMonMapIcon[Guids.EncoderKind],ContextMenu = _motionMonCM,

}

},null)

{

MapIconDictionary = serverMapIcon,

SecurityActions = securityActionsCtrl,

MapIcon = serverMapIcon[Guids.ServerKind],

ContextMenu = _serverCM,

PlacementHint=PlacementHint.Servers,

},

};

     List<SecurityAction> securityActionsCtrl = new List<SecurityAction>

                                              {

                                                 new SecurityAction("GENERIC\_WRITE", "Manage"),

                                                 new SecurityAction("GENERIC\_READ", "Read")

                                              };

     List<SecurityAction> securityActionsEnc = new List<SecurityAction>

                                              {

                                                 new SecurityAction("GENERIC\_WRITE", "Manage"),

                                                 new SecurityAction("GENERIC\_READ", "Read"),

                                              };

       List<SecurityAction> securityActionsEncInp = new List<SecurityAction>

                                                  {

                                                      new SecurityAction("GENERIC\_WRITE", "Manage"),

                                                      new SecurityAction("GENERIC\_READ", "Read"),

                                                  };

Also, forgot to mention earlier that we are using 2018 R3.

Thanks

We will experiment and based on what we find we will update this question next week.

If it will help, I can provide a sample application/code that reproduces the issue.

Thanks

That must be helpful. Could you please provide the sample application/code?

How do I upload the project/dll?

Thanks

If requested to upload files to the support FTP server, please upload the files to a folder carrying the case number (MSC371327) as folder name. If the folder does not exist, please create it.

EMEA FTP server details:

FTP url: msftp.milestone.dk

Username for uploading files: UpLoad

Password for uploading files: 1qazxsw2

Link: FTP://UpLoad:1qazxsw2@msftp.milestone.dk

If you are uploading large files or have connectivity issues, then we recommend using a FTP client program that supports resume.

And please let Milestone Support know when the upload is done.

I didn’t receive anything from you. Could you please upload files?

We are preparing a sample and should have it uploaded this week.

The sample has been uploaded to the MSC371327 folder.

Thanks

Thank you for the files, Milestone Development is investigating it.

We could reproduce the issue. Milestone Development will investigate it.

We had a developer analyse your code and the feedback is:

The EncoderManager.cs needs to save encoder - BEFORE creating the client inputs. Line 117 should be:

public override Item CreateItem(Item parentItem, FQID suggestedFQID)
{
	CurrentItem = new PAEncoderItem(suggestedFQID, "Enter Encoder name ...", parentItem);
            Configuration.Instance.SaveItemConfiguration(PAGuids.PAPluginId, CurrentItem);
            SecurityAccess.RegisterItem(CurrentItem);
            if (_userControl != null)
			{
				_userControl.FillContent(CurrentItem);
			}
			return CurrentItem;
		}