ConfigurationApi.ClientService.QueryItems vs ConfigurationServiceClient::GetItems to return all CameraGroups

Hello,

If I use ConfigurationApi.ClientService.QueryItems::Query() for CameraGroups it only returns the toplevel CameraGroup.

I know I can then loop on that and recursively load all children CameraGroups, but I’d like an API that directly gives me all CameraGroups.

Would ConfigurationServiceClient::GetItems(“CameraGroup”) return all children?

I ask before because settings up the code to get a ConfigurationServiceClient instance is incredibly painful compared to ConfigurationApi.ClientService.QueryItems, and there are good chances that ConfigurationServiceClient is just as limited and I have to go the recursive route.

You will need to use GetChildItemsHierarchy

We have this sample:

private static ConfigurationItem[] GetAllGroups(string url, bool isBasic, string userName, string password)
{
	Uri uri = new UriBuilder(url).Uri;
	string hostName = uri.Authority;
	string uriString;
	if (isBasic)
	{
		if (uri.Port == 80)
		{
			hostName = uri.Host;
		}
		uriString = string.Format(https://{0}/ManagementServer/ConfigurationApiService.svc, hostName);
	}
	else
		uriString = string.Format(http://{0}/ManagementServer/ConfigurationApiService.svc, hostName);
 
	var spn = SpnFactory.GetSpn(new Uri(uriString));
	var endpointAddress = new EndpointAddress(new Uri(uriString), new SpnEndpointIdentity(spn));
 
	var client = new ConfigurationServiceClient(GetBinding(isBasic), endpointAddress);
	if (isBasic)
	{
		client.ClientCredentials.UserName.UserName = "[BASIC]\\" + userName;
		client.ClientCredentials.UserName.Password = password;
	}
	else
	{
		client.ClientCredentials.Windows.ClientCredential = new NetworkCredential(userName, password);
	}
	client.InnerChannel.Open();
 
	var cameraGroupFilter = new ItemFilter("CameraGroup", new PropertyFilter[0]);
	return client.GetChildItemsHierarchy("/CameraGroupFolder", new string[] { "CameraGroup" }, new[] { cameraGroupFilter });
}
 
private static System.ServiceModel.Channels.Binding GetBinding(bool IsBasic)
{
	if (!IsBasic)
	{
		WSHttpBinding binding = new WSHttpBinding();
		var security = binding.Security;
		security.Message.ClientCredentialType = MessageCredentialType.Windows;
 
		binding.ReaderQuotas.MaxStringContentLength = 2147483647;
		binding.MaxReceivedMessageSize = 2147483647;
		binding.MaxBufferPoolSize = 2147483647;
		binding.ReaderQuotas = XmlDictionaryReaderQuotas.Max;
 
		var timeout = TimeSpan.FromMinutes(10);
		binding.SendTimeout = timeout;
		binding.OpenTimeout = timeout;
		binding.CloseTimeout = timeout;
		binding.ReceiveTimeout = timeout;
		return binding;
	}
	else
	{
		BasicHttpBinding binding = new BasicHttpBinding();
		binding.ReaderQuotas.MaxStringContentLength = 2147483647;
		binding.MaxReceivedMessageSize = 2147483647;
		binding.MaxBufferSize = 2147483647;
		binding.MaxBufferPoolSize = 2147483647;
		binding.TextEncoding = Encoding.UTF8;
		binding.UseDefaultWebProxy = true;
		binding.AllowCookies = false;
		binding.Namespace = "VideoOS.ConfigurationAPI";
		binding.Security.Mode = BasicHttpSecurityMode.Transport;
		binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
		var timeout = TimeSpan.FromMinutes(10);
		binding.SendTimeout = timeout;
		binding.OpenTimeout = timeout;
		binding.CloseTimeout = timeout;
		binding.ReceiveTimeout = timeout;
 
		return binding;
	}
}

Thanks, but you should really consider adding a method that wraps all this in the EnvironmentManager instance so it becomes easy to get a ConfigurationServiceClient instance.

My developer colleague gave me a simpler solution, simpler code:

ServerId serverId = EnvironmentManager.Instance.MasterSite.ServerId;
var cameraGroupFilter = new[] { new ItemFilter("CameraGroup", new PropertyFilter[0]) };
var managementServer = new ManagementServer(serverId);
managementServer.FillChildren(new[] { "CameraGroup" }, cameraGroupFilter);

Well, I don’t see the difference with:

ServerId serverId = EnvironmentManager.Instance.MasterSite.ServerId;
var managementServer = new ManagementServer(serverId);
var groups = IterateOverGroups(managementServer.CameraGroupFolder.CameraGroups);

I mean, FillChildren() is void, maybe the benefit of your code is performance because it loads all the tree in one go instead of doing it groups by groups when accessed but API wise it’s the same.

In general you have a hierarchy:

ManagementServer managementServer = new ManagementServer(EnvironmentManager.Instance.MasterSite.ServerId);
CameraGroupFolder cameraGroupFolder = managementServer.CameraGroupFolder;
ICollection<CameraGroup> cameraGroups = cameraGroupFolder.CameraGroups;
foreach (CameraGroup cameraGroup in cameraGroups) { }

I have a feeling that you are right though, it is different ways to get to the same result, I am not able to say what is the optimal way.

Yes, the code example of your colleague is basically “How do I use FillChildren() ?”, which is a question I had in another post, maybe your colleague was answering to that.