07-29-2014 02:52 AM
Hi
I figure it's probably a CUCN error.. I'm trying to load a callhandler identified by its display name.
The REST response returned contains this:
{"@total":"2","Callhandler":[{"URI":"/vmrest/handlers/callhandlers/afffae55-51e1-4b91-a9b1-6687304cc36a","CreationTime":"2014-06-26T07:49:12Z","Language":"1033","Undeletable":"false","LocationObjectId":"c41c21a9-ee9f-4590-8958-0b6b79adc99c","LocationURI":"/vmrest/locations/connectionlocations/c41c21a9-ee9f-4590-8958-0b6b79adc99c","EditMsg":"true","IsPrimary":"true","OneKeyDelay":"1500","ScheduleSetObjectId":"6675f0af-eefd-4069-911f-5de01a2e7316","ScheduleSetURI":"/vmrest/schedulesets/6675f0af-eefd-4069-911f-5de01a2e7316","SendUrgentMsg":"0","MaxMsgLen":"300","IsTemplate":"false","ObjectId":"afffae55-51e1-4b91-a9b1-6687304cc36a","RecipientSubscriberObjectId":"bd4232b0-fda4-4595-8b0a-8453f7bc646a","RecipientUserURI":"/vmrest/users/bd4232b0-fda4-4595-8b0a-8453f7bc646a","DisplayName":"bbrauntest03","AfterMessageAction":"2","AfterMessageTargetConversation":"PHTransfer","AfterMessageTargetHandlerObjectId":"fae64789-66a5-4f0f-87f2-edfd12bc87b7","TimeZone":"110","UseDefaultLanguage":"true","UseDefaultTimeZone":"true","MediaSwitchObjectId":"174307b7-42b1-42fa-a116-74352d986705","PhoneSystemURI":"/vmrest/phonesystems/174307b7-42b1-42fa-a116-74352d986705","UseCallLanguage":"false","SendSecureMsg":"false","EnablePrependDigits":"false","DispatchDelivery":"false","CallSearchSpaceObjectId":"32844888-e20f-4928-98ef-a0f1dd5383f4","CallSearchSpaceURI":"/vmrest/searchspaces/32844888-e20f-4928-98ef-a0f1dd5383f4","InheritSearchSpaceFromCall":"true","PartitionObjectId":"9b6e9273-2125-48fb-be13-2f9fbec9904f","PartitionURI":"/vmrest/partitions/9b6e9273-2125-48fb-be13-2f9fbec9904f","GreetingsURI":"/vmrest/handlers/callhandlers/afffae55-51e1-4b91-a9b1-6687304cc36a/greetings","TransferOptionsURI":"/vmrest/handlers/callhandlers/afffae55-51e1-4b91-a9b1-6687304cc36a/transferoptions","MenuEntriesURI":"/vmrest/handlers/callhandlers/afffae55-51e1-4b91-a9b1-6687304cc36a/menuentries"},{"URI":"/vmrest/handlers/callhandlers/78283670-03a5-4805-b43e-821295a481e0","CreationTime":"2014-06-27T07:07:17Z","Language":"1033","Undeletable":"false","LocationObjectId":"c41c21a9-ee9f-4590-8958-0b6b79adc99c","LocationURI":"/vmrest/locations/connectionlocations/c41c21a9-ee9f-4590-8958-0b6b79adc99c","EditMsg":"true","IsPrimary":"false","OneKeyDelay":"1500","ScheduleSetObjectId":"cf662275-9cfb-4f9f-9c61-76b79a93dcc9","ScheduleSetURI":"/vmrest/schedulesets/cf662275-9cfb-4f9f-9c61-76b79a93dcc9","SendUrgentMsg":"0","MaxMsgLen":"300","IsTemplate":"false","ObjectId":"78283670-03a5-4805-b43e-821295a481e0","RecipientSubscriberObjectId":"bd4232b0-fda4-4595-8b0a-8453f7bc646a","RecipientUserURI":"/vmrest/users/bd4232b0-fda4-4595-8b0a-8453f7bc646a","DisplayName":"bbrauntest03","AfterMessageAction":"1","TimeZone":"110","UseDefaultLanguage":"true","UseDefaultTimeZone":"false","MediaSwitchObjectId":"174307b7-42b1-42fa-a116-74352d986705","PhoneSystemURI":"/vmrest/phonesystems/174307b7-42b1-42fa-a116-74352d986705","UseCallLanguage":"true","SendSecureMsg":"false","EnablePrependDigits":"false","DispatchDelivery":"false","CallSearchSpaceObjectId":"32844888-e20f-4928-98ef-a0f1dd5383f4","CallSearchSpaceURI":"/vmrest/searchspaces/32844888-e20f-4928-98ef-a0f1dd5383f4","InheritSearchSpaceFromCall":"true","PartitionObjectId":"9b6e9273-2125-48fb-be13-2f9fbec9904f","PartitionURI":"/vmrest/partitions/9b6e9273-2125-48fb-be13-2f9fbec9904f","GreetingsURI":"/vmrest/handlers/callhandlers/78283670-03a5-4805-b43e-821295a481e0/greetings","TransferOptionsURI":"/vmrest/handlers/callhandlers/78283670-03a5-4805-b43e-821295a481e0/transferoptions","MenuEntriesURI":"/vmrest/handlers/callhandlers/78283670-03a5-4805-b43e-821295a481e0/menuentries"}]}
As the parsing method only expects a single result, json parsing fails with the following error:
Failure populating class instance form JSON response:Newtonsoft.Json.JsonSerializationException: Cannot populate JSON array onto type 'Cisco.UnityConnection.RestFunctions.CallHandler'. Path '', line 1, position 1.
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Populate(JsonReader reader, Object target)
at Newtonsoft.Json.JsonSerializer.PopulateInternal(JsonReader reader, Object target)
at Newtonsoft.Json.JsonSerializer.Populate(JsonReader reader, Object target)
at Newtonsoft.Json.JsonConvert.PopulateObject(String value, Object target, JsonSerializerSettings settings)
at Cisco.UnityConnection.RestFunctions.CallHandler.GetCallHandler(String pObjectId, String pDisplayName, Boolean pIsUserTemplateHandler)
Makes sense seeing that in Callhandler.cs we have the parsing code
JsonConvert.PopulateObject(ConnectionServerRest.StripJsonOfObjectWrapper(res.ResponseText, "Callhandler"), this,
RestTransportFunctions.JsonSerializerSettings);
and JsonConvert is meant for a single object.
However, when experimenting, I found that in fact creating two call handlers with the same displayName is in fact supported (there's only a warning), so the parsing should be able to handle this case even if it's not recommended to use duplicate display names.
07-29-2014 06:57 AM
The call that accepts the ObjectId or display name returns a single User object, not a list – so clearly it’s expecting the ObjectId or the display name in that case to be unique – even if I added code to handle a list there which one would I pass back?
non unique display names are odd to be sure but legal. If you’re working in a site that has non unique display names and you wish to find call handlers using that method anyway you’ll need to explicitly request a list and then check yourself if there’s 0, 1 or more returned and determine (somehow) which call handler it is you want out of the set.
Getting a list of call handlers with a query would look like this:
List<CallHandler> oHandlers;
res = CallHandler.GetCallHandlers(_cxn, out oHandlers, "query=(DisplayName is Opening Greeting)";
07-31-2014 05:09 AM
I don't know why I had the duplicate.. I think it was a DB error.. something that didn't get properly deleted (I'm creating and deleting the same thing over and over again until I have this complex setup working).
Either way.. is it correct behavior if you have a method that's supposed to return 0 or 1 items and it bombs out if there are two returned by the server? If I didn't have the source code, I wouldn't have known (except when looking at fiddler).
That's just my opinion but I would've designed a method that's supposed to return 0 or 1 items in an environment that can return more than 1 like FirstOrDefault() - with a check for the number of items (it's in the response).. it's a few lines of code switching between < 2 results and >= 2 results.
07-31-2014 07:58 AM
I'll take a look - I think my preference in that case would be to return an error and not the first entry just to avoid messy accidents - I guess returning false for success, a readable error message and the first item found wouldn't be horrible. Given the different formats for single return and multiple returns it's not exactly a couple lines of code, but not the end of the world.
down side is technically I'd need to add that logic to all object classes and all search criteria (duplicate aliases are not legal but can and do happen in the field for instance mostly due to replication issues) - a fair amount of work, but I'll stick it on my to-do list.
07-31-2014 12:04 PM
Took a simpler approach after talking with a couple peers - returning the first object instance if multiple are found didn't fly for anyone - if the call is targeted around a single instance and that fetch fails (0 or more than 1) a readable error to that effect should be returned - the consensus was that it would be more appropriate to a "find first" type method. Either way, I've implemented the more specific check with readable error changes for:
Call Handlers,CallHandlerTemplate,Directory Handlers,Interview handler,Location,User,Distribution Lists
Users are pushing it but since I've seen overlapping aliases due to replication failures between clusters I went ahead and made the check.The error is now explicit instead of the curious json parsing note.
will be part of 3.0.38 when I release it (probably tomorrow AM)
07-31-2014 12:13 PM
So I'm definitely not the only one working fast
Your approach sounds fine to me.. the main point is that if not using the source code version you have a chance to figure out what is going wrong. Of course you can activate tracing (I think I first saw in fiddler that I had two callhandlers using the same displayname), but if you get a result telling you the cause instead of some stacktrace that leaves you scratching your head, that's perfectly fine (I'm duping anything that is not a success in detail anyway so it all ends up in the logs... but as is, I got the exception that didn't tell me anything).
I went online with the self-compiled version for the time being as I needed the fix for the Html notification device.
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide