Avoid hard-coded TCM URI in Tridion-Related Code - tridion

We often need specific items (schemas, templates, or components) in Tridion-related code. Template, Content Delivery, Workflow, or the Business Connector (Core Service) regularly need references to Tridion Content Manager URIs. We can link to components, but I typically see either hard-coded values or WebDAV URLs for everything else.
Hard-coded values
I understand hard-coding Tridion Content Manager (Native) URI's is a bad practice except for a few scenarios:
To simplify example code and make it clear what a variable is
When generated for use in Content Delivery (CD) API logic
Whenever possible we use the given API or WebDAV URLs to reference items, otherwise we must avoid using Content Porter on anything that references TCM URIs (or somehow make these references "configurable" outside of Tridion).
WebDAV URLs
WebDAV URLs seem to be better for a few reasons:
Hard-coded values in design template building blocks (TBBs) or other template formats remain intact with SDL Content Porter (breaking a relationship when moved through CMS environments, with an exception described below)
"Configuration" components that refer to specific items also do better with SDL Content Porter, though differently-named paths can "break" relationships
Use cases
In addition to having template that work well with Content Porter, I would like to localize folders and/or structure groups in lower publications. This can help with:
CMS authors that read different languages
translate item names and paths to appropriate languages
maybe help users navigate better (e.g. I suspect different-named folders may reduce confusion for where authors are in the BluePrint)
One Approach
To make references "Content Porter-friendly," at least for Template Building Blocks, I know we can use WebDAV Urls in components making sure to localize each path to the right locations in children publications. For example:
Code checks Publication Metadata
Publication Metadata points to a "config component"
Config component has paths as WebDAV URLs
As long as we set the Publication Metadata and localize the fields to the correct paths per publication, this will work for most scenarios.
Questions
Did I get this right? Is there a simpler or easier-to-maintain setup?
I believe we can alternatively use includes or map unmanaged URI in template code.
Anyone have an example of the #include approach? Do I use that at the top of a TBB and/or DWT and do references get replaced regardless of Template Mediator (e.g. will this work with XSLT Mediator, Razor Mediator, etc?)
Does the included reference work in lower publications or is this just for Content Porter? In other words, if I reference "tcm:5-123" will the template correctly reference "tcm:17-123" in publication 17?

