Convert query parameters to "pretty urls" - asp.net

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.

Related

Is the best way to update sections of a dynamic webpage - by rewriting the file every time?

At my company (a custom retail e-commerce website) we have a homepage with various sections on the page for promotions/sales/events. These sections may appear in any order, one after the other. The order of the sections are saved in a database table called mainpage_sections with an order column (int).
The present method we use for updating the homepage when the order of sections is changed, is by running a callback method that automatically rewrites the aspx View file itself, in HTML, with the new order of the sections. It does not pull the sections from the database and dynamically render them according to their order.
This struck me as being opposite to best principles and very messy. I asked why we didn't use a database read instead, but I was told that since this website is visited thousands of times a day, and the order of the sections rarely changes, it makes more sense to update the file itself, instead of running thousands of extra database reads just for people visiting the homepage of the website.
Does this approach make sense? What is the best-principle, recommended approach here? Is something like output caching a better choice?
Overwriting a code file does seem weird. What if you stored the ordering in a separate JSON file, and only overwrote the JSON file?

Kentico Web Part Zone(s) generated by Transformations

I am using a Repeater web part in Kentico to pick out pages from the content tree, to generate nicely repeatable snippets of structured HTML, based on an ASCX transformation. (No surprises here - its been working great!).
However, a new requirement landed whereby alongside the existing HTML structure mentioned above, each repeated item must also have an area where we can add any amount of additional content; based on other web parts.
I have previously written a few "layout" type web parts; implementing CMSAbstractLayoutWebPart, as described here, which has allowed me to generate a repeating amount of web part zones, so I feel like I'm half way there. The issue with that though is that as it stands, I don't seem to be able to make use of the great power and flexibility of the transformations on the page type (which I really think I need to do, and seems like it should be possible..).
I thought I may be able to specify the WebPartZone control in the transformation markup directly, like in the following:
<%# Register Src="~/CMSInlineControls/WebPartZone.ascx" TagName="CMSWebPartZone" TagPrefix="cms" %>
<cms:CMSWebPartZone ZoneID="ZoneIDHere" runat="server" />
<div>
<h3><%# Eval("Heading") %></h3>
<p><%# Eval("Summary") %></p>
</div>
But the design view doesn't seem to pick up the web part zone; so I'm assuming the page lifecycle may not allow me to do this as I'd hoped.
So what I would like to know is:
Is it possible to include WebPartZone control in a transformation such that I can then bring in new web parts in Design view?
If not, what is the recommended way to go about this? (If a custom web part is the way to go, I'd like to clone the Repeater web part in the first instance, as many of its existing properties will be needed - but presumably this must still inherit from CMSAbstractLayoutWebPart?
Thanks!
Update
Good point about the editor's experience; I would definitely like to keep this as consistent as possible. The issue for me is that the requirements that drive my data structures are not always fully understood - and are certainly subject to change. Also, they are liable to vary (albeit subtly) across different products. So I've been trying to keep templates and page types more or less the same across the board, and push out the differences into page properties that drive web part config through macros. So given that the transformation approach won't work, I expect a custom web part is the right fit for me.
I shall post my findings!
I think adding a web part zone into transformation is not a right direction as web part zone should be a part of page template (not transformation) in order to utilize it.
I'd probably try to organize my content so each item you currently showing in the repeater has any number of child pages (potentially of a different type) and use something like hierarchical viewer in order to present all of them on the page. It allows using different transformation based on either page type or node level. Another advantage of this approach is that you keep editors experience consistent.
In the end, I was able to use transformation markup to specify the generation of web part zones. I went down the route of creating a custom web part that inherits from CMSAbstractLayoutWebPart, rather than using CMSRepeater web part or similar...
Here's a breakdown of things I needed to do this:
Gave the custom layout-type web part some properties with which to query the content tree, and supply them to a TreeProvider.SelectNodes() method in the web part code once it has initialised (by overriding the OnInit() method)
Gave the web part a TransformationName property so that the raw markup can be retrieved using TransformationInfoProvider.GetTransformation(this.TransformationName)
Used the markup above and resolved macros within it using each node from the node query
Example of macro resolution code (HTML transformations with macros)
protected virtual string ResolveNode(TreeNode node)
{
var resolver = this.ContextResolver.CreateChild();
resolver.AddAnonymousSourceData(node);
return resolver.ResolveMacros(rawTransformationMarkup);
}
Then I go looking for placeholder text in the transformation markup and use the methods available in the CMSAbstractLayoutWebPart parent class(es), as detailed here, to Append() the resolved markup and also call AddZone() as necessary to tap into the response string builder
Summary: The great functionality of the API allowed me to completely avoid the use of any repeater controls. I could generate web part zones as part of the layout web part usual layout generation process.
It would be nice if I could figure out how to resolve the expressions in SCRIPT tags in ASCX transformations to complete the story, but by using HTML transformations I can use the above to accomplish what I need.

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.

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..

ASP.NET - best method for website where user can create articles (like a blog)

I'm an ASP.NET newbie, but not so new at programming in general.
I'm creating a commercial website, and I want to allow an admin to add new articles (an article consists of text, images and various properties such as category).
I am trying to decide the optimal Modus Operandi. This site is commercial, so SEO is a major consideration. This means that I want each url to be "unique". That is, if someone navigates to an article about raccoons, he should be redirected to www.mysite.com/articles/raccoons. This means - I can't have one page that loads the appropriate article dynamically a-la AJAX (gotta use deep-linking)
So how exactly do I do this? suppose the admin entered his text, uploaded the images and set the article properties. I create a new subfolder, save the images to the server (I understand that saving images to a DB is a big no-no), their addresses in a DB, and the content itself to the DB. But now what?
How do I go about creating the actual page?
Is there a function for creating a new aspx file? then what about its corresponding cs file? Or is it unwise to use aspx? Maybe plain html? but then how does it work with my site's master page? Or maybe just create another copy of a general aspx file which is populated with an article according to a parameter?
I would like to know what is the "smartest" approach before I dive in too deep.
You can Consider ASP.Net MVC for this. What you need is more like a Content Management System rather than a Blog, as you mentioned an administrator will add articles.
By Using ASP.Net MVC, you have a very clean implementation there, your urls will stay as you need it for SEO, You dont have to create aspx pages on the fly but the framework will let you deal with new urls from your class files.

Resources