In Sitecore, how to change or set PageMode - asp.net

In Sitecore, I have users who are using the editing ribbon to add content to pages. However, there are some pages that I want to prevent EditMode completely from that user's role. This is based off of a branch template, so I can't just revoke privileges for each page. I need some way to set the Sitecore.Context.PageMode to be Normal.
Is there an API for setting the PageMode?

While I was unable to find a C# API, I did find that I could just use a URL Redirect that looks something like this:
if (!Sitecore.Context.PageMode.IsNormal && !IsAdministrator())
{
String id = Sitecore.Context.Item.ID.ToString();
Response.Redirect("/?sc_mode=normal&sc_itemid=" + id + "&sc_lang=en");
}
This will set the PageMode to Normal if it in any other state.

your redirect method should work, but it also turns off the PageEditor mode for other pages the editor visits after the redirect.
You could also check if the Page is in EditMode and the user is part of a certain Role and for that (sub)layout show standard .NET controls instead of the Sitecore sc-controls.
Like <asp:Literal /> instead of <sc:Text />

I would suggest that rather than redirecting the user/hard-coding this to specific pages you make create a rule and make use of the Rules Engine. This will allow you to reuse the code and turn on-/off much easier through the content editor.
There is already a condition to select the role:
/sitecore/system/Settings/Rules/Common/Conditions/Security/User Role
So you will just need to create an action to switch to Normal mode. In your action, you can call the following code:
Context.Site.SetDisplayMode(Sitecore.Sites.DisplayMode.Normal, Sitecore.Sites.DisplayModeDuration.ResetAfterRequest);
Wrap it in a check like wilsjd has suggested.
Some info on the Rules Engine if you are not familiar with it:
Decoupling through the Rules Engine
All About the Sitecore ASP.NET CMS Rules Engine

Related

Sitecore - Webforms for Marketers 2.3 - Inserting a new form into a page

I'm trying to insert a new form I created in Webforms for Marketers 2.3. I go to the page I want to insert the form on, presentation tab, form, Insert. I select the form I created but then get a message - "There are no allowed placeholders in order to insert a new form".
I then went to Layout-Placeholder Settings-Content and added Layout-Renderings-Modules-Webforms for Marketeres - Form.
No success.
I've also tried adding the form while it was and was not in the Webforms for Marketers restricting placeholders settings.
No success.
So, anyone know what I'm missing? Do I need to add a specific sitecore placeholder in the sublayout to hold the form?
To expand upon Zach's answer.
I had not been binding the placeholder settings to the page correctly. To do this I went to the Presentation tab and hit details.
I then went to the placeholder settings, and added a new entry here.
Make sure to enter the correct place holder where the form will be entered. Then go and add the form on the page. Once you choose your form and have added the placeholder correctly, it should show up here. (This was my original problem).
You need to set up which placeholders a form may be added to using the Restricted Placeholders window accessible from the Sitecore Desktop.
Steps
First, open the sitecore desktop and go to All Applications -> Web Forms for Marketers -> Restricting Placeholders:
Next, use the resulting window to configure the placeholders to which forms may be added. At least one of the selected placeholders must be present for you to add a form to the item.
I hope this helps. Good luck! :)
There is another edge case where this dialog may fail to display your available WFFM placeholders.
If you have the SSL Redirector module installed, and the form page in HTTPS mode, the dialog will fail to display the list of placeholders.
The solution is to modify the SSL Redirector to only perform redirection when Context.PageMode.IsNormal is true, and the current site name != "shell".

ASP.NET Routing optional first parameter

I am new ASP.NET Routing and have a question.
On the site I am developing, visitors sign up and create an account (with a display name), such as JohnDoe and the site personalises itself, with information pertaining to the display name.
For example (in order of the routing table, I currently have):
http://www.domain.com/ - Generic index page
http://www.domain.com/Page1 - Generic page1
http://www.domain.com/Page2 - Generic page2
http://www.domain.com/JohnDoe - Personalised index page
http://www.domain.com/JohnDoe/Page1 - Personalised page1
http://www.domain.com/JohnDoe/Page2 - Personalised page2
The above is working fine (I simply have a rule for every eventuality).
My problem is that, I now need to create asp:HyperLink controls on the pages of the site. Currently, I am using this:
NavigateUrl="<%$ RouteUrl:RouteName=ROUTENAME %>"
....in the tag of the HyperLink control
How can I, given the following addresses....
http://www.domain.com/Example - Generic example page
http://www.domain.com/JohnDoe/Example - Personalised example page
....match ROUTENAME, where the first parameter can be optional?
I could obviously create two routes, as follows....
Routes.MapPageRoute("Example_No_Displayname", "Example", "~/Example.aspx")
Routes.MapPageRoute("Example_With_Displayname", "{Code}/Example", "~/Example.aspx")
....but that means that the route names need to be different and I need to bind the Hyperlink control to match both of them.
I hope I have made myself clear and I appreciate any assistance the community may be able to give.
It would be somewhat atypical to put the username itself in the URL. The actual user identity/name would typically be extracted from some established security context/token, such as a cookie, so you could use the same URLs for both the anonymous pages and the personalized pages. Is there a specific reason you want to have the username in the URL?
You shouldn't need to match directly on the route name if you use the GetRouteUrl method. That way you can still use the two routes you need to make this work. See the full sample here.