I tend to follow a few simple rules...
There is no single valid reason to ever use a TCM ID in anything - template code, configuration components, configuration files.
If I need webdav URLs in configuration, I try to always make them "relative", usually starting at "/Building%20Blocks" instead of the publication name. At runtime I can use Publication.WebDavUrl or PublicationData.LocationInfo.WebDavUrl to get the rest of the URL
Tridion knows what to do with managed links, so as much as possible, use them. (managed links are the xlink:href stuff you see a bit all over Tridion XML).
I also tend to use a "configuration page" for content delivery, with a template that outputs the TCM IDs I may need to "know" from the content delivery application. This is then either loaded at run time as a set of configuration variables or as dictionary or as a set of constants (I guess it depends how I'm feeling that day).

Although we commonly refer to a Template Type implementation as a Template Mediator, that's not the whole story. A Template Type implementation consists of both a Template Mediator, and a Template Content Handler, although the latter is optional. Whether a given implementation will process "includes" correctly depends not on the mediator but the handler.
A good starting point in the documention can be found by searching for AbstractTemplateContentHandler.
SDL Tridion's own Dreamweaver Templating implementation has such a handler. I've just looked at the Razor implementation, and it currently makes use of the Dreamweaver content handler. Obviously, YMMV for the various XSLT template type implementations that exist.
As this is an extensibility point of SDL Tridion, whether included references will work "correctly" in lower publications depends on the implementer's view of what that would mean.
One interesting possibility is to implement your own custom handler that behaves as you wish. The template type configuration (in the Tridion Content Manager configuration file) allows for the mediator and content handler for a given template type to be specified independently, which means you could potentially customise the content handling behaviour for an existing template type.

Related

Convert query parameters to "pretty urls"

I have an Episerver site with a JobDetailsPageController with a Index method that takes a jobId parameter and creates a view with some details about that job. The urls looks something like this: https://hostname/<root-depending-on-site-tree>/jobs/?jobid=44.
What I would like is having urls on the form .../jobs/manager-position-telco-44, essentiallly creating a slug of the job title and appending the id. I have done this in the past using standard ASP.NET MVC Attribute Routing on a non-Episerver site, but EpiServer has a routing of its own that I don't know too well and can't figure out.
Also, adding non-query strings after the slash consistently sends me (no surprise) to a 404 page, so I would need to somehow customise this behaviour. I need to use EpiServers standard routing to end up at the right "parent", but ignore the latter part (the pretty bit).
Is it possible to create such urls on a normal page in page tree in EpiServer? I do understand it is possible to create static routes, but this node can be moved around like any other page so I cannot avoid EpiServer.
Please see this blog post. What you're looking for is partial routing.
#johan is right, partial routing is one way of doing this. Just wanted to add other possible solutions that might or might not match your needs.
Import data as content
Instead of serving content dynamically, you could consider importing your job ads from whatever source you have directly in content tree as separate pages below particular root page. That would give you a lot benefits - pages would be cached, it would support multiple languages, editors would see content directly in EPiServer CMS, data could be adjusted manually, etc.
This would be a good solution if your data does not change often and you need to provide a way for editor to create a new job ad manually as well.
Implement you own content provider
Another way to serve your dynamic data to EPiServer is to write your own custom content provider. You can find documentation here: http://world.episerver.com/documentation/Items/Developers-Guide/Episerver-CMS/7/Content-Providers/Content-Providers/
This solution requires more coding and is more complex, but it has some benefits as well. If one wanted, it would be possible to not just serve content from external data source, but also update that data by changing values directly in EPiServer UI.

Can Sitecore templates be used to store SQL Queries or JavaScript

We are building a Page with dynamic functionality using ASP.NET + Sitecore 7.0.
Is it practical and appropriate use Sitecore templates for:
SQL Stored Procedure Name to be invoked
JavaScript to be invoked
ColumnNames to be used etc (related to coding customization)
Or should these configuration properties remain inside the ASP.NET Project itself?
What is the primary purpose of Data Templates in Sitecore?
Are they for developer customization or customer-level customization?
The purpose of a data template in Sitecore is to define the set of fields for content items which inherit from that template. - Think of a data template as a class and the content items (pages) as instances of that class.
Templates are usually used to define the user-editable content of pages within a site, that being said you can have items to store information which is not managed by regular content editors. The question is where do you draw the line between things which should be put into Sitecore and things which should be a part of the solution. My advice is only put things in Sitecore if they need to be there. If you have to have the ability for editors or admins to configure those settings/properties.
I would say that putting SQL/ColumnNames is probably a bad idea unless you are building some sort of report builder interface in which case it may be essential?
Likewise with placing JavaScript into Sitecore; this can be OK in moderation (e.g. snippets of analytics code which content editors may want control over?). If you're placing whole libraries of JavaScript into Sitecore, you're probably doing it wrong.
One final point to note is findability/re-factorability of code: if you have code spread between Sitecore and your solution, it can make it very difficult to maintain as it is difficult to get a complete overview of code involved.

How edit and save the tridion default templates (TBB's)?

How to edit and save back the default tridion template building blocks say for Ex(Default Finish Actions) provided by SDL?
Where can i found the soucre of default TBB's? After locating and editing the TBB's, how to save back in TCM?
Editing default templates provided by SDL is not supported. They are stored in DLL and there's no way you can customize it. Maximum you can do is to disable some of the templates from being created. Alternatively you can can create your own set of default templates.
You can use the Template Builder to assemble and (test) run Compound Templates (Page and Component Templates). You can access the Template Builder from the Tools tab in the Ribbon.
The default TBBs should not be changed.
.NET TBBs are either C# fragments with the code directly accessible, or classes that implement the ITemplate interface.
Please see the following blog post to get you started:
http://www.createandbreak.net/2011/11/template-building-blocks-via-net.html
The code for (an older version of) most of the Default Template Building Blocks can be found on the Tridion forum (http://forum.sdltridion.com).
(I don't have access anymore, but maybe somebody can edit my answer and provide the link)
As others have said though, you risk getting into support trouble if you simply modify and replace them. It might be better to:
take the code from the forum as a starting point
create your own variant, making the modifications you need
compile this into a new TBB
replace the standard TBB in the Default Finish Actions with your own variant
That way you can accomplish most things, without risking support problems. When they doubt whether you broke is, you can just swap out your own variant for the original and prove them wrong.

Alfresco Share | Using dashlet into a custom page programmatically

I'm very new to Alfresco. My question is, how can we use a dashlet (created from scratch) into a page (created from scratch too)? What are the files and configurations to deal with, for including a dashlet into a page.
Moreover, the newly created page has to be similar to dashboard page but without authentication. The idea here is to do away from the default "Share" dashboard login flow.
Thanks.
A dashlet is simply a special type of web script, so yes, it is quite possible to place the same web script into a custom page by binding it into a component region.
The relationship between pages, templates, components and regions can be a little complex if you're new to Share development, so I'd recommend reviewing Dave Draper and Erik Winlof's Share Customizations Live presentation from last November's DevCon, where they introduce a sample project including an Ant build script and which includes a custom web script and page definition. The code can be downloaded from this Git repo as a basis for your own project.
You should not find that too many changes if any are required to your dashlet web script to make it work inside a custom page, but remember that if the user is unauthenticated then you will not have access to any information about them, nor will you be able to retrieve any data from the repository.
Let me try to answer this with some examples:
Alfresco page
To create an Alfresco Share page (you use share?), you need to create three files:
<TOMCAT>/webapps/share/WEB-INF/classes/alfresco/site-data/pages/my-page.xml
<TOMCAT>/webapps/share/WEB-INF/classes/alfresco/site-data/template-instances/my-page.xml
<TOMCAT>/webapps/share/WEB-INF/classes/alfresco/templates/org/alfresco/my-page.ftl
The first one defines your page, the second one defines what components (dashlets) you will use on the page, and the last one is a HTML template (in Freemarker) arranging your components.
The first two files are XML, a bit alfresco specific, but simple XML, and the last one you could put static HTML and it'd work, or you could put some freemarker macros.
What is in each of those files (examples), you can read on this page, written specially for you and this question :) (Don't ask, I felt like writing about it)
No authentication
To not use authentication, you can just put <authentication>none</authentication> in the page definition file (the first XML file).
Dashlet files
Basically, a dashlet can be at the minimum two files, usually 4-5 or something like that. The dashlet.get.desc.xml file signifies two things: desc.xml part says it's for a new component (dashlet), and get part says this component will answer to HTTP GET calls.
is usually placed somewhere bellow /webapps/share/WEB-INF/classes/alfresco/site-webscripts/org/alfresco/components. Doesn't really matter where bellow, but you would want to put it in some folder to manage all your code easier.
This file contains one important thing: url. Url defines what url your dashlet will answer to. And when you defined your page in the page definition above, you would put this url there to access the dashlet.
You could even access the dashlet directly, using the link http://localhost:8080/share/my/url/to/dashlet.
The other file, dashlet.get.html.ftl is, again, a freemarker template file. You put HTML there. You can also have a controller file for the dashlet, dashlet.get.js which prepares some dynamic content (it is written in server-side javascript and has access to some of Alfresco Javascript API).
Finally, you can put some internationalized text (translations) into bundles (basically, dashlet.get.properties, dashlet.get_DE.properties, dashlet.get_ES.properties etc, by browser lanugages).
There are also options to include client-side javascript or css files to this dashlet.
To see how exactly to assemble all this, you could try reading this page. Probably not really a good read, but it will hopefully clear some things up.
Sorry, just to be clear, you want to reproduce a share interface on an Alfresco repository, but without the login? Dashlets and interface components are webscripts, and webscripts are stored inside the repository, so in order to access them you need to be authenticated. You could use tag in the webscript xml description a runas="admin" or runas="guest" in order to achieve something. If i misunderstood, please let me know, and I'll try to help..

Access a component's fields from a custom deployer

I'm trying to create a custom deployer in Tridion 2011 SP1 that can index a component to a solr instance once published. Everything is working fine but I've come across a bit of a problem with the way it indexes the components fields.
I can access the meta data fields okay by using the Component.getCustomMeta() method and parsing the XML. Accessing the normal fields however does not seem to be possible without reading in the file that is being output and parsing the output. This is not entirely feasible as the markup may change and it seems to be a long way around doing what should (hopefully) be a simple thing.
I've had a trawl through the docs and there doesn't seem to be anything available to get the field values so am I at a loss here and will need to parse the output or am I missing something somewhere?
Content fields are not exposed as such on the delivery side, content is exposed as, not surprisingly, "content".
If you really need the fields, you need to:
Produce a "parseable" output for your component presentations
Parse the component presentations as they get published.
Look at implementations like DD4T for similar approaches.
In short - you cannot do it, because Tridion does not expose it Out of the Box. The only way to do it is by changing the content output format through a template.
We have done an alternative workaround to achieve for the similar requirement. One down side with the implementation is extra rendering of Component Presentations in XML and duplicate of xml storage in broker.
Here is what we have done:
Created a Dynamic CT (XML representation of content) GetComponentAsXML and mapped to all schemas
All the Page Templates has a C# TBB that looks up the content that we need to push to SOLR
C# TBB does the RenderComponentPresentation with above Dynamic CT GetComponentAsXML, this pushes the XML (engine.RenderComponentPresentation(component.Id, componentTemplateURI)
Deployer now gets the content in xml format, in addition to the other type of component presentations (like ascx, emebedded on page etc..)
Hope this information helps.

Resources