Is anyone aware of a guide to writing service interceptors? I have the REST API Documentation which has a small section, but really looking for information on what references I need to include, how to setup the development environment, any actions such as user authentication that need to be completed?
A HelloWorld interceptor tutorial that goes through these would be so helpful if anyone has one...
Hi Simon,
I just wanted to chime in and say that I would be very interested in this as well!! We have at least one fairly immediate situation where a service interceptor might be very helpful.
Thanks,
David
From: Tessitura Technical Forum [mailto:forums-technical@tessituranetwork.com] On Behalf Of Simon Davidson Sent: Wednesday, August 29, 2012 1:53 AM To: David Frederick Subject: [Tessitura Technical Forum] Service Interceptor Guide
This message was sent automatically to you by www.tessituranetwork.com because you subscribed to the Tessitura Technical Forum. You may reply to this message to post to the Technical forum or visit the site to search, read and post to the forums. In the interest of keeping the forum posts from becoming cluttered, we encourage you to delete previous message text from your reply before sending. Thank you!
Hello - I'd like to third that request!
Me too please! :)
We are working on having a few plug-in examples and some basic getting started level documentation ready to go along with the 11.0.4 release coming out soon.
That's great news!
Any planned release dates for 11.04 yet? :-)
That's great Ron! Thanks for the update...
Scoll to page 36 in this PDF:
http://www.tessituranetwork.com/tlcc/2012/PDFs/03-B_Version_11_Alchemy.pdf
for the slideshow from Jon Ballinger's presentation on Interceptors from TLCC2012. It lacks some key details but it's a start.
RE: the "Plugin Layer": To find it, do a search for all the 'plugins' folders on your Tessitura Services server. Each service folder has its own 'plugins' subfolder, containing the 'PluginConfig.xml' file. Interceptor config XML code goes in between the tags <PluginConfigs> and </PluginConfigs> .
Now if we could find some docs on developing and loading a Tessitura dll assembly in a language like vb.NET, we'd be in business. Anybody got an example?
Here's a text version of the Constituent plugin configuration image from the TLCC presentation, for cut/paste purposes (save you a few keystrokes, maybe):
<PluginConfig> <UriMarch>Constituents/Search/* </UriMarch> <Verb>Get </Verb> <FullPluginName>ConstituentService.Search</FullPluginName> <PluginPlacement>POST</PluginPlacement></PluginConfig>
The other plugin configs follow the same XML format.
I hope this helps somehow . . . .
Hi Ron,
Has the service interceptor examples and documentation you referred to been posted? I didn't see it in the 11.0.4 documentation and haven't been able to find it.
Thanks,David
Hi Everyone,
After much turmoil we finally managed to implement a “Hello world” interceptor that just writes a text file to hard drive. I hope it helps someone.
1. Start a new class library project in VS and name it TestPluginCSharp.
2. Copy Tessitura.Services.Common.Interceptor.Client.dll from your Tessitura service (the one that you are building plug-in for e.g. ConstituentService) bin folder to your new class library bin folder and add project reference to it.
3. Add a class named TestPluginCSharp and add the following code:
using Tessitura.Services.Common.Interceptor.Client;
namespace TestPluginCSharp
{
public class TestPluginCSharp
public static PluginData Operation(PluginData pluginData)
//you'll need the folder set up somewhere on the server for your test file
System.IO.File.WriteAllText(@"C:\Test\test.txt", "Howdy!");
return pluginData;
}
4. Build your project
5. Copy TestPluginCSharp.dll from bin\Debug folder to the service Plugins folder (e.g. ConstituentService\Plugins).
6. Open PluginConfig.xml from ConstituentService\Plugins in your VS and add:
<PluginConfigs>
<PluginConfig>
<UriMatch>Constituents/*</UriMatch>
<Verb>GET</Verb>
<FullPluginName>TestPluginCSharp.TestPluginCSharp</FullPluginName>
<PluginPlacement>PRE</PluginPlacement>
</PluginConfig>
</PluginConfigs>
Note: no preceding forward slash in UriMatch
7. Save PluginConfig
8. You may need to restart Application Pool for Tess in IIS
9. I also have EnablePlugins and ReloadPluginConfig keys set to true in Web.config of the service.
10. In Firefox start RESTClient. Set up OAuth Authorisation as per REST_API_Documentation.doc
11. Set call method to GET
12. Set to address of your service (e.g. https://your_server/Tess/ConstituentService/Constituents/60671061 ) and send request.
13. This should result in test.txt being written to the path at step 2.
Good luck!
Sergei Stenkov
Hi Sergei,
That's a great help, thanks very much!
I don't suppose you've experimented a bit further and tried to get information from the REST Service? So in your example, how you would get the consitutent id 60671061.
Thanks
Sergei
Thanks a lot for this information. We managed to get something working with a lot of trial an error, but this short list of steps will help us get rid of a lot of extra tasks that we did while we were trying to get things to work (ie. throwing punches in the dark). This is very helpful.
Fernando Margueirat Business Analyst The National Ballet of Canada 470 Queens Quay West Toronto, Ontario M5V 3K4 P: 416 345 9686 x453 F: 416 345 8323
From: Tessitura Technical Forum [mailto:forums-technical@tessituranetwork.com] On Behalf Of Sergei Stenkov Sent: October-25-12 1:19 AM To: Fernando Margueirat Subject: Re: [Tessitura Technical Forum] Service Interceptor Guide
From: Simon Davidson <bounce-simondavidson9902@tessituranetwork.com> Sent: 8/29/2012 3:45:10 AM
It's all baby steps for me with interceptors. You could search for it I think. When I try executing this search through the REST client it brings back ConstituentSummary containing the ID:
https://tessxxx.xxx.com/Tess/ConstituentService/Constituents/Search?q=""&type=basic&constituentGroups=individuals&ln=stenkov
... and a bit of result:
Hi All,
Good day.
Is there any one have a clear ideas about how to set up the plugin configurations?
it is not hard to write .net code, it is not hard to test the .net code.
But finally when I put the custom plugins into the REST, it is very hard to figure out where when and what is happening.
from user point view, things are clear, like 1, if someone already had a mobile in the system, stop insert same mobile number, 2, or stop same email address entry.
The REST API document is missing the detail how client calls REST.
also there is something not in the document. what is RegEx? like this:
2014-12-09 16:30:44.3753|Debug|Verb and Placement matched but RegEx for URI match '^CRM/Constituents/[^/]*/Snapshot(/)?$' didn't match the actual URI 'ReferenceData/SystemDefaults/Summary'.
I can see the REST structure is very complicated.
is there some documents about this part of REST?
have fun
Ben
HI All,
is there anyone can tell me why same codes worked with "POST" method (insert) didn't work with "PUT" method(update)?
is there something different inside REST between "POST" URI and "PUT" URI?
Thank you very much for your help.
namespace MTC_REST.TessituraPlugins.ConstituentService{ public class DupEmailLoginPreventionSnapshot { public static PluginData Operation(PluginData input) { string update = string.Empty; string insert = string.Empty; update = @"PUT"; insert = @"POST"; if (input.Verb == insert) { var constituent = SerializationHelper.Deserialize<ConstituentSnapshot>(input.Data); var myEmail = input.Data; if (myEmail.Name.ToString().ToLower().Contains("electronicaddress")) { string EmailAddress = string.Empty; int mycheck = 0; EmailAddress = constituent.ElectronicAddress.Address.ToString(); mycheck = checkEmail(EmailAddress); if (mycheck > 0) { throw new PluginValidationException("Email Address is already under another account " + mycheck.ToString() + ". It is not allowed for this account."); } } return input; } else if (input.Verb == update)///this part codes have the same logic but it never hit by plugin. { var constituentUpdate = SerializationHelper.Deserialize<ConstituentSnapshot>(input.Data); var myEmailUpdate = input.Data; if (myEmailUpdate.Name.ToString().ToLower().Contains("electronicaddress")) { string EmailAddress = string.Empty; int mycheck = 0; EmailAddress = constituentUpdate.ElectronicAddress.Address.ToString(); mycheck = checkEmail(EmailAddress); if (mycheck > 0) { throw new PluginValidationException("Email Address is already under another account " + mycheck.ToString() + ". It is not allowed for this account."); } } return input; } else { return input; } } public static int checkEmail(string emailaddress) { string tmp = string.Empty; int myreturn = 0; var sqlCommandHelper = new SqlCommandHelper(); var sqlStatement = "dbo.LP_MTC_INTERCEPTION_STOP_EMAIL_LOGIN_DUP"; var parameters = new Dictionary<string, string>(); parameters.Add("@EMAILADDRESS", emailaddress); System.Data.DataSet ds= sqlCommandHelper.ExecuteSqlCommandReturnDataSet(sqlStatement, parameters, true); System.Data.DataTable tb = ds.Tables[0]; if (tb.Rows.Count>0) { tmp = tb.Rows[0]["customer_no"].ToString(); } if (tmp.Trim().Length > 0) { myreturn =Convert.ToInt32( tmp.Trim().ToString()); } return myreturn; } }}