How to break an ASP.NET website down into modules that can be enabled/disabled?

I have an ASP.NET website with some independent sections. I need a way to turn on/off the different sections (each section is in it's own directory) based on the user selection. How can I prevent the users from accessing sections that are turned off?
The solution I ended up using was to make a new class ModulePage that inherited Page. In the OnInit it would check an Abstract property I added IxModule to see if that that module was turned on or off, if it was on the page will display and if it is not the user is redirected to another page. Each page in each module has to be change to inherit ModulePage and then just specify the IxModule value. It is working very well.
you can require a log-in for those pages. I'm not sure if that's what you want.
You could look for a specific web.config app setting for each section. Each section would need a web.config setting with a sectionID app setting element.
If your using master pages, just do a check in the master's on PageLoad and check to see if the user has access to the sectionID store in the config setting. Store the section IDs that the current user has access to in the session or a cookie or something (not sure what type of security your looking for). Have one global function to lookup the app setting from the web.config. Depending on which page is calling it (from which directory) you will get the specific section's ID.
If the user does not have access redirect or show a message or something.

sitemap shortcoming

I am constrained to using a SiteMap for authentication. I am an experienced developer that has not had to use the SiteMap previously, so I am probably missing something due to the paradigm shift.
in order to get around the url limitation in SiteMap, I <doh!>cleverly</doh!> appended a querystring value:
<siteMapNode url="workflow.aspx?Location=Process1" description="Process1">
<siteMapNode url="workflow.aspx?Location=Process2" description="Process2">
the page dynamically returns the appropriate information/display based on the querystring value, and I don't have multiple stub pages. everything worked and it seemed like a good idea, until...
managers now want to access the page and edit their employee's work aliased as them, so they need to click a link like this:
href=workflow.aspx?Location=Process1&UserID=12&IDWorkflowLocation=3340
{update to explanation}
it arrives at the page correctly, but
SiteMap.CurrentNode==null;
because there is already a querystring in the sitemap it doesn't append correctly. I reaally don't want to have to make uniquely named stub .aspx pages. any ideas?
Try this:
href=workflow.aspx?Location=Process1&UserID=12&IDWorkflowLocation=3340
Have you tried programmatically modifying the site map nodes at runtime? This article explains how: http://msdn.microsoft.com/en-us/library/ms178425.aspx
I have used this in the past, but I seem to remember that the SiteMapResolve event fires on every request (even if you define it on a specific WebForm).
Hope this helps.
You need to extend the SiteMap class, override the CurrentNode property and get some of your own logic in there to catch this.

url rewriting + Asp.Net Login Form = Death

on our site we do url rewriting to generate massive amounts of database generated pages. on every page, there is a Login control for users. like this:
Internal aspx page: /DB.aspx?id=123
User visible url: /ABC/123.aspx, /ABC/456.aspx ... (url rewritten)
unfortunately, the tag on each page has an action attribute of "DB.aspx?id=123". when the user clicks the button the browser is posting to /ABC/DB.aspx?id=123 which of course does not exist.
solutions i tried:
1. change the action attribute by subclassing HtmlForm. this destroys the all other forms on the site.
2. remove the action attribute (so that the browser is always posting to the same url). this works on the rewritten pages but on "/" (the default.aspx in the root dir) i get a message that the verb post is not allowed on "/" (iis 6 and i have no control over mappings)
anybody?
Check this really nice blog post from scott gu, http://weblogs.asp.net/scottgu/archive/2007/02/26/tip-trick-url-rewriting-with-asp-net.aspx.
"Specifically, you can take advantage of the new ASP.NET 2.0 Control Adapter extensibility architecture to customize the rendering of the control, and override its "action" attribute value with a value you provide. This doesn't require you to change any code in your .aspx pages"
Check the section: "Handling ASP.NET PostBacks with URL Rewriting", I have used the adapter he posted successfully.
Ps. be aware there are some issues on asp.net when using url rewrite when using cookieless session, and the rewritten url is deeper than the original page, just like the one you have. (/abc/apage vs. /db?). The issue is right into the source code of the framework, there are workarounds but that's a whole subject (with tradeoffs :( ... you might want to have them at the same level).
Semantics maybe, but does the action attribute = "DB.aspx?id=123" or "/DB.aspx?id=123"? Assuming your URL rewriting allows pass-through to physical pages, this might be your issue.
I never did it, but I saw the code using Reflector and I guess you can fix it this way:
On the page:
this.Form.Action = null;
or:
this.Form.SetAttribute("action", null);
If that doesn't work, just set the path you want:
this.Form.SetAttribute("action", "ABC/123.aspx");
If you upgrade to ASP.NET 3.5 SP1, the action property is now properly recognized and can be set from codebehind.

Resources