private const ConnectionType UserIdConnectionType = ConnectionType.RemoteTrusted; //use RemoteTrusted if specifying a windows user on the server, or SQL if using a DB local user /// <summary> /// The Main method - the standard entry function for a .Net console application. This method will execute other /// methods in order to fulfill the final goal - in this case, printing the name of the Root node in the Archive instance. /// </summary> static void Main() { //create a client instance (in this case, the addition of a service reference auto-generated this 'proxy' class) to operate with. CinegyDataAccessServiceClient cinegyClient = new CinegyDataAccessServiceClient(); //CAS requires a connection context to be provided with most calls, in order to assign the correct session to any individual call. //This context is linked to a user login, and will determine the security context in which results are returned. //Identical calls to the same method varying by context may yield different results, depending on the user permissions! ConnectContext clientConnectContext = ConnectToCas(cinegyClient); //The CAS proxy object implements a number of concrete types - but any type that exists in the explorer tree structure //inherit from Node. The Root Node is a special object which represents the very start of the explorer tree. //If you wanted to draw the tree out, you would start by getting the details of the root node. Node rootNode = GetRootNode(cinegyClient, clientConnectContext); //Little bit of error checking, in case the connection has failed and the root node is null if (rootNode != null) { Console.WriteLine("Connected to CAS OK, Root Node Name: " + rootNode.name); } //CAS will keep a connection alive for a time (the default is 5 minutes, unless altered in configuration). //A heartbeat can be transmitted to let the service know the connection is still alive, and absence of this //light-weight heartbeat (or other calls) will make the service terminate the connection (and invalidate the context). //However, if you know you are disconnecting, call the explict disconnection and then the service will //return the license for that connection and invalidate the context immediately. This is very useful when configured //to block secondary logins from one user if another is active (just like the Desktop client). DisconnectFromCas(cinegyClient, clientConnectContext); Console.WriteLine("\n\nPress Enter to Quit."); Console.ReadLine(); }
/// <summary> /// A method to explicitly disconnect from CAS, returning the used license and freeing this user account to be used again /// </summary> /// <param name="cinegyClient">A valid instance of a CAS proxy client</param> /// <param name="clientContext">The context to be returned to the pool and invalidated</param> private static void DisconnectFromCas(CinegyDataAccessServiceClient cinegyClient, ConnectContext clientContext) { try { string errorMsg; cinegyClient.Disconnect(ref clientContext, out errorMsg); } catch (Exception ex) { Console.WriteLine("Failed to disconnect cleanly from CAS - don't worry, the service will timeout the connection within a few minutes anyway. Exception: " + ex.Message); } }
private static Node GetRootNode(CinegyDataAccessServiceClient cinegyClient, ConnectContext clientContext) { string errorMsg; int retCode; Node rootNode = cinegyClient.GetRoot(clientContext, out retCode, out errorMsg); if (rootNode == null) { Console.WriteLine("Error " + retCode + " while trying to retrieve root node: " + errorMsg); return(null); } return(rootNode); }
/// <summary> /// The method that locates and returns the special-case 'root node'. From this node, all other nodes can be located. /// </summary> /// <param name="cinegyClient">A valid instance of a CAS proxy client</param> /// <param name="clientContext">The context to be returned and invalidated</param> /// <returns>A generic CAS Node object containing the root node details for the database the supplied context was generated from.</returns> private static Node GetRootNode(CinegyDataAccessServiceClient cinegyClient, ConnectContext clientContext) { string errorMsg; int retCode; //the actual root node is cast into a CAS Node class from the client special method 'GetRoot' - the main call in this wrapper method. Node rootNode = cinegyClient.GetRoot(clientContext, out retCode, out errorMsg); if (rootNode == null) { Console.WriteLine("Error " + retCode + " while trying to retrieve root node: " + errorMsg); return(null); } return(rootNode); }
/// <summary> /// This is the worker method for carrying out the actual connection to the CAS service. /// If the connection fails, errors are logged to the console (this should be structured exceptions in production code) /// </summary> /// <param name="cinegyClient">The instance of the proxy class to use to connect with</param> /// <returns>If successful, a valid ConnectContext object to be used for other stateful calls to methods</returns> private static ConnectContext ConnectToCas(CinegyDataAccessServiceClient cinegyClient) { ConnectContext clientContext; try { string errorMsg; int retCode; string applicationId = string.Format("{0}##{1}##{2}##{3}", ApplicationName, ApplicationGuid, MinimumCasVersion, VersionId); cinegyClient.Endpoint.Address = new EndpointAddress(CasUrl); BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportCredentialOnly); //in this example, we are updating various WCF parameters to allow more data to flow back and forward. //the defaults set by the automatic generation of the proxy are a bit low. //they can be altered by hand in the app.config file, or by code (shown below). //watch out for problems with these values being too small if you generate a fresh project and reference! binding.MaxReceivedMessageSize = 2147483647; binding.MaxBufferSize = 2147483647; binding.ReaderQuotas.MaxStringContentLength = 2147483647; binding.ReaderQuotas.MaxArrayLength = 2147483647; cinegyClient.Endpoint.Binding = binding; clientContext = cinegyClient.Connect(DbServer, 0, DbName, UserIdConnectionType, UserName, UserPassword, applicationId, DomainName, WrapperType.None, out retCode, out errorMsg); if (retCode != 0) { Console.WriteLine("Error " + retCode + " while connecting: " + errorMsg); return(null); } } catch (Exception ex) { Console.WriteLine("Connection attempt threw exception: " + ex.Message); return(null); } return(clientContext); }
/// <summary> /// This is the worker method for carrying out the actual connection to the CAS service. /// If the connection fails, errors are logged to the console (this should be structured exceptions in production code) /// </summary> /// <param name="cinegyClient">The instance of the proxy class to use to connect with</param> /// <returns>If successful, a valid ConnectContext object to be used for other stateful calls to methods</returns> private static ConnectContext ConnectToCas(CinegyDataAccessServiceClient cinegyClient) { ConnectContext clientContext; try { string errorMsg; int retCode; //All connections to CAS should be identified, allowing easier administration. //The applcation ID here matches a pattern for the server to parse, which includes a //free-text (human friendly) applcation name, a Guid (which is used to retrieve the correct //license from the CAS license pool), the minimum CAS version required by the client, and a //version ID string identifying the version of the client. string applicationId = string.Format("{0}##{1}##{2}##{3}", ApplicationName, ApplicationGuid, MinimumCasVersion, VersionId); //The use of an endpoint address here allows the configuration in auto-generated WCF proxies to be overriden. //This is very useful when the client application may need to connect to multiple endpoints based on user selection. cinegyClient.Endpoint.Address = new EndpointAddress(CasUrl); //This is the call to the actual method (via the proxy client) that will return the context. //Tracing through this method in debug mode will reveal other code generated by WCF that deals with making this call over HTTP clientContext = cinegyClient.Connect(DbServer, 0, DbName, UserIdConnectionType, UserName, UserPassword, applicationId, DomainName, WrapperType.None, out retCode, out errorMsg); //If things have failed, the return code from any CAS method will be non-zero if (retCode != 0) { Console.WriteLine("Error " + retCode + " while connecting: " + errorMsg); return(null); } } catch (Exception ex) { Console.WriteLine("Connection attempt threw exception: " + ex.Message); return(null); } return(clientContext); }
/// <summary> /// This is the method for executing the actual search query on the server. /// </summary> /// <param name="cinegyClient">The instance of the proxy class to use to connect with</param> /// <param name="clientContext">The active context to use for the query</param> /// <param name="searchWrapper">The wrapper class containing all relevant parameters for the search.</param> /// <returns>An array of SearchResults populated with values for the page</returns> private static SearchResult[] Search(CinegyDataAccessServiceClient cinegyClient, ConnectContext clientContext, SearchWrapper searchWrapper) { try { string errorMsg; //Pepare the array for containing the result set. SearchResult[] searchResults; int returnCode; //Execute the actual search method against CAS, passing the prepared parameters. cinegyClient.Search(clientContext, searchWrapper.Parameters, out searchResults, out returnCode, out errorMsg); Console.WriteLine("Return Code: " + returnCode); Console.WriteLine("Message: " + errorMsg); return(searchResults); } catch (Exception ex) { Console.WriteLine("Search failed. Exception: " + ex.Message); return(null); } }
private static ConnectContext ConnectToCas(CinegyDataAccessServiceClient cinegyClient) { ConnectContext clientContext; try { string errorMsg; int retCode; string applicationId = string.Format("{0}##{1}##{2}##{3}", ApplicationName, ApplicationGuid, MinimumCasVersion, VersionId); cinegyClient.Endpoint.Address = new EndpointAddress(CasUrl); BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportCredentialOnly); binding.MaxReceivedMessageSize = 2147483647; binding.MaxBufferSize = 2147483647; binding.ReaderQuotas.MaxStringContentLength = 2147483647; binding.ReaderQuotas.MaxArrayLength = 2147483647; cinegyClient.Endpoint.Binding = binding; clientContext = cinegyClient.Connect(DbServer, 0, DbName, UserIdConnectionType, UserName, UserPassword, applicationId, DomainName, WrapperType.None, out retCode, out errorMsg); if (retCode != 0) { Console.WriteLine("Error " + retCode + " while connecting: " + errorMsg); return(null); } } catch (Exception ex) { Console.WriteLine("Connection attempt threw exception: " + ex.Message); return(null); } return(clientContext); }
private const ConnectionType UserIdConnectionType = ConnectionType.RemoteTrusted; //use RemoteTrusted if specifying a windows user on the server, or SQL if using a DB local user /// <summary> /// The Main method - the standard entry function for a .Net console application. This method will execute other /// methods in order to fulfill the final goal - in this case, running the main console input loop to perform a Cinegy search. /// </summary> static void Main(string[] args) { Console.ForegroundColor = ConsoleColor.Green; //colour the console green, since it is springtime! #justforfun //create a client instance (in this case, the addition of a service reference auto-generated this 'proxy' class) to operate with. CinegyDataAccessServiceClient cinegyClient = new CinegyDataAccessServiceClient(); //CAS requires a connection context to be provided with most calls, in order to assign the correct session to any individual call. //This context is linked to a user login, and will determine the security context in which results are returned. //Identical calls to the same method varying by context may yield different results, depending on the user permissions! ConnectContext clientConnectContext = ConnectToCas(cinegyClient); if (clientConnectContext == null) { while (Console.KeyAvailable == false) { } return; } Console.WriteLine("\nConnected to " + DbName + "\n"); HandleConsoleInput(cinegyClient, clientConnectContext); DisconnectFromCas(cinegyClient, clientConnectContext); }
/// <summary> /// This method, first introduced in this sample application, looks up a specified node and returns an array of all of it's child nodes. /// </summary> /// <param name="parentId">The database GUID of the node to look up and return the child nodes from.</param> /// <param name="cinegyClient">A valid instance of a CAS proxy client</param> /// <param name="clientContext">The context to be returned and invalidated</param> /// <returns>An array of child nodes, belonging to the parent node specifed.</returns> private static Node[] GetChildren(Guid parentId, CinegyDataAccessServiceClient cinegyClient, ConnectContext clientContext) { string errorMsg; int retCode; //While CinegyAS node id's are often exchanged as simple .NET Guids, they need to be cast into this //special NODEID object when actually used with the proxy client methods. This object contains the //actual GUID as a field. NODEID id = new NODEID(); id._nodeid_id = parentId; //When calling the method to GetChildrenNodes, a real instance of the parent node does not need to be //created - a local copy of NodeBase (from which Node inherits) can be used instead, with the crucial //ID value allocated. Doing this save a call just to get a real copy of the 'Node' first. NodeBase parentNode = new NodeBase() { _id = id }; //The first interesting new method of this sample - the call to GetChildrenNode. //This method requires a reference to the NodeBase (which can be a previously returned instance of a Node, or a local variable of NodeBase), //which will be used as the parent to query. //The GET_NODE_REQUEST_TYPE is interesting, since it allows you to filter the results to show all, deleted or not deleted nodes. Not Deleted will //be the most useful in many cases. Node[] children = cinegyClient.GetChildrenNodes(clientContext, parentNode, GET_NODE_REQUEST_TYPE.NotDeleted, out retCode, out errorMsg); if (retCode != 0) { Console.WriteLine("Error " + retCode + " while trying to retrieve Children: " + errorMsg); return(null); } return(children); }
private static Node GetNode(Guid nodeId, CinegyDataAccessServiceClient cinegyClient, ConnectContext clientContext) { string errorMsg; int retCode; NODEID id = new NODEID(); id._nodeid_id = nodeId; NodeBase nodeBase = new NodeBase() { _id = id }; Node node = cinegyClient.GetNode(clientContext, nodeBase, GET_NODE_REQUEST_TYPE.NotDeleted, out retCode, out errorMsg); if (node == null) { Console.WriteLine("Error " + retCode + " while trying to retrieve Node: " + errorMsg); return(null); } return(node); }
/// <summary> /// The method used to allow interactive commanding of the search process. Will repeat /// inside a 'do' loop until the 'Q' key is pressed, whereupon it will quit the loop (ultimately /// leading to the application terminating). /// </summary> /// <param name="cinegyClient">The instance of the proxy class to use to connect with</param> /// <param name="clientContext">The active context to use for the query</param> private static void HandleConsoleInput(CinegyDataAccessServiceClient cinegyClient, ConnectContext clientContext) { ConsoleKeyInfo keyInfo = new ConsoleKeyInfo(); //This is a List of node IDs for moving back and forward by the pageful in the result set. //These IDs will be used as the _guid_start_id property of the SearchParameters object. IList <Guid> searchPageIDs = new List <Guid>(); //Create an instance of the SearchWrapper class, used to command the search operation SearchWrapper searchWrapper = new SearchWrapper(); SearchResult[] searchResults; //main 'do' loop for console input do { Console.WriteLine("\n--------------------------------------------------------"); Console.WriteLine("Press the 's' key to start new search."); Console.WriteLine("Press the 'n' key to go to next search result page."); Console.WriteLine("Press the 'p' key to go to previous search result page."); Console.WriteLine("Press the 'q' key to quit\n"); while (Console.KeyAvailable == false) { } keyInfo = Console.ReadKey(true); switch (keyInfo.Key) { //The user wants to start a new search. This will reset the wrapper, and set //a new general string search paramter containing the entered text. case ConsoleKey.S: Console.Write("Keyword: "); //this list will be populated with IDs referring to every page of //results that are returned. searchPageIDs = new List <Guid>(); searchWrapper = new SearchWrapper(); searchWrapper.Parameters._str_search = Console.ReadLine(); Console.WriteLine("Searching...\n"); //Call to a local method to organise the values collected ready to run the actual search. PrepareSearch(searchWrapper, searchPageIDs, SearchMode.NewSearch); //Call to a local method to execute the prepared seach operation. searchResults = Search(cinegyClient, clientContext, searchWrapper); //Call to a local method to process the results and respond. HandleSearchResults(searchResults, searchWrapper, searchPageIDs); break; //Pages to the nex search page returned from CAS, so the screen is not overfilled case ConsoleKey.N: Console.WriteLine("Retrieving next Page for '" + searchWrapper.Parameters._str_search + "'....\n"); //Again, calls to the PrepareSearch local method, but specifying the next page PrepareSearch(searchWrapper, searchPageIDs, SearchMode.NextPage); //And then re-executes the search method to get the filled results searchResults = Search(cinegyClient, clientContext, searchWrapper); //Before processing the display HandleSearchResults(searchResults, searchWrapper, searchPageIDs); break; //Pages to the prvious search page returned from CAS. case ConsoleKey.P: Console.WriteLine("Retrieving previous Page for '" + searchWrapper.Parameters._str_search + "'....\n"); //Same as next page, but now with a different mode (PreviousPage) PrepareSearch(searchWrapper, searchPageIDs, SearchMode.PreviousPage); searchResults = Search(cinegyClient, clientContext, searchWrapper); HandleSearchResults(searchResults, searchWrapper, searchPageIDs); break; //Quit application. case ConsoleKey.Q: Console.WriteLine("Quitting..."); break; default: Console.WriteLine("Unknown Key Command"); break; } } while (keyInfo.Key != ConsoleKey.Q); }
private const ConnectionType UserIdConnectionType = ConnectionType.RemoteTrusted; //use RemoteTrusted if specifying a windows user on the server, or SQL if using a DB local user /// <summary> /// The Main method - the standard entry function for a .Net console application. This method will execute other /// methods in order to fulfill the final goal - in this case, printing the details of all the children of the specified node. /// If no node ID GUID is passed as a command line argument, the details of the root node will be displayed. /// </summary> static void Main(string[] args) { CinegyDataAccessServiceClient cinegyClient = new CinegyDataAccessServiceClient(); ConnectContext clientConnectContext = ConnectToCas(cinegyClient); //if no arguments have been passed in, provide the name and DB ID of the root node if ((args == null) || (args.Length == 0)) { Node rootNode = GetRootNode(cinegyClient, clientConnectContext); if (rootNode != null) { Console.WriteLine("Connected to CAS OK, Root Node Name: " + rootNode.name + ", Root Node ID: " + rootNode._id._nodeid_id.ToString()); } } else { Guid parentId; //attempt to turn the first command line argument to a valid GUID if (Guid.TryParse(args[0], out parentId)) { //Get an array of Node objects representing the 'children' contained by this specified 'parent' node. Node[] children = GetChildren(parentId, cinegyClient, clientConnectContext); if (children != null) { if (children.GetLength(0) == 0) { Console.WriteLine("No children nodes found - is the supplied node empty or missing?"); Console.WriteLine(); } //All items that exist in the tree can be cast as Nodes, no matter what they //really are (folders, clips, bins) - they all inherit from Node. //This makes it simple to get key properties that are shared by //these different types. foreach (Node child in children) { //All nodes have names - this is what is displayed to the user, for example in the explorer tree Console.WriteLine("[" + child.name + "]"); //A node type is a concrete type which defines key behaviours and properties. Sub-types are loosely coupled, and configurable. //For example, Portfolios, Programmes and Folders are all of master type 'Folder', and differ by Sub-type (which allows //these items to have different names and icons). Console.WriteLine("\t" + "Type: " + child._type.ToString()); //A node's _id value is the identity that it has in the database, and is unique. Nodes can be looked up //using other methods in the client by their node _id value. Console.WriteLine("\t" + "ID: " + child._id._nodeid_id.ToString()); Console.WriteLine(); } } } else { Console.WriteLine("Format of Node ID is not valid"); } } //Don't forget to disconnect! DisconnectFromCas(cinegyClient, clientConnectContext); Console.WriteLine("\n\nPress Enter to Quit."); Console.ReadLine(); }
private const ConnectionType UserIdConnectionType = ConnectionType.RemoteTrusted; //use RemoteTrusted if specifying a windows user on the server, or SQL if using a DB local user /// <summary> /// The Main method - the standard entry function for a .Net console application. This method will execute other /// methods in order to fulfill the final goal - in this case, printing the details of all the children of the specified node, along with any metadata fields set. /// </summary> static void Main(string[] args) { CinegyDataAccessServiceClient cinegyClient = new CinegyDataAccessServiceClient(); ConnectContext clientConnectContext = ConnectToCas(cinegyClient); if ((args == null) || (args.Length == 0)) { Console.WriteLine("No Node ID provided - please provide a GUID as a command line argument to this application."); //The root node cannot currently be looked up with the generic call to GetNodeByID (in the future, this will be improved) //So don't try and get metadata from the root node with this sample! Console.WriteLine("Please note, this GUID provided must NOT be the Root Node GUID!"); Console.WriteLine(); } else { Guid nodeId; if (Guid.TryParse(args[0], out nodeId)) { Node node = GetNode(nodeId, cinegyClient, clientConnectContext); if (node != null) { Console.WriteLine("[" + node.name + "]"); Console.WriteLine("\t" + "Type: " + node._type.ToString()); Console.WriteLine("\t" + "ID: " + node._id._nodeid_id.ToString()); Console.WriteLine("\t" + "Owner: " + node.owner); Console.WriteLine(); //The node metadataSet is the group of metadata objects, which includes values, assigned to the node. //An object with no metadata values will not have a metadata set, since empty values are not //included in the results. if (node.metadataSet != null) { Console.WriteLine("*** Metadata ***"); Console.WriteLine(); //The node metadatSet has a property 'metadata' which is an array of metadata objects foreach (var metadata in node.metadataSet.metadata) { //print out the interesting properties of the metadata object Console.WriteLine("[" + metadata.internalName + "]"); Console.WriteLine("\t" + "Descriptor ID: " + metadata.descriptorID._nodeid_id.ToString()); Console.WriteLine("\t" + "Type: " + metadata.type); Console.WriteLine("\t" + "Value: " + metadata.value); Console.WriteLine(); } } } } else { Console.WriteLine("Format of Node ID is not valid"); } } //Remember, disconnect when you will not use this context again DisconnectFromCas(cinegyClient, clientConnectContext); Console.WriteLine("\n\nPress Enter to Quit."); Console.ReadLine(); }