<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://communitytest.tessitura.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Community Docs Wiki</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation</link><description>Wiki for creating community documentation.</description><dc:language>en-US</dc:language><generator>Telligent Community 12 Non-Production</generator><item><title>Community Developer Documentation</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation</link><pubDate>Tue, 14 Oct 2025 19:53:56 GMT</pubDate><guid isPermaLink="false">fd08b0f2-65fa-4b2b-916a-cce3e88b61d0:0df77497-ef81-4954-8d09-7486fbfc1ef5</guid><dc:creator>Todd Lantry (he/him)</dc:creator><description>Current Revision posted to Community Docs Wiki by Todd Lantry (he/him) on 10/14/2025 7:53:56 PM&lt;br /&gt;
&lt;p&gt;Use this space to write and share documentation on Tessitura functionality that doesn&amp;#39;t already exist, but you would have found useful for one of your own projects.&lt;/p&gt;
&lt;p&gt;In &lt;a title="the developer resources page describing slack and providing a form to get access" href="https://www.tessituranetwork.com/devs#community" rel="noopener noreferrer" target="_blank"&gt;Slack&lt;/a&gt;, you can summon a link to this page with the command &lt;code&gt;!wiki&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;...&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>The Secret Life of HTML Templates</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation/790/the-secret-life-of-html-templates</link><pubDate>Thu, 11 Apr 2024 18:45:32 GMT</pubDate><guid isPermaLink="false">fd08b0f2-65fa-4b2b-916a-cce3e88b61d0:6aa35c30-07ae-4c3a-b10f-0acfb6040cab</guid><dc:creator>Nick Reilingh</dc:creator><description>Current Revision posted to Community Docs Wiki by Nick Reilingh on 4/11/2024 6:45:32 PM&lt;br /&gt;
&lt;blockquote&gt;
&lt;p&gt;or: How I Learned to Stop Worrying and Just Write HTML Templates&lt;/p&gt;
&lt;p&gt;or: HTML Templates: The Missing Manual&lt;/p&gt;
&lt;p&gt;or: The HTML Templates documentation they&amp;nbsp;&lt;em&gt;don&amp;#39;t&lt;/em&gt; want you to know about!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This article aims to explain the differences between the Razor template syntax used in Tessitura HTML Templates and the syntax that you might see used in training courses&amp;nbsp;for Razor Pages in ASP.NET Core/MVC web applications. At present, the Tessitura documentation only scratches the surface of what is available syntactically, and doesn&amp;#39;t really attempt to explain how&amp;nbsp;HTML Templates are implemented.&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Tessitura&lt;/td&gt;
&lt;td&gt;v15.1&lt;/td&gt;
&lt;td&gt;v16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Razor&lt;/td&gt;
&lt;td&gt;ASP.NET MVC 3?&lt;/td&gt;
&lt;td&gt;?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C#&lt;/td&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;td&gt;6.0?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RazorEngine&lt;/td&gt;
&lt;td&gt;3.10&lt;/td&gt;
&lt;td&gt;?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="mcetoc_1f6o9tpq90"&gt;The Big Secret&lt;/h2&gt;
&lt;p&gt;HTML Templates are rendered using an Apache-licensed, open-source project called &lt;a title="Documentation site for RazorEngine" href="http://antaris.github.io/RazorEngine/" rel="noopener noreferrer" target="_blank"&gt;RazorEngine&lt;/a&gt;, which is available &lt;a title="GitHub repo for Antaris/RazorEngine" href="https://github.com/Antaris/RazorEngine" rel="noopener noreferrer" target="_blank"&gt;on GitHub&lt;/a&gt;. To&amp;nbsp;summarize the &lt;a title="About Razor and its syntax" href="https://antaris.github.io/RazorEngine/AboutRazor.html" rel="noopener noreferrer" target="_blank"&gt;RazorEngine documentation&lt;/a&gt;, RazorEngine is a framework&amp;nbsp;which consumes the Razor parser -- as is ASP.NET MVC. There is a difference between Razor&amp;#39;s syntax and special features provided by these frameworks. RazorEngine only shares its syntax with other implementations like ASP.NET MVC. This is why convenience methods like &lt;code&gt;@Html.Raw()&lt;/code&gt; (often seen in web results about Razor Pages) do not work in HTML templates -- the &lt;code&gt;@Html&lt;/code&gt; helper is a &lt;a title="HtmlHelper Class" href="https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.htmlhelper?view=aspnet-mvc-5.2" rel="noopener noreferrer" target="_blank"&gt;class&lt;/a&gt; specifically implemented by the ASP.NET MVC framework. (RazorEngine instead has &lt;code&gt;@Raw()&lt;/code&gt; built-in to provide the &lt;a title="Encoding Values in RazorEngine" href="https://antaris.github.io/RazorEngine/Encoding.html" rel="noopener noreferrer" target="_blank"&gt;same functionality&lt;/a&gt;.) Reading the &lt;a href="https://antaris.github.io/RazorEngine/index.html" rel="noopener noreferrer" target="_blank"&gt;RazorEngine documentation&lt;/a&gt; can be informative. Tessitura appears to implement version 3.10 of RazorEngine.&lt;/p&gt;
&lt;p&gt;The fundamentals of how Razor operates still apply. The Razor syntax parser converts a .cshtml template into a C# &lt;code&gt;Execute()&lt;/code&gt; method on a generated class, which, when invoked, has access to the provided model and returns a string.&lt;/p&gt;
&lt;h2 id="mcetoc_1f6oeo60f1"&gt;Assorted Syntactic Tips and Tricks&lt;/h2&gt;
&lt;p&gt;The version of C# available in Tessitura HTML Templates in Tessitura V15.1 is C# 5.0. In Tessitura V16, Razor templates will support C# 9.0, giving them support for &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated" rel="noopener noreferrer" target="_blank"&gt;interpolated strings&lt;/a&gt; (C# 6.0), &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/local-functions" rel="noopener noreferrer" target="_blank"&gt;local functions&lt;/a&gt; (C# 7.0), and other features.&lt;/p&gt;
&lt;p&gt;The version of Razor available in Tessitura HTML Templates in V15.1 is &amp;quot;Razor 3&amp;quot;, which is versioned as such because it shipped with ASP.NET MVC 3. This means technically, the &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/mvc/views/razor" rel="noopener noreferrer" target="_blank"&gt;syntax documentation linked in the Tessitura docs&lt;/a&gt; is&amp;nbsp;WAY too new for what is actually in use. This explains why &amp;quot;templating methods&amp;quot; described in these docs are not functional in Tessitura HTML Templates.&lt;/p&gt;
&lt;p&gt;Razor supports the use of a &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-5.0#functions" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;@functions&lt;/code&gt; directive&lt;/a&gt;, which gives you a&amp;nbsp;space to define additional members (methods and properties) to be added to the&amp;nbsp;generated class. Curiously, the HTML Templates editor does not syntax-color code inside of a &lt;code&gt;@functions&lt;/code&gt; directive.&lt;/p&gt;
&lt;pre&gt;@functions {&lt;br /&gt;    private string SOME_URL_CONSTANT = &amp;quot;https://example.com&amp;quot;;&lt;br /&gt;    private string LinkTag(string link) {&lt;br /&gt;        return &amp;quot;&amp;lt;a href=\&amp;quot;&amp;quot; + SOME_URL_CONSTANT + &amp;quot;\&amp;quot;&amp;gt;&amp;quot; + link + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;@Raw(LinkTag(&amp;quot;some text&amp;quot;))&lt;br /&gt;@* Outputs:&lt;br /&gt;&amp;lt;a href=&amp;quot;https://example.com&amp;quot;&amp;gt;some text&amp;lt;/a&amp;gt;&lt;br /&gt;*@&lt;/pre&gt;
&lt;p&gt;Methods are private because&amp;nbsp;the template&amp;#39;s execution is just another method in the same class.&lt;/p&gt;
&lt;p&gt;The version of Razor used in RazorEngine 3.10 (Razor 3, shipped in ASP.NET MVC 3) also supports the &lt;code&gt;@helper&lt;/code&gt; directive, which allows you to define a kind of function that contains markup, just like the rest of the template. This allows for easy reuse of template code. Helpers were &lt;a href="https://github.com/aspnet/Razor/issues/281" rel="noopener noreferrer" target="_blank"&gt;removed in&amp;nbsp;Razor 4&lt;/a&gt;, &lt;a href="https://www.c-sharpcorner.com/article/html-helpers-in-asp-net-mvc-5/" rel="noopener noreferrer" target="_blank"&gt;reappear in ASP.NET MVC 5&lt;/a&gt;,&amp;nbsp;were removed again in &lt;a href="https://github.com/dotnet/aspnetcore/issues/5110" rel="noopener noreferrer" target="_blank"&gt;ASP.NET Core&lt;/a&gt;,&amp;nbsp;and finally &lt;a href="https://github.com/dotnet/aspnetcore-tooling/pull/334" rel="noopener noreferrer" target="_blank"&gt;code blocks were enhanced to allow for inline markup in functions&lt;/a&gt;, without the need for the &lt;code&gt;@helper&lt;/code&gt; directive. Helpers can be used as &amp;quot;templating methods&amp;quot; which are otherwise unavailable as described above.&lt;/p&gt;
&lt;pre&gt;@helper BoldMe(string content) {&lt;br /&gt;    &amp;lt;b&amp;gt;@content&amp;lt;/b&amp;gt;&lt;br /&gt;}&lt;br /&gt;@BoldMe(&amp;quot;look at me, I&amp;#39;m bold!&amp;quot;)&lt;br /&gt;@* Outputs:&lt;br /&gt;&amp;lt;b&amp;gt;look at me, I&amp;amp;#39;m bold!&amp;lt;/b&amp;gt;&lt;br /&gt;*@&lt;/pre&gt;
&lt;p&gt;The output of the helper correctly writes literal or encoded HTML like the rest of the template does.&lt;/p&gt;
&lt;p&gt;A regular function can be made to behave like a templating method by defining it with a void type and then calling the imperative &lt;code&gt;WriteLiteral()&lt;/code&gt; and &lt;code&gt;Write()&lt;/code&gt; functions, which is basically what a Razor template compiles to in the first place. Then this function can be called inside a code block (&lt;code&gt;@{}&lt;/code&gt;) to inject its output at that location.&lt;/p&gt;
&lt;pre&gt;@functions {&lt;br /&gt;    private void DIYRenderFunction(string content) {&lt;br /&gt;        WriteLiteral(&amp;quot;&amp;lt;p&amp;gt;&amp;quot;);&lt;br /&gt;        Write(content);&lt;br /&gt;        WriteLiteral(&amp;quot;&amp;lt;/p&amp;gt;&amp;quot;);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;@{ DIYRenderFunction(&amp;quot;here are my paragraph tags &amp;amp; encoded content&amp;quot;); }&lt;br /&gt;@* Outputs:&lt;br /&gt;&amp;lt;p&amp;gt;here are my paragraph tags &amp;amp;amp; encoded content&amp;lt;/p&amp;gt;&lt;br /&gt;*@&lt;/pre&gt;
&lt;p&gt;Helpers can be passed into one another as arguments if your types are correct. The defined helper token refers to a method which returns a&amp;nbsp;&lt;a title="RazorEngine TemplateWriter type" href="https://antaris.github.io/RazorEngine/references/razorengine-templating-templatewriter.html" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;RazorEngine.Templating.TemplateWriter&lt;/code&gt; type&lt;/a&gt;, which is what writes template content as Literal or HTML-encoded inline. This type has a&amp;nbsp;&lt;code&gt;.ToString()&lt;/code&gt;&amp;nbsp;method which can be used to cast to a string type at the point of use, but this is often non-optimal because if the helper template outputs HTML (which it often will), you will need to&amp;nbsp;&lt;code&gt;@Raw()&lt;/code&gt;&amp;nbsp;the result when using it in another helper template.&amp;nbsp;Luckily, C# supports the &lt;code&gt;dynamic&lt;/code&gt; keyword in a type signature, which means you can pass in either a &lt;code&gt;TemplateWriter&lt;/code&gt; or a raw &lt;code&gt;string&lt;/code&gt; and RazorEngine will do the right thing at runtime:&lt;/p&gt;
&lt;pre&gt;@helper ItalicizeMe(dynamic content) {&lt;br /&gt;    &amp;lt;i&amp;gt;@content&amp;lt;/i&amp;gt;&lt;br /&gt;}&lt;br /&gt;@helper BoldMe(dynamic content) {&lt;br /&gt;    &amp;lt;b&amp;gt;@content&amp;lt;/b&amp;gt;&lt;br /&gt;}&lt;br /&gt;@ItalicizeMe(BoldMe(&amp;quot;I&amp;#39;m bold, AND italic!&amp;quot;))&lt;br /&gt;@ItalicizeMe(&amp;quot;I&amp;#39;m only italic!&amp;quot;)&lt;br /&gt;@* Outputs:&lt;br /&gt;    &amp;lt;i&amp;gt;    &amp;lt;b&amp;gt;I&amp;amp;#39;m bold, AND italic!&amp;lt;/b&amp;gt;&lt;br /&gt;&amp;lt;/i&amp;gt;&lt;br /&gt;    &amp;lt;i&amp;gt;I&amp;amp;#39;m only italic!&amp;lt;/i&amp;gt;&lt;br /&gt;*@&lt;/pre&gt;
&lt;p&gt;You can also compose helpers by nesting them inside each other&amp;#39;s templates, since helpers and &lt;code&gt;@functions&lt;/code&gt;&amp;nbsp;directives share the same scope (the generated class). In contrast, variables declared in a code block are local to the render method, so while they can be referenced in the template itself, they cannot be referenced in other class methods like helpers and functions.&lt;/p&gt;
&lt;p&gt;A special syntax exists in Razor 3 for raw text. This is necessary when using helpers without surrounding tags. Information here: &lt;a href="https://weblogs.asp.net/scottgu/asp-net-mvc-3-razor-s-and-lt-text-gt-syntax" rel="noopener noreferrer" target="_blank"&gt;ASP.NET MVC 3: Razor&amp;rsquo;s @: and &amp;lt;text&amp;gt; syntax&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, with all of these tools in our toolbox, only one question remains... Can we avoid writing inline styles?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: c#, HTML Templates, razor&lt;/div&gt;
</description></item><item><title>Browser-based custom screen auth token API authentication</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation/813/browser-based-custom-screen-auth-token-api-authentication</link><pubDate>Thu, 07 Mar 2024 17:11:00 GMT</pubDate><guid isPermaLink="false">fd08b0f2-65fa-4b2b-916a-cce3e88b61d0:5cd0acf0-1403-4323-b451-22deaf94c67e</guid><dc:creator>Nick Reilingh</dc:creator><description>Current Revision posted to Community Docs Wiki by Nick Reilingh on 3/7/2024 5:11:00 PM&lt;br /&gt;
&lt;p&gt;Per the &lt;a href="https://www.tessitura.com/passthrough?itemUri=%2FDocuments%2FCustomizations%2FTessitura_Custom_Screens_v150.pdf" rel="noopener noreferrer" target="_blank"&gt;Tessitura Custom Screens (v15.0+)&lt;/a&gt; documentation, browser-based custom screens can be requested with an &lt;code&gt;&amp;lt;&amp;lt;auth&amp;gt;&amp;gt;&lt;/code&gt;&amp;nbsp;token passed as a URL parameter. This token represents the Tessitura Client&amp;#39;s currently logged-in user&amp;#39;s application session, and can be used to authenticate API requests with the user&amp;#39;s security context.&lt;/p&gt;
&lt;p&gt;This style of session token authentication is far preferable to the alternative, where the web application providing the browser-based custom screen must authenticate to the API as itself, be granted access to a maximum resource scope, and implement resource security on behalf of the API services based on the current user&amp;#39;s usergroup. To do this securely, the web application must also request the user to log into itself, inside of a custom tab inside a Tessitura client app session that the user has already authenticated to. This complicates security implementation and the double-login requirement makes for bad UX.&lt;/p&gt;
&lt;p&gt;To make use of this method of authentication, the custom web application can be largely if not entirely stateless. The only tradeoff is that API resource permissions must be granted to the Tessitura User Groups that the users operate under. In the case of custom tabs/screens, it would be advisable to bundle appropriate API permissions with access to the custom screen security object itself.&lt;/p&gt;
&lt;p&gt;The authentication flow looks something like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;TR_CUSTOM_TAB is configured with an entry for https://your.app/?token=&amp;lt;&amp;lt;auth&amp;gt;&amp;gt;, and usergroups are granted permission to this custom tab and to any API Resources that will need to be accessed (logging in as an Admin group circumvents this requirement and can be useful for testing).&lt;/li&gt;
&lt;li&gt;User opens the custom tab. Custom web app receives a GET request from the embedded browser containing the auth token in the URL.&lt;/li&gt;
&lt;li&gt;Web app must parse URL parameters obtaining the token value, decoding any URL %-encoding which is likely to occur in the auth token parameter. Most libraries and frameworks will do this automatically.&lt;/li&gt;
&lt;li&gt;Web app can now make a request to the Tessitura API. Instead of&amp;nbsp;using traditional basic auth (Username:Usergroup:Location:Password), the request can simply provide a token authorization header as follows: &lt;code&gt;Authorization: Token &amp;lt;token&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Depending on the specific needs of the web app, it is likely advisable for the token to be returned back to the frontend as a session cookie, since the URL parameter provided by Tessitura is only guaranteed when the custom screen is loaded for the first time (or reloaded). Any navigations the user does from within the custom screen (e.g. by clicking an &amp;lt;a&amp;gt; tag) will navigate to whatever&amp;nbsp;href has been provided by the web app. An app developer may&amp;nbsp;opt to provide the auth token in all such hrefs instead of using the session cookie approach, but this is up to personal taste.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: Authentication, authorization, custom screens, REST API&lt;/div&gt;
</description></item><item><title>New to Using Tessitura in a Software Developer Role? Start here!</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation/806/new-to-using-tessitura-in-a-software-developer-role-start-here</link><pubDate>Wed, 22 Mar 2023 19:17:43 GMT</pubDate><guid isPermaLink="false">fd08b0f2-65fa-4b2b-916a-cce3e88b61d0:099c55c8-142a-4f8e-98ae-43b7399f8eb3</guid><dc:creator>Marcus Johnson</dc:creator><description>Current Revision posted to Community Docs Wiki by Marcus Johnson on 3/22/2023 7:17:43 PM&lt;br /&gt;
&lt;p&gt;&lt;span&gt;&lt;img style="display:block;margin-left:auto;margin-right:auto;" alt=" " height="252" src="/resized-image/__size/320x240/__key/communityserver-wikis-components-files/00-00-00-01-13/It_2700_s_5F00_dangerous_5F00_to_5F00_go_5F00_alone_21005F00_Take_5F00_this_2E00_.png" width="288" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Are you a developer looking to build Tessitura-powered applications but don&amp;#39;t know where to start? Look no further! Our documentation space is here to help you get started with our easy-to-follow getting started guide. With links to the &lt;a href="https://www.tessituranetwork.com/Support/Documentation/API"&gt;API Resources&lt;/a&gt; page, &lt;a href="https://www.tessituranetwork.com/en/Files/Misc/Links/REST-API-Help-v15_1"&gt;REST API Help Documentation&lt;/a&gt;, &lt;a href="https://www.tessituranetwork.com/Files/Docs/API/SOAP-API-Guide-v151"&gt;SOAP API Guide v15&lt;/a&gt; and the &lt;a href="https://www.tessituranetwork.com/Files/Docs/API/SOAP-to-REST"&gt;SOAP to REST Transition Guide&lt;/a&gt;, we have all the resources you need to start building your Tessitura-powered applications.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1gs5adujn0"&gt;Developer Basics&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Registered Developers have access to Tessitura documentation including API help pages. application documentation and best practice advice.&amp;nbsp; If the company has access, they may register an account under it; if not,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href="https://www.tessituranetwork.com/Support/Resources/Developer"&gt;request access&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a title="Access the Developer group and forum" href="//topical_groups/developers" rel="noopener noreferrer" target="_blank"&gt;Community forums and Topical community group&lt;/a&gt;&amp;nbsp;&amp;ndash; Get answers today from other Tessitura developers in the forums and engage with other developers on Developer User Group virtual meetups.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tn-webshare.slack.com/" rel="noopener noreferrer" target="_blank"&gt;Slack Channel&lt;/a&gt;&amp;nbsp;&amp;ndash; Have a question? &amp;nbsp;Chat with other developers about the Tessitura API, web development, SQL, HTML Templates, Community Source projects, and more.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bitbucket.org/TN_WebShare/profile/repositories" rel="noopener noreferrer" target="_blank"&gt;Shared Code Repository&lt;/a&gt;&amp;nbsp;&amp;ndash; Stumped for a solution? &amp;nbsp;Interested to see how others have solved similar problems? Take a peek at projects other developers have chosen to share in our community&amp;#39;s shared code repository.&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1gs5ag8ar1"&gt;Additional Resources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Videos detailing the basics of the Tessitura API and what you can do with them.
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.tessituranetwork.com/Items/Videos/Training/Introduction_to_API"&gt;Introduction to Tessitura and the API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tessituranetwork.com/Items/Videos/Training/REST_API_Intro"&gt;Introduction to the Tessitura REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tessituranetwork.com/Items/Videos/Training/REST_API_Security"&gt;Tessitura REST API Security and Authentication&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tessituranetwork.com/Files/Docs/API/SOAP-API-Guide-v151"&gt;SOAP API Guide v15&lt;/a&gt;&amp;nbsp;&amp;ndash; Full listing of methods available via the Tessitura SOAP API.&lt;/li&gt;
&lt;/ul&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Show Information from a Custom Data Service</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation/805/show-information-from-a-custom-data-service</link><pubDate>Wed, 08 Mar 2023 16:30:53 GMT</pubDate><guid isPermaLink="false">fd08b0f2-65fa-4b2b-916a-cce3e88b61d0:5d88c84d-819d-4c22-be71-2c11f8342a72</guid><dc:creator>John A. Moskal II</dc:creator><description>Current Revision posted to Community Docs Wiki by John A. Moskal II on 3/8/2023 4:30:53 PM&lt;br /&gt;
&lt;p&gt;This is an example of fetching and displaying in an HTML Template e-mail, arbitrary data from a custom Data Service Table/View stored in &lt;span style="font-family:courier new, courier;"&gt;TR_DATASERVICE_TABLES&lt;/span&gt;.&amp;nbsp; Updates/edits welcome.&lt;/p&gt;
&lt;p&gt;In this example, we reference a local database view &lt;span style="font-family:courier new, courier;"&gt;LVXS_CP_ORDER_PRIMARY_ORG&lt;/span&gt; with the name &lt;span style="font-family:courier new, courier;"&gt;CPOrdersPrimaryOrg&lt;/span&gt; and unique key column of &lt;span style="font-family:courier new, courier;"&gt;order_no&lt;/span&gt;.&amp;nbsp; Sample reason this might be needed is in a consortium environment where orders might feature products from multiple organizations and there is a need to determine a primary/joint style/content template for the e-mail.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="html"&gt;@* Sample get single custom dataservice element based on ID *@

@* Use Newtonsoft.Json for parsing *@
@using Newtonsoft.Json;
@using Tessitura.Services.Common.Client.Utils;

@* Define object CPOrderOrg for properly named and typed results *@
@functions
{       
    public class CPOrderOrg
    {
        [JsonPropertyAttribute(&amp;quot;organization&amp;quot;)]
        public int OrgId;
        [JsonPropertyAttribute(&amp;quot;org_desc&amp;quot;)]
        public string OrgDesc;
    }
}

@* Define URL for and get data from custom dataservice entry CPOrdersPrimaryOrg based on the Order ID; single object results *@
@{
    @* Order ID is provided in the Order Confirmations template type *@
    var customURL = &amp;quot;Custom/CPOrdersPrimaryOrg/&amp;quot; + Model.OrderProductView.Id;
    var orderPrimaryOrg = Model.RestClient
        .AtUrl(customURL)
        .WithContentType(ContentType.Json)
        .Get&amp;lt;CPOrderOrg&amp;gt;()
        .ResponseObject;
}

@* Output results *@
&amp;lt;p&amp;gt;
    @orderPrimaryOrg.OrgId
    @orderPrimaryOrg.OrgDesc
&amp;lt;/p&amp;gt;
&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: HTML Templates, razor, REST API&lt;/div&gt;
</description></item><item><title>Show Information from a Custom Data Service</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation/805/show-information-from-a-custom-data-service/revision/1</link><pubDate>Wed, 08 Mar 2023 16:29:45 GMT</pubDate><guid isPermaLink="false">fd08b0f2-65fa-4b2b-916a-cce3e88b61d0:5d88c84d-819d-4c22-be71-2c11f8342a72</guid><dc:creator>John A. Moskal II</dc:creator><description>Revision 1 posted to Community Docs Wiki by John A. Moskal II on 3/8/2023 4:29:45 PM&lt;br /&gt;
&lt;p&gt;This is an example of fetching and displaying in an HTML Template e-mail, arbitrary data from a custom Data Service Table/View stored in &lt;span style="font-family:courier new, courier;"&gt;TR_DATASERVICE_TABLES&lt;/span&gt;.&amp;nbsp; Updates/edits welcome.&lt;/p&gt;
&lt;p&gt;In this example, we reference a local database view &lt;span style="font-family:courier new, courier;"&gt;LVXS_CP_ORDER_PRIMARY_ORG&lt;/span&gt; with the name &lt;span style="font-family:courier new, courier;"&gt;CPOrdersPrimaryOrg&lt;/span&gt; and unique key column of &lt;span style="font-family:courier new, courier;"&gt;order_no&lt;/span&gt;.&amp;nbsp; Sample reason this might be needed is in a consortium environment where orders might feature products from multiple organizations and there is a need to determine a primary/joint style/content template for the e-mail.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;@* Sample get single custom dataservice element based on ID *@

@* Use Newtonsoft.Json for parsing *@
@using Newtonsoft.Json;
@using Tessitura.Services.Common.Client.Utils;

@* Define object CPOrderOrg for properly named and typed results *@
@functions
{       
    public class CPOrderOrg
    {
        [JsonPropertyAttribute(&amp;quot;organization&amp;quot;)]
        public int OrgId;
        [JsonPropertyAttribute(&amp;quot;org_desc&amp;quot;)]
        public string OrgDesc;
    }
}

@* Define URL for and get data from custom dataservice entry CPOrdersPrimaryOrg based on the Order ID; single object results *@
@{
    @* Order ID is provided in the Order Confirmations template type *@
    var customURL = &amp;quot;Custom/CPOrdersPrimaryOrg/&amp;quot; + Model.OrderProductView.Id;
    var orderPrimaryOrg = Model.RestClient
        .AtUrl(customURL)
        .WithContentType(ContentType.Json)
        .Get&amp;lt;CPOrderOrg&amp;gt;()
        .ResponseObject;
}

@* Output results *@
&amp;lt;p&amp;gt;
    @orderPrimaryOrg.OrgId
    @orderPrimaryOrg.OrgDesc
&amp;lt;/p&amp;gt;
&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: HTML Templates, razor, REST API&lt;/div&gt;
</description></item><item><title>Measure and improve SQL query performance</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation/804/measure-and-improve-sql-query-performance</link><pubDate>Thu, 02 Feb 2023 04:06:50 GMT</pubDate><guid isPermaLink="false">fd08b0f2-65fa-4b2b-916a-cce3e88b61d0:9d41c095-a5e0-4485-b646-da895846d434</guid><dc:creator>James Murty</dc:creator><description>Current Revision posted to Community Docs Wiki by James Murty on 2/2/2023 4:06:50 AM&lt;br /&gt;
&lt;p&gt;Some tips for writing custom database queries or stored procedures that perform well, or&amp;nbsp;improving the performance of existing&amp;nbsp;SQL.&lt;/p&gt;
&lt;p&gt;This page was inspired and informed by &lt;a href="https://tn-webshare.slack.com/archives/C02GE71RP/p1675270129492499"&gt;a thread&lt;/a&gt; in the Tessitura Network Slack. Thanks to all the contributors to that thread.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;It can be difficult to evaluate the&amp;nbsp;how quick (or slow) queries&amp;nbsp;are when you run them in SSMS because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;there can be a significant difference between the time to run a query (as reported&amp;nbsp;as SQL Server Execution time) versus the &amp;quot;clock&amp;quot; time to return the results (as shown at the bottom right of the window)&lt;/li&gt;
&lt;li&gt;query caching can skew results of&amp;nbsp;re-run queries&lt;/li&gt;
&lt;li&gt;general database load can affect timings, if you&amp;#39;re&amp;nbsp;writing queries on a live or actively used database (don&amp;#39;t do this, if you can help it)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Use these directives to&amp;nbsp;improve the quality and consistency of query metrics, though&amp;nbsp;they may not work on RAMP deployments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;DBCC DROPCLEANBUFFERS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;SET STATISTICS IO ON&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Change the final statement to `&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;SELECT 1;&lt;/span&gt;` to measure just the query time without returning data. If&amp;nbsp;this shows a significant difference in performance you are likely experiencing key lookups, try&amp;nbsp;gradually adding back the real SELECT statements to find the one(s) that are&amp;nbsp;slow. In all cases avoid returning * from tables, only return what you really need.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: performance, database, SQL&lt;/div&gt;
</description></item><item><title>Measure and improve SQL query performance</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation/804/measure-and-improve-sql-query-performance/revision/1</link><pubDate>Thu, 02 Feb 2023 04:05:13 GMT</pubDate><guid isPermaLink="false">fd08b0f2-65fa-4b2b-916a-cce3e88b61d0:9d41c095-a5e0-4485-b646-da895846d434</guid><dc:creator>James Murty</dc:creator><description>Revision 1 posted to Community Docs Wiki by James Murty on 2/2/2023 4:05:13 AM&lt;br /&gt;
&lt;p&gt;Some tips for writing custom database queries or stored procedures that perform well, or&amp;nbsp;improving the performance of existing&amp;nbsp;SQL.&lt;/p&gt;
&lt;p&gt;This page was inspired and informed by &lt;a href="https://tn-webshare.slack.com/archives/C02GE71RP/p1675270129492499"&gt;a thread&lt;/a&gt; in the Tessitura Network Slack. Thanks to all the contributors to that thread.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;It can be difficult to evaluate the&amp;nbsp;how quick (or slow) queries&amp;nbsp;are when you run them in SSMS because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;there can be a significant difference between the time to run a query (as reported&amp;nbsp;as SQL Server Execution time) versus the &amp;quot;clock&amp;quot; time to return the results (as shown at the bottom right of the window)&lt;/li&gt;
&lt;li&gt;query caching can skew results of&amp;nbsp;re-run queries&lt;/li&gt;
&lt;li&gt;general database load can affect timings, if you&amp;#39;re&amp;nbsp;writing queries on a live or actively used database (don&amp;#39;t do this, if you can help it)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Use these directives to&amp;nbsp;improve the quality and consistency of query metrics, though&amp;nbsp;they may not work on RAMP deployments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;DBCC DROPCLEANBUFFERS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;SET STATISTICS IO ON&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Change the final statement to `&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;SELECT 1;&lt;/span&gt;` to measure just the query time without returning data. If&amp;nbsp;this shows a significant difference in performance you are likely experiencing key lookups, try&amp;nbsp;gradually adding back the real SELECT statements to find the one(s) that are&amp;nbsp;slow. In all cases avoid returning * from tables, only return what you really need.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: performance, database, SQL&lt;/div&gt;
</description></item><item><title>Show information from a custom stored procedure</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation/801/show-information-from-a-custom-stored-procedure</link><pubDate>Mon, 05 Dec 2022 05:31:16 GMT</pubDate><guid isPermaLink="false">fd08b0f2-65fa-4b2b-916a-cce3e88b61d0:3db4dc4a-5991-4e1a-8955-873a5d0ba0ca</guid><dc:creator>James Murty</dc:creator><description>Current Revision posted to Community Docs Wiki by James Murty on 12/5/2022 5:31:16 AM&lt;br /&gt;
&lt;p&gt;This is a rough guide to fetching and displaying in an HTML Template email arbitrary data from a custom stored procedure via the&amp;nbsp;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;Custom/Execute&lt;/span&gt; REST API endpoint.&lt;/p&gt;
&lt;p&gt;NOTE: This may not be the best way to do things&amp;mdash;edits, additions, and improvements to this document are very welcome.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In this example, we use&amp;nbsp;a&amp;nbsp;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;CUSTOMER_ORDERS&lt;/span&gt;&amp;nbsp;stored procedure to include a summary of a constituent&amp;#39;s recent orders in a &lt;em&gt;Constituent Info&lt;/em&gt;&amp;nbsp;template.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@using Tessitura.Services.Common.Client.Utils;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@using Tessitura.Service.Client.CRM;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@using Tessitura.Service.Client.Custom;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@* Use Newtonsoft library to parse fields from JSON data *@&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@using Newtonsoft.Json;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&amp;nbsp; // Define an OrderInfo object to parse JSON data from fields returned by the&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// custom query to attributes of the correct type.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@functions {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;public class OrderInfo&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;[JsonPropertyAttribute("order_no")]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;public int OrderNo;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;[JsonPropertyAttribute("order_total")]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;public double OrderTotal;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;[JsonPropertyAttribute("last_update_dt")]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;public DateTime LastUpdate;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// Find orders that have been updated in the last 30 days&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;DateTime now = DateTime.Now;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;DateTime ordersFromDate = now.AddDays(-30);&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// Define request parameters for CUSTOMER_ORDERS custom stored procedure&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;LocalProcedureRequest localProcedureRequest = new LocalProcedureRequest&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;ProcedureName = &amp;quot;CUSTOMER_ORDERS&amp;quot;,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;ParameterValues = new ParameterValues&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// Constituent ID is made available in Constituent Info templates&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;new ParameterValue&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Name = &amp;quot;constituent_id&amp;quot;,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Value = Model.ConstituentSnapshot.Id.ToString()&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;},&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; new ParameterValue&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Name = &amp;quot;start_dt&amp;quot;,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Value = ordersFromDate.ToString(&amp;quot;yyyy-MM-dd&amp;quot;)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&amp;nbsp; };&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// Fetch data from stored procedure CUSTOMER_ORDERS via /Custom/Execute API&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// endpoint and parse JSON response data into a list of `OrderInfo` objects&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;var orders = Model.RestClient&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;.AtUrl(&amp;quot;Custom/Execute&amp;quot;)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// Request JSON data in response&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;.WithContentType(ContentType.Json)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// POST request, with defined types to (de)serialize req/resp data&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;.Post&amp;lt;LocalProcedureRequest, List&amp;lt;OrderInfo&amp;gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;(localProcedureRequest)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;.ResponseObject;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@*&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// Uncomment to see JSON response data in the HTML Template editor&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;pre&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@Raw(Newtonsoft.Json.JsonConvert.SerializeObject(&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@orders,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Newtonsoft.Json.Formatting.Indented&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;/pre&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;*@&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@if (orders.Count &amp;gt; 0)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;h1&amp;gt;Customer Orders&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@foreach (var order in orders)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;li&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@order.OrderNo -&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@order.OrderTotal.ToString(&amp;quot;C&amp;quot;) -&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@order.LastUpdate.ToString(&amp;quot;dd MMMM yyyy HH:mm tt&amp;quot;)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;p&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;TOTAL: @orders.Sum(o =&amp;gt; o.OrderTotal).ToString(&amp;quot;C&amp;quot;)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: razor, REST API&lt;/div&gt;
</description></item><item><title>Show information from a custom stored procedure</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation/801/show-information-from-a-custom-stored-procedure/revision/3</link><pubDate>Mon, 05 Dec 2022 05:28:00 GMT</pubDate><guid isPermaLink="false">fd08b0f2-65fa-4b2b-916a-cce3e88b61d0:3db4dc4a-5991-4e1a-8955-873a5d0ba0ca</guid><dc:creator>James Murty</dc:creator><description>Revision 3 posted to Community Docs Wiki by James Murty on 12/5/2022 5:28:00 AM&lt;br /&gt;
&lt;p&gt;This is a rough guide to fetching and displaying&amp;nbsp;arbitrary data from a custom stored procedure via the&amp;nbsp;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;Custom/Execute&lt;/span&gt; REST API endpoint.&lt;/p&gt;
&lt;p&gt;NOTE: This may not be the best way to do things&amp;mdash;edits, additions, and improvements to this document are very welcome.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In this example, we use&amp;nbsp;a&amp;nbsp;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;CUSTOMER_ORDERS&lt;/span&gt;&amp;nbsp;stored procedure to include a summary of a constituent&amp;#39;s recent orders in a &lt;em&gt;Constituent Info&lt;/em&gt;&amp;nbsp;template.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@using Tessitura.Services.Common.Client.Utils;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@using Tessitura.Service.Client.CRM;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@using Tessitura.Service.Client.Custom;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@* Use Newtonsoft library to parse fields from JSON data *@&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@using Newtonsoft.Json;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&amp;nbsp; // Define an OrderInfo object to parse JSON data from fields returned by the&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// custom query to attributes of the correct type.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@functions {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;public class OrderInfo&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;[JsonPropertyAttribute("order_no")]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;public int OrderNo;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;[JsonPropertyAttribute("order_total")]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;public double OrderTotal;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;[JsonPropertyAttribute("last_update_dt")]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;public DateTime LastUpdate;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// Find orders that have been updated in the last 30 days&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;DateTime now = DateTime.Now;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;DateTime ordersFromDate = now.AddDays(-30);&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// Define request parameters for CUSTOMER_ORDERS custom stored procedure&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;LocalProcedureRequest localProcedureRequest = new LocalProcedureRequest&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;ProcedureName = &amp;quot;CUSTOMER_ORDERS&amp;quot;,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;ParameterValues = new ParameterValues&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// Constituent ID is made available in Constituent Info templates&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;new ParameterValue&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Name = &amp;quot;constituent_id&amp;quot;,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Value = Model.ConstituentSnapshot.Id.ToString()&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;},&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; new ParameterValue&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Name = &amp;quot;start_dt&amp;quot;,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Value = ordersFromDate.ToString(&amp;quot;yyyy-MM-dd&amp;quot;)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&amp;nbsp; };&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// Fetch data from stored procedure CUSTOMER_ORDERS via /Custom/Execute API&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// endpoint and parse JSON response data into a list of `OrderInfo` objects&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;var orders = Model.RestClient&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;.AtUrl(&amp;quot;Custom/Execute&amp;quot;)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// Request JSON data in response&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;.WithContentType(ContentType.Json)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// POST request, with defined types to (de)serialize req/resp data&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;.Post&amp;lt;LocalProcedureRequest, List&amp;lt;OrderInfo&amp;gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;(localProcedureRequest)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;.ResponseObject;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@*&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// Uncomment to see JSON response data in the HTML Template editor&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;pre&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@Raw(Newtonsoft.Json.JsonConvert.SerializeObject(&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@orders,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Newtonsoft.Json.Formatting.Indented&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;/pre&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;*@&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@if (orders.Count &amp;gt; 0)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;h1&amp;gt;Customer Orders&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@foreach (var order in orders)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;li&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@order.OrderNo -&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@order.OrderTotal.ToString(&amp;quot;C&amp;quot;) -&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@order.LastUpdate.ToString(&amp;quot;dd MMMM yyyy HH:mm tt&amp;quot;)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;p&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;TOTAL: @orders.Sum(o =&amp;gt; o.OrderTotal).ToString(&amp;quot;C&amp;quot;)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: razor, REST API&lt;/div&gt;
</description></item><item><title>Show information from a custom stored procedure</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation/801/show-information-from-a-custom-stored-procedure/revision/2</link><pubDate>Mon, 05 Dec 2022 05:25:56 GMT</pubDate><guid isPermaLink="false">fd08b0f2-65fa-4b2b-916a-cce3e88b61d0:3db4dc4a-5991-4e1a-8955-873a5d0ba0ca</guid><dc:creator>James Murty</dc:creator><description>Revision 2 posted to Community Docs Wiki by James Murty on 12/5/2022 5:25:56 AM&lt;br /&gt;
&lt;p&gt;This is a rough guide to fetching and displaying&amp;nbsp;arbitrary data from a custom stored procedure via the&amp;nbsp;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;Custom/Execute&lt;/span&gt; REST API endpoint.&lt;/p&gt;
&lt;p&gt;NOTE: This may not be the best way to do things&amp;mdash;edits, additions, and improvements to this document are very welcome.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In this example, we use&amp;nbsp;a&amp;nbsp;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;CUSTOMER_ORDERS&lt;/span&gt;&amp;nbsp;stored procedure to include a summary of a constituent&amp;#39;s recent orders in a &lt;em&gt;Constituent Info&lt;/em&gt;&amp;nbsp;template.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@using Tessitura.Services.Common.Client.Utils;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@using Tessitura.Service.Client.CRM;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@using Tessitura.Service.Client.Custom;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@* Use Newtonsoft library to parse fields from JSON data *@&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@using Newtonsoft.Json;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&amp;nbsp; // Define an OrderInfo object to parse JSON data from fields returned by the&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// custom query to attributes of the correct type.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@functions {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;public class OrderInfo&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;[JsonPropertyAttribute("order_no")]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;public int OrderNo;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;[JsonPropertyAttribute("order_total")]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;public double OrderTotal;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;[JsonPropertyAttribute("last_update_dt")]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;public DateTime LastUpdate;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// Find orders that have been updated in the last 30 days&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;DateTime now = DateTime.Now;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;DateTime ordersFromDate = now.AddDays(-30);&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// Define request parameters for CUSTOMER_ORDERS custom stored procedure&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;LocalProcedureRequest localProcedureRequest = new LocalProcedureRequest&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;ProcedureName = &amp;quot;CUSTOMER_ORDERS&amp;quot;,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;ParameterValues = new ParameterValues&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// Constituent ID is made available in Constituent Info templates&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;new ParameterValue&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Name = &amp;quot;constituent_id&amp;quot;,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Value = Model.ConstituentSnapshot.Id.ToString()&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;},&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&amp;nbsp; &amp;nbsp; new ParameterValue&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Name = &amp;quot;start_dt&amp;quot;,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Value = ordersFromDate.ToString(&amp;quot;yyyy-MM-dd&amp;quot;)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&amp;nbsp; };&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// Fetch data from stored procedure CUSTOMER_ORDERS via /Custom/Execute API&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// endpoint and parse JSON response data into a list of `OrderInfo` objects&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;var orders = Model.RestClient&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;.AtUrl(&amp;quot;Custom/Execute&amp;quot;)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// Request JSON data in response&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;.WithContentType(ContentType.Json)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// POST request, with defined types to (de)serialize req/resp data&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;.Post&amp;lt;LocalProcedureRequest, List&amp;lt;OrderInfo&amp;gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;(localProcedureRequest)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;.ResponseObject;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@*&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;// Uncomment to see JSON response data in the HTML Template editor&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;pre&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@Raw(Newtonsoft.Json.JsonConvert.SerializeObject(&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@orders,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Newtonsoft.Json.Formatting.Indented&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;));&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;/pre&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;*@&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;@if (orders.Count &amp;gt; 0)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;h1&amp;gt;Customer Orders&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@foreach (var order in orders)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;li&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@order.OrderNo -&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@order.OrderTotal.ToString(&amp;quot;C&amp;quot;) -&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;@order.LastUpdate.ToString(&amp;quot;dd MMMM yyyy HH:mm tt&amp;quot;)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;p&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;TOTAL: @orders.Sum(o =&amp;gt; o.OrderTotal).ToString(&amp;quot;C&amp;quot;)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt; &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: razor, REST API&lt;/div&gt;
</description></item><item><title>Show information from a custom stored procedure</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation/801/show-information-from-a-custom-stored-procedure/revision/1</link><pubDate>Mon, 05 Dec 2022 05:21:38 GMT</pubDate><guid isPermaLink="false">fd08b0f2-65fa-4b2b-916a-cce3e88b61d0:3db4dc4a-5991-4e1a-8955-873a5d0ba0ca</guid><dc:creator>James Murty</dc:creator><description>Revision 1 posted to Community Docs Wiki by James Murty on 12/5/2022 5:21:38 AM&lt;br /&gt;
&lt;p&gt;This is a rough guide to fetching and displaying&amp;nbsp;arbitrary data from a custom stored procedure via the&amp;nbsp;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;Custom/Execute&lt;/span&gt; REST API endpoint.&lt;/p&gt;
&lt;p&gt;NOTE: This may not be the best way to do things&amp;mdash;edits, additions, and improvements to this document are very welcome.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In this example, we use&amp;nbsp;a&amp;nbsp;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;CUSTOMER_ORDERS&lt;/span&gt;&amp;nbsp;stored procedure to include a summary of a constituent&amp;#39;s recent orders in a &lt;em&gt;Constituent Info&lt;/em&gt;&amp;nbsp;template.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;@using Tessitura.Services.Common.Client.Utils;
@using Tessitura.Service.Client.CRM;
@using Tessitura.Service.Client.Custom;

@* Use Newtonsoft library to parse fields from JSON data *@
@using Newtonsoft.Json;

@{
	// Define an OrderInfo object to parse JSON data from fields returned by the
	// custom query to attributes of the correct type.
	@functions {
		public class OrderInfo
		{
			[JsonPropertyAttribute(&amp;quot;order_no&amp;quot;)]
			public int OrderNo;
			[JsonPropertyAttribute(&amp;quot;order_total&amp;quot;)]
			public double OrderTotal;
			[JsonPropertyAttribute(&amp;quot;last_update_dt&amp;quot;)]
			public DateTime LastUpdate;
		}
	}

	// Find orders that have been updated in the last 30 days
	DateTime now = DateTime.Now;
	DateTime ordersFromDate = now.AddDays(-30);

	// Define request parameters for CUSTOMER_ORDERS custom stored procedure
	LocalProcedureRequest localProcedureRequest = new LocalProcedureRequest
		{
			ProcedureName = &amp;quot;CUSTOMER_ORDERS&amp;quot;,
			ParameterValues = new ParameterValues
			{
				// Constituent ID is made available in Constituent Info templates
				new ParameterValue
				{
					Name = &amp;quot;constituent_id&amp;quot;,
					Value = Model.ConstituentSnapshot.Id.ToString()
				},
				new ParameterValue
				{
					Name = &amp;quot;start_dt&amp;quot;,
					Value = ordersFromDate.ToString(&amp;quot;yyyy-MM-dd&amp;quot;)
				}
			}
		};

	// Fetch data from stored procedure CUSTOMER_ORDERS via /Custom/Execute API
	// endpoint and parse JSON response data into a list of `OrderInfo` objects
	var orders = Model.RestClient
		.AtUrl(&amp;quot;Custom/Execute&amp;quot;)
		// Request JSON data in response
		.WithContentType(ContentType.Json)
		// POST request, with defined types to (de)serialize req/resp data
		.Post&amp;lt;LocalProcedureRequest, List&amp;lt;OrderInfo&amp;gt;&amp;gt;
		(localProcedureRequest)
		.ResponseObject;

	@*
	// Uncomment to see JSON response data in the HTML Template editor
	&amp;lt;pre&amp;gt;
		@Raw(Newtonsoft.Json.JsonConvert.SerializeObject(
			@orders,
			Newtonsoft.Json.Formatting.Indented
		));
	&amp;lt;/pre&amp;gt;
	*@
}

@if (orders.Count &amp;gt; 0)
{
	&amp;lt;h1&amp;gt;Customer Orders&amp;lt;/h1&amp;gt;

	&amp;lt;ul&amp;gt;
		@foreach (var order in orders)
		{
			&amp;lt;li&amp;gt;
				@order.OrderNo -
				@order.OrderTotal.ToString(&amp;quot;C&amp;quot;) -
				@order.LastUpdate.ToString(&amp;quot;dd MMMM yyyy HH:mm tt&amp;quot;)
			&amp;lt;/li&amp;gt;
		}
	&amp;lt;/ul&amp;gt;

	&amp;lt;p&amp;gt;
		TOTAL: @orders.Sum(o =&amp;gt; o.OrderTotal).ToString(&amp;quot;C&amp;quot;)
	&amp;lt;/p&amp;gt;
}
&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: razor, REST API&lt;/div&gt;
</description></item><item><title>Tips for writing HTML Templates</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation/800/tips-for-writing-html-templates</link><pubDate>Mon, 05 Dec 2022 05:04:30 GMT</pubDate><guid isPermaLink="false">fd08b0f2-65fa-4b2b-916a-cce3e88b61d0:26ceb1f2-6ebe-451d-bb91-c2d8f18649e0</guid><dc:creator>James Murty</dc:creator><description>Current Revision posted to Community Docs Wiki by James Murty on 12/5/2022 5:04:30 AM&lt;br /&gt;
&lt;p&gt;Here are some tips for writing and managing HTML Templates in Tessitura. These tips work as of version 15.&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:200%;"&gt;Make your own backups&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Tessitura does not create back-ups of HTML Templates, so you must do this yourself if you want to keep a history of changes and guard against accidentally breaking your emails.&lt;/p&gt;
&lt;p&gt;Some advice:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Never edit an existing template directly. Instead, duplicate&amp;nbsp;the original to a new name and work on it there. Copy your changes back into the original once you are sure they work&lt;/li&gt;
&lt;li&gt;Make your own copies of template documents before &amp;ndash; and during &amp;ndash; the editing process by copying everything in the Template tab and pasting it somewhere else.
&lt;ul&gt;
&lt;li&gt;If you have a version-controlled code repository this would be a perfect place to save copies of your templates and work-in-progress&lt;/li&gt;
&lt;li&gt;Even if you don&amp;#39;t,&amp;nbsp;saving your own copies of your templates before major changes is almost certainly a good idea.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:200%;"&gt;Inspect contents of a Model or data object&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;Use the following snippet to&amp;nbsp;show the contents of a data object in JSON format. This lets you find out what fields are available.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;This example shows the contents of &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;anObject&lt;span style="font-family:arial, helvetica, sans-serif;"&gt;.&amp;nbsp;It works best if you wrap the statement in &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&amp;lt;pre&amp;gt;&amp;lt;/pre&amp;gt;&lt;/span&gt; tags.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;pre class="ui-code" data-mode="html"&gt;&amp;lt;pre&amp;gt;
	@Raw(Newtonsoft.Json.JsonConvert.SerializeObject(
		@anObject,
		Newtonsoft.Json.Formatting.Indented
	));
&amp;lt;/pre&amp;gt;&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: razor&lt;/div&gt;
</description></item><item><title>Tips for writing HTML Templates</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation/800/tips-for-writing-html-templates/revision/1</link><pubDate>Mon, 05 Dec 2022 05:04:11 GMT</pubDate><guid isPermaLink="false">fd08b0f2-65fa-4b2b-916a-cce3e88b61d0:26ceb1f2-6ebe-451d-bb91-c2d8f18649e0</guid><dc:creator>James Murty</dc:creator><description>Revision 1 posted to Community Docs Wiki by James Murty on 12/5/2022 5:04:11 AM&lt;br /&gt;
&lt;p&gt;Here are some tips for writing and managing HTML Templates in Tessitura. These tips work as of version 15.&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:200%;"&gt;Make your own backups&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Tessitura does not create back-ups of HTML Templates, so you must do this yourself if you want to keep a history of changes and guard against accidentally breaking your emails.&lt;/p&gt;
&lt;p&gt;Some advice:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Never edit an existing template directly. Instead, duplicate&amp;nbsp;the original to a new name and work on it there. Copy your changes back into the original once you are sure they work&lt;/li&gt;
&lt;li&gt;Make your own copies of template documents before &amp;ndash; and during &amp;ndash; the editing process by copying everything in the Template tab and pasting it somewhere else.
&lt;ul&gt;
&lt;li&gt;If you have a version-controlled code repository this would be a perfect place to save copies of your templates and work-in-progress&lt;/li&gt;
&lt;li&gt;Even if you don&amp;#39;t,&amp;nbsp;saving your own copies of your templates before major changes is almost certainly a good idea.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style="font-size:200%;"&gt;Inspect contents of a Model or data object&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;Use the following snippet to&amp;nbsp;show the contents of a data object in JSON format. This lets you find out what fields are available.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;This example shows the contents of &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;anObject&lt;span style="font-family:arial, helvetica, sans-serif;"&gt;.&amp;nbsp;It works best if you wrap the statement in &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;&amp;lt;pre&amp;gt;&amp;lt;/pre&amp;gt;&lt;/span&gt; tags.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:inherit;"&gt;&lt;pre class="ui-code" data-mode="html"&gt;&amp;lt;pre&amp;gt;
	@Raw(Newtonsoft.Json.JsonConvert.SerializeObject(
		@anObject,
		Newtonsoft.Json.Formatting.Indented
	));
&amp;lt;/pre&amp;gt;&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: razor&lt;/div&gt;
</description></item><item><title>HTML Templates</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation/799/html-templates</link><pubDate>Mon, 05 Dec 2022 04:50:15 GMT</pubDate><guid isPermaLink="false">fd08b0f2-65fa-4b2b-916a-cce3e88b61d0:46582c7c-cb18-4c19-ba29-2cfa9236f9ab</guid><dc:creator>James Murty</dc:creator><description>Current Revision posted to Community Docs Wiki by James Murty on 12/5/2022 4:50:15 AM&lt;br /&gt;
&lt;p&gt;See sub-pages in the sidebar&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Deploying network ticket printers via Windows Group Policy</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation/796/deploying-network-ticket-printers-via-windows-group-policy</link><pubDate>Sat, 02 Jul 2022 00:42:30 GMT</pubDate><guid isPermaLink="false">fd08b0f2-65fa-4b2b-916a-cce3e88b61d0:afe17571-5a89-4e78-a9c6-2052d9379780</guid><dc:creator>Nick Reilingh</dc:creator><description>Current Revision posted to Community Docs Wiki by Nick Reilingh on 7/2/2022 12:42:30 AM&lt;br /&gt;
&lt;p&gt;Printer deployment is a vast subject with a multitude of options, but I wanted to point out one particular &lt;a title="footgun - Wiktionary" href="https://en.wiktionary.org/wiki/footgun#English" rel="noopener noreferrer" target="_blank"&gt;footgun&lt;/a&gt; that can cause issues for box office personnel doing batch printing and similar activities:&lt;/p&gt;
&lt;p&gt;When deploying networked ticket printers via Group Policy Preferences, an &amp;quot;action&amp;quot; must be selected for the preference&amp;nbsp;from Create, Update, Replace, and Delete. This action controls how the preference will be applied. What may not be obvious if you are new to Group Policy is that the Replace action is equivalent to a&amp;nbsp;Create action followed by a Delete action which is pre-scheduled for the next policy refresh. This means that every 90 minutes or so (with some random variance) when&amp;nbsp;group policy is applied by the client, your printer will be deleted and immediately recreated by the group policy client.&lt;/p&gt;
&lt;p&gt;If Tessitura is actively printing to a printer like in a batch print and the printer gets deleted, its reference&amp;nbsp;to the printer is invalidated and the print will start to error out. This is because the reference to the printer during printing is a code object reference, not a reference by printer name, and when group policy deletes and recreates the printer, it deletes the existing&amp;nbsp;code object and creates a brand new one that only just happens to have the same user-visible name.&lt;/p&gt;
&lt;p&gt;So: Don&amp;#39;t use the Replace action for ticket printers. Use Create or Update. You can always issue a Delete action preference later to clean up cruft instead of making use of the &amp;quot;Remove this item when it is no longer applied&amp;quot; option, which&amp;nbsp;&lt;em&gt;requires&lt;/em&gt; the Replace action.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: printers, group policy&lt;/div&gt;
</description></item><item><title>The Secret Life of HTML Templates</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation/790/the-secret-life-of-html-templates/revision/6</link><pubDate>Fri, 28 May 2021 16:03:36 GMT</pubDate><guid isPermaLink="false">fd08b0f2-65fa-4b2b-916a-cce3e88b61d0:6aa35c30-07ae-4c3a-b10f-0acfb6040cab</guid><dc:creator>Nick Reilingh</dc:creator><description>Revision 6 posted to Community Docs Wiki by Nick Reilingh on 5/28/2021 4:03:36 PM&lt;br /&gt;
&lt;blockquote&gt;
&lt;p&gt;or: How I Learned to Stop Worrying and Just Write HTML Templates&lt;/p&gt;
&lt;p&gt;or: HTML Templates: The Missing Manual&lt;/p&gt;
&lt;p&gt;or: The HTML Templates documentation they&amp;nbsp;&lt;em&gt;don&amp;#39;t&lt;/em&gt; want you to know about!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This article aims to explain the differences between the Razor template syntax used in Tessitura HTML Templates and the syntax that you might see used in training courses&amp;nbsp;for Razor Pages in ASP.NET Core/MVC web applications. At present, the Tessitura documentation only scratches the surface of what is available syntactically, and doesn&amp;#39;t really attempt to explain how&amp;nbsp;HTML Templates are implemented.&lt;/p&gt;
&lt;h2 id="mcetoc_1f6o9tpq90"&gt;The Big Secret&lt;/h2&gt;
&lt;p&gt;HTML Templates are rendered using an Apache-licensed, open-source project called &lt;a title="Documentation site for RazorEngine" href="http://antaris.github.io/RazorEngine/" rel="noopener noreferrer" target="_blank"&gt;RazorEngine&lt;/a&gt;, which is available &lt;a title="GitHub repo for Antaris/RazorEngine" href="https://github.com/Antaris/RazorEngine" rel="noopener noreferrer" target="_blank"&gt;on GitHub&lt;/a&gt;. To&amp;nbsp;summarize the &lt;a title="About Razor and its syntax" href="https://antaris.github.io/RazorEngine/AboutRazor.html" rel="noopener noreferrer" target="_blank"&gt;RazorEngine documentation&lt;/a&gt;, RazorEngine is a framework&amp;nbsp;which consumes the Razor parser -- as is ASP.NET MVC. There is a difference between Razor&amp;#39;s syntax and special features provided by these frameworks. RazorEngine only shares its syntax with other implementations like ASP.NET MVC. This is why convenience methods like &lt;code&gt;@Html.Raw()&lt;/code&gt; (often seen in web results about Razor Pages) do not work in HTML templates -- the &lt;code&gt;@Html&lt;/code&gt; helper is a &lt;a title="HtmlHelper Class" href="https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.htmlhelper?view=aspnet-mvc-5.2" rel="noopener noreferrer" target="_blank"&gt;class&lt;/a&gt; specifically implemented by the ASP.NET MVC framework. (RazorEngine instead has &lt;code&gt;@Raw()&lt;/code&gt; built-in to provide the &lt;a title="Encoding Values in RazorEngine" href="https://antaris.github.io/RazorEngine/Encoding.html" rel="noopener noreferrer" target="_blank"&gt;same functionality&lt;/a&gt;.) Reading the &lt;a href="https://antaris.github.io/RazorEngine/index.html" rel="noopener noreferrer" target="_blank"&gt;RazorEngine documentation&lt;/a&gt; can be informative. Tessitura appears to implement version 3.10 of RazorEngine.&lt;/p&gt;
&lt;p&gt;The fundamentals of how Razor operates still apply. The Razor syntax parser converts a .cshtml template into a C# &lt;code&gt;Execute()&lt;/code&gt; method on a generated class, which, when invoked, has access to the provided model and returns a string.&lt;/p&gt;
&lt;h2 id="mcetoc_1f6oeo60f1"&gt;Assorted Syntactic Tips and Tricks&lt;/h2&gt;
&lt;p&gt;The version of C# available in Tessitura HTML Templates in Tessitura V15.1 is C# 5.0. In Tessitura V16, Razor templates will support C# 9.0, giving them support for &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated" rel="noopener noreferrer" target="_blank"&gt;interpolated strings&lt;/a&gt; (C# 6.0), &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/local-functions" rel="noopener noreferrer" target="_blank"&gt;local functions&lt;/a&gt; (C# 7.0), and other features.&lt;/p&gt;
&lt;p&gt;The version of Razor available in Tessitura HTML Templates in V15.1 is &amp;quot;Razor 3&amp;quot;, which is versioned as such because it shipped with ASP.NET MVC 3. This means technically, the &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/mvc/views/razor" rel="noopener noreferrer" target="_blank"&gt;syntax documentation linked in the Tessitura docs&lt;/a&gt; is&amp;nbsp;WAY too new for what is actually in use. This explains why &amp;quot;templating methods&amp;quot; described in these docs are not functional in Tessitura HTML Templates.&lt;/p&gt;
&lt;p&gt;Razor supports the use of a &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-5.0#functions" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;@functions&lt;/code&gt; directive&lt;/a&gt;, which gives you a&amp;nbsp;space to define additional members (methods and properties) to be added to the&amp;nbsp;generated class. Curiously, the HTML Templates editor does not syntax-color code inside of a &lt;code&gt;@functions&lt;/code&gt; directive.&lt;/p&gt;
&lt;pre&gt;@functions {&lt;br /&gt;    private string SOME_URL_CONSTANT = &amp;quot;https://example.com&amp;quot;;&lt;br /&gt;    private string LinkTag(string link) {&lt;br /&gt;        return &amp;quot;&amp;lt;a href=\&amp;quot;&amp;quot; + SOME_URL_CONSTANT + &amp;quot;\&amp;quot;&amp;gt;&amp;quot; + link + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;@Raw(LinkTag(&amp;quot;some text&amp;quot;))&lt;br /&gt;@* Outputs:&lt;br /&gt;&amp;lt;a href=&amp;quot;https://example.com&amp;quot;&amp;gt;some text&amp;lt;/a&amp;gt;&lt;br /&gt;*@&lt;/pre&gt;
&lt;p&gt;Methods are private because&amp;nbsp;the template&amp;#39;s execution is just another method in the same class.&lt;/p&gt;
&lt;p&gt;The version of Razor used in RazorEngine 3.10 (Razor 3, shipped in ASP.NET MVC 3) also supports the &lt;code&gt;@helper&lt;/code&gt; directive, which allows you to define a kind of function that contains markup, just like the rest of the template. This allows for easy reuse of template code. Helpers were &lt;a href="https://github.com/aspnet/Razor/issues/281" rel="noopener noreferrer" target="_blank"&gt;removed in&amp;nbsp;Razor 4&lt;/a&gt;, &lt;a href="https://www.c-sharpcorner.com/article/html-helpers-in-asp-net-mvc-5/" rel="noopener noreferrer" target="_blank"&gt;reappear in ASP.NET MVC 5&lt;/a&gt;,&amp;nbsp;were removed again in &lt;a href="https://github.com/dotnet/aspnetcore/issues/5110" rel="noopener noreferrer" target="_blank"&gt;ASP.NET Core&lt;/a&gt;,&amp;nbsp;and finally &lt;a href="https://github.com/dotnet/aspnetcore-tooling/pull/334" rel="noopener noreferrer" target="_blank"&gt;code blocks were enhanced to allow for inline markup in functions&lt;/a&gt;, without the need for the &lt;code&gt;@helper&lt;/code&gt; directive. Helpers can be used as &amp;quot;templating methods&amp;quot; which are otherwise unavailable as described above.&lt;/p&gt;
&lt;pre&gt;@helper BoldMe(string content) {&lt;br /&gt;    &amp;lt;b&amp;gt;@content&amp;lt;/b&amp;gt;&lt;br /&gt;}&lt;br /&gt;@BoldMe(&amp;quot;look at me, I&amp;#39;m bold!&amp;quot;)&lt;br /&gt;@* Outputs:&lt;br /&gt;&amp;lt;b&amp;gt;look at me, I&amp;amp;#39;m bold!&amp;lt;/b&amp;gt;&lt;br /&gt;*@&lt;/pre&gt;
&lt;p&gt;The output of the helper correctly writes literal or encoded HTML like the rest of the template does.&lt;/p&gt;
&lt;p&gt;A regular function can be made to behave like a templating method by defining it with a void type and then calling the imperative &lt;code&gt;WriteLiteral()&lt;/code&gt; and &lt;code&gt;Write()&lt;/code&gt; functions, which is basically what a Razor template compiles to in the first place. Then this function can be called inside a code block (&lt;code&gt;@{}&lt;/code&gt;) to inject its output at that location.&lt;/p&gt;
&lt;pre&gt;@functions {&lt;br /&gt;    private void DIYRenderFunction(string content) {&lt;br /&gt;        WriteLiteral(&amp;quot;&amp;lt;p&amp;gt;&amp;quot;);&lt;br /&gt;        Write(content);&lt;br /&gt;        WriteLiteral(&amp;quot;&amp;lt;/p&amp;gt;&amp;quot;);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;@{ DIYRenderFunction(&amp;quot;here are my paragraph tags &amp;amp; encoded content&amp;quot;); }&lt;br /&gt;@* Outputs:&lt;br /&gt;&amp;lt;p&amp;gt;here are my paragraph tags &amp;amp;amp; encoded content&amp;lt;/p&amp;gt;&lt;br /&gt;*@&lt;/pre&gt;
&lt;p&gt;Helpers can be passed into one another as arguments if your types are correct. The defined helper token refers to a method which returns a&amp;nbsp;&lt;a title="RazorEngine TemplateWriter type" href="https://antaris.github.io/RazorEngine/references/razorengine-templating-templatewriter.html" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;RazorEngine.Templating.TemplateWriter&lt;/code&gt; type&lt;/a&gt;, which is what writes template content as Literal or HTML-encoded inline. This type has a&amp;nbsp;&lt;code&gt;.ToString()&lt;/code&gt;&amp;nbsp;method which can be used to cast to a string type at the point of use, but this is often non-optimal because if the helper template outputs HTML (which it often will), you will need to&amp;nbsp;&lt;code&gt;@Raw()&lt;/code&gt;&amp;nbsp;the result when using it in another helper template.&amp;nbsp;Luckily, C# supports the &lt;code&gt;dynamic&lt;/code&gt; keyword in a type signature, which means you can pass in either a &lt;code&gt;TemplateWriter&lt;/code&gt; or a raw &lt;code&gt;string&lt;/code&gt; and RazorEngine will do the right thing at runtime:&lt;/p&gt;
&lt;pre&gt;@helper ItalicizeMe(dynamic content) {&lt;br /&gt;    &amp;lt;i&amp;gt;@content&amp;lt;/i&amp;gt;&lt;br /&gt;}&lt;br /&gt;@helper BoldMe(dynamic content) {&lt;br /&gt;    &amp;lt;b&amp;gt;@content&amp;lt;/b&amp;gt;&lt;br /&gt;}&lt;br /&gt;@ItalicizeMe(BoldMe(&amp;quot;I&amp;#39;m bold, AND italic!&amp;quot;))&lt;br /&gt;@ItalicizeMe(&amp;quot;I&amp;#39;m only italic!&amp;quot;)&lt;br /&gt;@* Outputs:&lt;br /&gt;    &amp;lt;i&amp;gt;    &amp;lt;b&amp;gt;I&amp;amp;#39;m bold, AND italic!&amp;lt;/b&amp;gt;&lt;br /&gt;&amp;lt;/i&amp;gt;&lt;br /&gt;    &amp;lt;i&amp;gt;I&amp;amp;#39;m only italic!&amp;lt;/i&amp;gt;&lt;br /&gt;*@&lt;/pre&gt;
&lt;p&gt;You can also compose helpers by nesting them inside each other&amp;#39;s templates, since helpers and &lt;code&gt;@functions&lt;/code&gt;&amp;nbsp;directives share the same scope (the generated class). In contrast, variables declared in a code block are local to the render method, so while they can be referenced in the template itself, they cannot be referenced in other class methods like helpers and functions.&lt;/p&gt;
&lt;p&gt;A special syntax exists in Razor 3 for raw text. This is necessary when using helpers without surrounding tags. Information here: &lt;a href="https://weblogs.asp.net/scottgu/asp-net-mvc-3-razor-s-and-lt-text-gt-syntax" rel="noopener noreferrer" target="_blank"&gt;ASP.NET MVC 3: Razor&amp;rsquo;s @: and &amp;lt;text&amp;gt; syntax&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, with all of these tools in our toolbox, only one question remains... Can we avoid writing inline styles?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: c#, HTML Templates, razor&lt;/div&gt;
</description></item><item><title>The Secret Life of HTML Templates</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation/790/the-secret-life-of-html-templates/revision/5</link><pubDate>Fri, 28 May 2021 15:04:13 GMT</pubDate><guid isPermaLink="false">fd08b0f2-65fa-4b2b-916a-cce3e88b61d0:6aa35c30-07ae-4c3a-b10f-0acfb6040cab</guid><dc:creator>Nick Reilingh</dc:creator><description>Revision 5 posted to Community Docs Wiki by Nick Reilingh on 5/28/2021 3:04:13 PM&lt;br /&gt;
&lt;blockquote&gt;
&lt;p&gt;or: How I Learned to Stop Worrying and Just Write HTML Templates&lt;/p&gt;
&lt;p&gt;or: HTML Templates: The Missing Manual&lt;/p&gt;
&lt;p&gt;or: The HTML Templates documentation they&amp;nbsp;&lt;em&gt;don&amp;#39;t&lt;/em&gt; want you to know about!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This article aims to explain the differences between the Razor template syntax used in Tessitura HTML Templates and the syntax that you might see used in training courses&amp;nbsp;for Razor Pages in ASP.NET Core/MVC web applications. At present, the Tessitura documentation only scratches the surface of what is available syntactically, and doesn&amp;#39;t really attempt to explain how&amp;nbsp;HTML Templates are implemented.&lt;/p&gt;
&lt;h2 id="mcetoc_1f6o9tpq90"&gt;The Big Secret&lt;/h2&gt;
&lt;p&gt;HTML Templates are rendered using an Apache-licensed, open-source project called &lt;a title="Documentation site for RazorEngine" href="http://antaris.github.io/RazorEngine/" rel="noopener noreferrer" target="_blank"&gt;RazorEngine&lt;/a&gt;, which is available &lt;a title="GitHub repo for Antaris/RazorEngine" href="https://github.com/Antaris/RazorEngine" rel="noopener noreferrer" target="_blank"&gt;on GitHub&lt;/a&gt;. To&amp;nbsp;summarize the &lt;a title="About Razor and its syntax" href="https://antaris.github.io/RazorEngine/AboutRazor.html" rel="noopener noreferrer" target="_blank"&gt;RazorEngine documentation&lt;/a&gt;, RazorEngine is a framework&amp;nbsp;which consumes the Razor parser -- as is ASP.NET MVC. There is a difference between Razor&amp;#39;s syntax and special features provided by these frameworks. RazorEngine only shares its syntax with other implementations like ASP.NET MVC. This is why convenience methods like &lt;code&gt;@Html.Raw()&lt;/code&gt; (often seen in web results about Razor Pages) do not work in HTML templates -- the &lt;code&gt;@Html&lt;/code&gt; helper is a &lt;a title="HtmlHelper Class" href="https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.htmlhelper?view=aspnet-mvc-5.2" rel="noopener noreferrer" target="_blank"&gt;class&lt;/a&gt; specifically implemented by the ASP.NET MVC framework. (RazorEngine instead has &lt;code&gt;@Raw()&lt;/code&gt; built-in to provide the &lt;a title="Encoding Values in RazorEngine" href="https://antaris.github.io/RazorEngine/Encoding.html" rel="noopener noreferrer" target="_blank"&gt;same functionality&lt;/a&gt;.) Reading the &lt;a href="https://antaris.github.io/RazorEngine/index.html" rel="noopener noreferrer" target="_blank"&gt;RazorEngine documentation&lt;/a&gt; can be informative. Tessitura appears to implement version 3.10 of RazorEngine.&lt;/p&gt;
&lt;p&gt;The fundamentals of how Razor operates still apply. The Razor syntax parser converts a .cshtml template into a C# &lt;code&gt;Execute()&lt;/code&gt; method on a generated class, which, when invoked, has access to the provided model and returns a string.&lt;/p&gt;
&lt;h2 id="mcetoc_1f6oeo60f1"&gt;Assorted Syntactic Tips and Tricks&lt;/h2&gt;
&lt;p&gt;The version of C# available in Tessitura HTML Templates in Tessitura V15.1 is C# 5.0. In Tessitura V16, Razor templates will support C# 9.0, giving them support for interpolated strings (among other features).&lt;/p&gt;
&lt;p&gt;The version of Razor available in Tessitura HTML Templates in V15.1 is &amp;quot;Razor 3&amp;quot;, which is versioned as such because it shipped with ASP.NET MVC 3. This means technically, the &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/mvc/views/razor" rel="noopener noreferrer" target="_blank"&gt;syntax documentation linked in the Tessitura docs&lt;/a&gt; is&amp;nbsp;WAY too new for what is actually in use. This explains why &amp;quot;templating methods&amp;quot; described in these docs are not functional in Tessitura HTML Templates.&lt;/p&gt;
&lt;p&gt;Razor supports the use of a &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-5.0#functions" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;@functions&lt;/code&gt; directive&lt;/a&gt;, which gives you a&amp;nbsp;space to define additional members (methods and properties) to be added to the&amp;nbsp;generated class. Curiously, the HTML Templates editor does not syntax-color code inside of a &lt;code&gt;@functions&lt;/code&gt; directive.&lt;/p&gt;
&lt;pre&gt;@functions {&lt;br /&gt;    private string SOME_URL_CONSTANT = &amp;quot;https://example.com&amp;quot;;&lt;br /&gt;    private string LinkTag(string link) {&lt;br /&gt;        return &amp;quot;&amp;lt;a href=\&amp;quot;&amp;quot; + SOME_URL_CONSTANT + &amp;quot;\&amp;quot;&amp;gt;&amp;quot; + link + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;@Raw(LinkTag(&amp;quot;some text&amp;quot;))&lt;br /&gt;@* Outputs:&lt;br /&gt;&amp;lt;a href=&amp;quot;https://example.com&amp;quot;&amp;gt;some text&amp;lt;/a&amp;gt;&lt;br /&gt;*@&lt;/pre&gt;
&lt;p&gt;Methods are private because&amp;nbsp;the template&amp;#39;s execution is just another method in the same class.&lt;/p&gt;
&lt;p&gt;The version of Razor used in RazorEngine 3.10 (Razor 3, shipped in ASP.NET MVC 3) also supports the &lt;code&gt;@helper&lt;/code&gt; directive, which allows you to define a kind of function that contains markup, just like the rest of the template. This allows for easy reuse of template code. Helpers were &lt;a href="https://github.com/aspnet/Razor/issues/281" rel="noopener noreferrer" target="_blank"&gt;removed in&amp;nbsp;Razor 4&lt;/a&gt;, &lt;a href="https://www.c-sharpcorner.com/article/html-helpers-in-asp-net-mvc-5/" rel="noopener noreferrer" target="_blank"&gt;reappear in ASP.NET MVC 5&lt;/a&gt;,&amp;nbsp;were removed again in &lt;a href="https://github.com/dotnet/aspnetcore/issues/5110" rel="noopener noreferrer" target="_blank"&gt;ASP.NET Core&lt;/a&gt;,&amp;nbsp;and finally &lt;a href="https://github.com/dotnet/aspnetcore-tooling/pull/334" rel="noopener noreferrer" target="_blank"&gt;code blocks were enhanced to allow for inline markup in functions&lt;/a&gt;, without the need for the &lt;code&gt;@helper&lt;/code&gt; directive. Helpers can be used as &amp;quot;templating methods&amp;quot; which are otherwise unavailable as described above.&lt;/p&gt;
&lt;pre&gt;@helper BoldMe(string content) {&lt;br /&gt;    &amp;lt;b&amp;gt;@content&amp;lt;/b&amp;gt;&lt;br /&gt;}&lt;br /&gt;@BoldMe(&amp;quot;look at me, I&amp;#39;m bold!&amp;quot;)&lt;br /&gt;@* Outputs:&lt;br /&gt;&amp;lt;b&amp;gt;look at me, I&amp;amp;#39;m bold!&amp;lt;/b&amp;gt;&lt;br /&gt;*@&lt;/pre&gt;
&lt;p&gt;The output of the helper correctly writes literal or encoded HTML like the rest of the template does.&lt;/p&gt;
&lt;p&gt;A regular function can be made to behave like a templating method by defining it with a void type and then calling the imperative &lt;code&gt;WriteLiteral()&lt;/code&gt; and &lt;code&gt;Write()&lt;/code&gt; functions, which is basically what a Razor template compiles to in the first place. Then this function can be called inside a code block (&lt;code&gt;@{}&lt;/code&gt;) to inject its output at that location.&lt;/p&gt;
&lt;pre&gt;@functions {&lt;br /&gt;    private void DIYRenderFunction(string content) {&lt;br /&gt;        WriteLiteral(&amp;quot;&amp;lt;p&amp;gt;&amp;quot;);&lt;br /&gt;        Write(content);&lt;br /&gt;        WriteLiteral(&amp;quot;&amp;lt;/p&amp;gt;&amp;quot;);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;@{ DIYRenderFunction(&amp;quot;here are my paragraph tags &amp;amp; encoded content&amp;quot;); }&lt;br /&gt;@* Outputs:&lt;br /&gt;&amp;lt;p&amp;gt;here are my paragraph tags &amp;amp;amp; encoded content&amp;lt;/p&amp;gt;&lt;br /&gt;*@&lt;/pre&gt;
&lt;p&gt;Helpers can be passed into one another as arguments if your types are correct. The defined helper token refers to a method which returns a&amp;nbsp;&lt;a title="RazorEngine TemplateWriter type" href="https://antaris.github.io/RazorEngine/references/razorengine-templating-templatewriter.html" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;RazorEngine.Templating.TemplateWriter&lt;/code&gt; type&lt;/a&gt;, which is what writes template content as Literal or HTML-encoded inline. This type has a&amp;nbsp;&lt;code&gt;.ToString()&lt;/code&gt;&amp;nbsp;method which can be used to cast to a string type at the point of use, but this is often non-optimal because if the helper template outputs HTML (which it often will), you will need to&amp;nbsp;&lt;code&gt;@Raw()&lt;/code&gt;&amp;nbsp;the result when using it in another helper template.&amp;nbsp;Luckily, C# supports the &lt;code&gt;dynamic&lt;/code&gt; keyword in a type signature, which means you can pass in either a &lt;code&gt;TemplateWriter&lt;/code&gt; or a raw &lt;code&gt;string&lt;/code&gt; and RazorEngine will do the right thing at runtime:&lt;/p&gt;
&lt;pre&gt;@helper ItalicizeMe(dynamic content) {&lt;br /&gt;    &amp;lt;i&amp;gt;@content&amp;lt;/i&amp;gt;&lt;br /&gt;}&lt;br /&gt;@helper BoldMe(dynamic content) {&lt;br /&gt;    &amp;lt;b&amp;gt;@content&amp;lt;/b&amp;gt;&lt;br /&gt;}&lt;br /&gt;@ItalicizeMe(BoldMe(&amp;quot;I&amp;#39;m bold, AND italic!&amp;quot;))&lt;br /&gt;@ItalicizeMe(&amp;quot;I&amp;#39;m only italic!&amp;quot;)&lt;br /&gt;@* Outputs:&lt;br /&gt;    &amp;lt;i&amp;gt;    &amp;lt;b&amp;gt;I&amp;amp;#39;m bold, AND italic!&amp;lt;/b&amp;gt;&lt;br /&gt;&amp;lt;/i&amp;gt;&lt;br /&gt;    &amp;lt;i&amp;gt;I&amp;amp;#39;m only italic!&amp;lt;/i&amp;gt;&lt;br /&gt;*@&lt;/pre&gt;
&lt;p&gt;You can also compose helpers by nesting them inside each other&amp;#39;s templates, since helpers and &lt;code&gt;@functions&lt;/code&gt;&amp;nbsp;directives share the same scope (the generated class). In contrast, variables declared in a code block are local to the render method, so while they can be referenced in the template itself, they cannot be referenced in other class methods like helpers and functions.&lt;/p&gt;
&lt;p&gt;A special syntax exists in Razor 3 for raw text. This is necessary when using helpers without surrounding tags. Information here: &lt;a href="https://weblogs.asp.net/scottgu/asp-net-mvc-3-razor-s-and-lt-text-gt-syntax" rel="noopener noreferrer" target="_blank"&gt;ASP.NET MVC 3: Razor&amp;rsquo;s @: and &amp;lt;text&amp;gt; syntax&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, with all of these tools in our toolbox, only one question remains... Can we avoid writing inline styles?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: c#, HTML Templates, razor&lt;/div&gt;
</description></item><item><title>The Secret Life of HTML Templates</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation/790/the-secret-life-of-html-templates/revision/4</link><pubDate>Fri, 28 May 2021 04:31:56 GMT</pubDate><guid isPermaLink="false">fd08b0f2-65fa-4b2b-916a-cce3e88b61d0:6aa35c30-07ae-4c3a-b10f-0acfb6040cab</guid><dc:creator>Nick Reilingh</dc:creator><description>Revision 4 posted to Community Docs Wiki by Nick Reilingh on 5/28/2021 4:31:56 AM&lt;br /&gt;
&lt;blockquote&gt;
&lt;p&gt;or: How I Learned to Stop Worrying and Just Write HTML Templates&lt;/p&gt;
&lt;p&gt;or: HTML Templates: The Missing Manual&lt;/p&gt;
&lt;p&gt;or: The HTML Templates documentation they&amp;nbsp;&lt;em&gt;don&amp;#39;t&lt;/em&gt; want you to know about!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This article aims to explain the differences between the Razor template syntax used in Tessitura HTML Templates and the syntax that you might see used in training courses&amp;nbsp;for Razor Pages in ASP.NET Core/MVC web applications. At present, the Tessitura documentation only scratches the surface of what is available syntactically, and doesn&amp;#39;t really attempt to explain how&amp;nbsp;HTML Templates are implemented.&lt;/p&gt;
&lt;h2 id="mcetoc_1f6o9tpq90"&gt;The Big Secret&lt;/h2&gt;
&lt;p&gt;HTML Templates are rendered using an Apache-licensed, open-source project called &lt;a title="Documentation site for RazorEngine" href="http://antaris.github.io/RazorEngine/" rel="noopener noreferrer" target="_blank"&gt;RazorEngine&lt;/a&gt;, which is available &lt;a title="GitHub repo for Antaris/RazorEngine" href="https://github.com/Antaris/RazorEngine" rel="noopener noreferrer" target="_blank"&gt;on GitHub&lt;/a&gt;. To&amp;nbsp;summarize the &lt;a title="About Razor and its syntax" href="https://antaris.github.io/RazorEngine/AboutRazor.html" rel="noopener noreferrer" target="_blank"&gt;RazorEngine documentation&lt;/a&gt;, RazorEngine is a framework&amp;nbsp;which consumes the Razor parser -- as is ASP.NET MVC. There is a difference between Razor&amp;#39;s syntax and special features provided by these frameworks. RazorEngine only shares its syntax with other implementations like ASP.NET MVC. This is why convenience methods like &lt;code&gt;@Html.Raw()&lt;/code&gt; (often seen in web results about Razor Pages) do not work in HTML templates -- the &lt;code&gt;@Html&lt;/code&gt; helper is a &lt;a title="HtmlHelper Class" href="https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.htmlhelper?view=aspnet-mvc-5.2" rel="noopener noreferrer" target="_blank"&gt;class&lt;/a&gt; specifically implemented by the ASP.NET MVC framework. (RazorEngine instead has &lt;code&gt;@Raw()&lt;/code&gt; built-in to provide the &lt;a title="Encoding Values in RazorEngine" href="https://antaris.github.io/RazorEngine/Encoding.html" rel="noopener noreferrer" target="_blank"&gt;same functionality&lt;/a&gt;.) Reading the &lt;a href="https://antaris.github.io/RazorEngine/index.html" rel="noopener noreferrer" target="_blank"&gt;RazorEngine documentation&lt;/a&gt; can be informative. Tessitura appears to implement version 3.10 of RazorEngine.&lt;/p&gt;
&lt;p&gt;The fundamentals of how Razor operates still apply. The Razor syntax parser converts a .cshtml template into a C# &lt;code&gt;Execute()&lt;/code&gt; method on a generated class, which, when invoked, has access to the provided model and returns a string.&lt;/p&gt;
&lt;h2 id="mcetoc_1f6oeo60f1"&gt;Assorted Syntactic Tips and Tricks&lt;/h2&gt;
&lt;p&gt;The version of C# available in Tessitura HTML Templates in Tessitura V15.1 is C# 5.0. In Tessitura V16 there&amp;nbsp;is&amp;nbsp;support for interpolated strings, which indicates that the language has been updated to at least&amp;nbsp;C# 6.0.&lt;/p&gt;
&lt;p&gt;The version of Razor available in Tessitura HTML Templates in V15.1 is &amp;quot;Razor 3&amp;quot;, which is versioned as such because it shipped with ASP.NET MVC 3. This means technically, the &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/mvc/views/razor" rel="noopener noreferrer" target="_blank"&gt;syntax documentation linked in the Tessitura docs&lt;/a&gt; is&amp;nbsp;WAY too new for what is actually in use. This explains why &amp;quot;templating methods&amp;quot; described in these docs are not functional in Tessitura HTML Templates.&lt;/p&gt;
&lt;p&gt;Razor supports the use of a &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-5.0#functions" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;@functions&lt;/code&gt; directive&lt;/a&gt;, which gives you a&amp;nbsp;space to define additional members (methods and properties) to be added to the&amp;nbsp;generated class. Curiously, the HTML Templates editor does not syntax-color code inside of a &lt;code&gt;@functions&lt;/code&gt; directive.&lt;/p&gt;
&lt;pre&gt;@functions {&lt;br /&gt;    private string SOME_URL_CONSTANT = &amp;quot;https://example.com&amp;quot;;&lt;br /&gt;    private string LinkTag(string link) {&lt;br /&gt;        return &amp;quot;&amp;lt;a href=\&amp;quot;&amp;quot; + SOME_URL_CONSTANT + &amp;quot;\&amp;quot;&amp;gt;&amp;quot; + link + &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;@Raw(LinkTag(&amp;quot;some text&amp;quot;))&lt;br /&gt;@* Outputs:&lt;br /&gt;&amp;lt;a href=&amp;quot;https://example.com&amp;quot;&amp;gt;some text&amp;lt;/a&amp;gt;&lt;br /&gt;*@&lt;/pre&gt;
&lt;p&gt;Methods are private because&amp;nbsp;the template&amp;#39;s execution is just another method in the same class.&lt;/p&gt;
&lt;p&gt;The version of Razor used in RazorEngine 3.10 (Razor 3, shipped in ASP.NET MVC 3) also supports the &lt;code&gt;@helper&lt;/code&gt; directive, which allows you to define a kind of function that contains markup, just like the rest of the template. This allows for easy reuse of template code. Helpers were &lt;a href="https://github.com/aspnet/Razor/issues/281" rel="noopener noreferrer" target="_blank"&gt;removed in&amp;nbsp;Razor 4&lt;/a&gt;, &lt;a href="https://www.c-sharpcorner.com/article/html-helpers-in-asp-net-mvc-5/" rel="noopener noreferrer" target="_blank"&gt;reappear in ASP.NET MVC 5&lt;/a&gt;,&amp;nbsp;were removed again in &lt;a href="https://github.com/dotnet/aspnetcore/issues/5110" rel="noopener noreferrer" target="_blank"&gt;ASP.NET Core&lt;/a&gt;,&amp;nbsp;and finally &lt;a href="https://github.com/dotnet/aspnetcore-tooling/pull/334" rel="noopener noreferrer" target="_blank"&gt;code blocks were enhanced to allow for inline markup in functions&lt;/a&gt;, without the need for the &lt;code&gt;@helper&lt;/code&gt; directive. Helpers can be used as &amp;quot;templating methods&amp;quot; which are otherwise unavailable as described above.&lt;/p&gt;
&lt;pre&gt;@helper BoldMe(string content) {&lt;br /&gt;    &amp;lt;b&amp;gt;@content&amp;lt;/b&amp;gt;&lt;br /&gt;}&lt;br /&gt;@BoldMe(&amp;quot;look at me, I&amp;#39;m bold!&amp;quot;)&lt;br /&gt;@* Outputs:&lt;br /&gt;&amp;lt;b&amp;gt;look at me, I&amp;amp;#39;m bold!&amp;lt;/b&amp;gt;&lt;br /&gt;*@&lt;/pre&gt;
&lt;p&gt;The output of the helper correctly writes literal or encoded HTML like the rest of the template does.&lt;/p&gt;
&lt;p&gt;A regular function can be made to behave like a templating method by defining it with a void type and then calling the imperative &lt;code&gt;WriteLiteral()&lt;/code&gt; and &lt;code&gt;Write()&lt;/code&gt; functions, which is basically what a Razor template compiles to in the first place. Then this function can be called inside a code block (&lt;code&gt;@{}&lt;/code&gt;) to inject its output at that location.&lt;/p&gt;
&lt;pre&gt;@functions {&lt;br /&gt;    private void DIYRenderFunction(string content) {&lt;br /&gt;        WriteLiteral(&amp;quot;&amp;lt;p&amp;gt;&amp;quot;);&lt;br /&gt;        Write(content);&lt;br /&gt;        WriteLiteral(&amp;quot;&amp;lt;/p&amp;gt;&amp;quot;);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;@{ DIYRenderFunction(&amp;quot;here are my paragraph tags &amp;amp; encoded content&amp;quot;); }&lt;br /&gt;@* Outputs:&lt;br /&gt;&amp;lt;p&amp;gt;here are my paragraph tags &amp;amp;amp; encoded content&amp;lt;/p&amp;gt;&lt;br /&gt;*@&lt;/pre&gt;
&lt;p&gt;Helpers can be nested by calling &lt;code&gt;.ToString()&lt;/code&gt; on the result of the inner helper before passing to the outer. Note that if the inner helper outputs HTML, then you will need to &lt;code&gt;@Raw()&lt;/code&gt; it in the outer helper.&lt;/p&gt;
&lt;pre&gt;@helper ListMe(string content) {&lt;br /&gt;    &amp;lt;ul&amp;gt;&lt;br /&gt;        &amp;lt;li&amp;gt;@Raw(content)&amp;lt;/li&amp;gt;&lt;br /&gt;    &amp;lt;/ul&amp;gt;&lt;br /&gt;}&lt;br /&gt;@helper BoldMe(string content) {&lt;br /&gt;    &amp;lt;b&amp;gt;@content&amp;lt;/b&amp;gt;&lt;br /&gt;}&lt;br /&gt;@ListMe(BoldMe(&amp;quot;I am bold, AND in a list!&amp;quot;).ToString())&lt;br /&gt;@* Outputs:&lt;br /&gt;    &amp;lt;ul&amp;gt;&lt;br /&gt;        &amp;lt;li&amp;gt;    &amp;lt;b&amp;gt;I am bold, AND in a list!&amp;lt;/b&amp;gt;&lt;br /&gt;&amp;lt;/li&amp;gt;&lt;br /&gt;    &amp;lt;/ul&amp;gt;&lt;br /&gt;*@&lt;/pre&gt;
&lt;p&gt;A special syntax exists in Razor 3 for raw text. This is necessary when using helpers without surrounding tags. Information here: &lt;a href="https://weblogs.asp.net/scottgu/asp-net-mvc-3-razor-s-and-lt-text-gt-syntax" rel="noopener noreferrer" target="_blank"&gt;ASP.NET MVC 3: Razor&amp;rsquo;s @: and &amp;lt;text&amp;gt; syntax&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, with all of these tools in our toolbox, only one question remains... Can we avoid writing inline styles?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: c#, HTML Templates, razor&lt;/div&gt;
</description></item><item><title>Transitioning TNEW Customizations to V16</title><link>https://communitytest.tessitura.com/topical_groups/developers/w/community-developer-documentation/788/transitioning-tnew-customizations-to-v16</link><pubDate>Fri, 28 May 2021 04:26:14 GMT</pubDate><guid isPermaLink="false">fd08b0f2-65fa-4b2b-916a-cce3e88b61d0:73db91eb-b056-4847-957b-3d550d685a98</guid><dc:creator>Nick Reilingh</dc:creator><description>Current Revision posted to Community Docs Wiki by Nick Reilingh on 5/28/2021 4:26:14 AM&lt;br /&gt;
&lt;p&gt;As of April 30, 2021, version 16 of Tessitura and TNEW are announced and (at least Tessitura is) in internal alpha testing. Closed beta is expected to occur in Q3 of the calendar year.&lt;/p&gt;
&lt;p&gt;As of May 28, 2021, everything&amp;nbsp;on this page is superseded by information in the &lt;a href="https://www.tessituranetwork.com/en/Items/Videos/Webinars/2021/Open-Studio-May-2021"&gt;May 2021 Open Studio&lt;/a&gt; (45:30).&lt;/p&gt;
&lt;p&gt;TNEW Customizations (by which we mean database procedures which are invoked by hooks and URL routes inside the TNEW application) may be affected by changes in v16 in a&amp;nbsp;few important ways:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The LWP_VALIDATE_CART execution path will be deprecated (or removed? currently unconfirmed.)&lt;/li&gt;
&lt;li&gt;The legacy SOAP API is being removed, which will affect any customizations currently making use of the &amp;quot;TNEWSqlBridge&amp;quot; CLR procedures which are used to invoke SOAP methods from within a database procedure.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The usage of LWP_VALIDATE_CART will be replaced by a local procedure execution path for the same hooks. This means that in LTR_VALIDATE_CART, where you enable validation point hooks for various TNEW events, you will instead identify a local procedure to be invoked in place of LWP_VALIDATE_CART for&amp;nbsp;each&amp;nbsp;hook. In theory, this does not represent a loss in functionality, but more research is necessary to discover the best practices for refactoring existing LWP_VALIDATE_CART functionality into individual procedures. (Possibly this could be accomplished with some kind of wrapper procedure that reuses LWP_VALIDATE_CART, but many customizations use extended validation point logic that would require some changed URLs and other methods of invocation.)&lt;/p&gt;
&lt;p&gt;The SOAP API removal represents a much more impactful change for those customizations that leverage the TNEWSqlBridge CLR procedures. At present, the next-generation answer to this&amp;nbsp;has not yet&amp;nbsp;been implemented, but it does remain in scope for V16&amp;#39;s general release, and some preliminary design&amp;nbsp;intentions do exist: TNEW will provide for something akin to a webhook infrastructure, where the same validation points that exist with precart can now invoke an external web service, which presumably will be provided with some context about the session such that it can easily make API calls back to the services with session context. It is recommended to wait for this feature to be&amp;nbsp;implemented and fleshed out before rebuilding customizations that currently use the CLR procedures for v16.&lt;/p&gt;
&lt;p&gt;New development happening today against v15.1 does not have many good options, in the event that bridging to the services layer is necessary from within a TNEW customization. If you build using the CLR procedures, you will just have to rearchitect the customization as a web service when v16 is available. The only way to avoid this while staying inside the database is to instead make calls to the REST services using OLE Automation, which tends to be very delicate and challenging code.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: tnew customization, tnew, v16&lt;/div&gt;
</description></item></channel></rss>