Help… authorisation/authentication errors in Event Logs when calling webservices…
I’ve got a site up and running and working (seemingly) perfectly on my local machine. I deployed the site to a production server, and it’s been running for a while now, with the client populating the site with content. I also recently performed an upgrade on the site from 4.7.0 to 4.7.1.
However, I got a call from the client saying that they were unable to sort nodes. They were right-clicking on the parent node, and sorting the nodes, but when the tree re-loaded, the nodes were in their original order.
I went in and took a look, and it’s a bit of an odd one.
Before sorting, the nodes look like this:
If I attempt move the last item “Arrian…” to the top, and then hit Save, it seems to work fine, and the Sort order is renumbered from [4, 1, 2, 3] to [0, 1, 2, 3].
If I then do the same thing, and try to move “Arrian…” back to the bottom, and hit Save again, this time it doesn’t work. It moves it to the second place in the list, and the sort orders look like this:
So, it looks like it’s trying to do the sort, but failing after the first ‘shuffle’.
I went in and had a look at Event Viewer on the server, and it’s littered with numerous instances of two specific errors related to authentication/authorisation. The first one is a “Warning” which looks like this:
Log Name: Application
Source: ASP.NET 4.0.30319.0
Date: 9/28/2011 10:06:57 PM
Event ID: 1309
Task Category: Web Event
Level: Warning
Keywords: Classic
User: N/A
Computer: PRESTON
Description:
Event code: 3005
Event message: An unhandled exception has occurred.
Event time: 9/28/2011 10:06:57 PM
Event time (UTC): 9/28/2011 10:06:57 PM
Event ID: e98e825c14f949d299d5537a5e483ace
Event sequence: 18
Event occurrence: 1
Event detail code: 0
Application information:
Application domain: /LM/W3SVC/2/ROOT-1-129617212029800000
Trust level: Full
Application Virtual Path: /
Application Path: C:\inetpub\cup\
Machine name: PRESTON
Process information:
Process ID: 3304
Process name: w3wp.exe
Account name: IIS APPPOOL\ASP.NET v4.0
Exception information:
Exception type: Exception
Exception message: Client authorization failed. User is not logged in
at umbraco.presentation.webservices.TreeDataService.ProcessRequest(HttpContext context)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
Request information:
Request URL: http://xxxxxxxxxx/umbraco/webservices/TreeDataService.ashx?rnd=545e63b73cf84a72be91f9a7949a87f9&id=2217&treeType=content&contextMenu=true&isDialog=false&rnd2=35
Request path: /umbraco/webservices/TreeDataService.ashx
User host address: 150.70.64.194
User:
Is authenticated: False
Authentication Type:
Thread account name: IIS APPPOOL\ASP.NET v4.0
Thread information:
Thread ID: 5
Thread account name: IIS APPPOOL\ASP.NET v4.0
Is impersonating: False
Stack trace: at umbraco.presentation.webservices.TreeDataService.ProcessRequest(HttpContext context)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
Custom event details:
Event Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="ASP.NET 4.0.30319.0" />
<EventID Qualifiers="32768">1309</EventID>
<Level>3</Level>
<Task>3</Task>
<Keywords>0x80000000000000</Keywords>
<TimeCreated SystemTime="2011-09-28T22:06:57.000000000Z" />
<EventRecordID>1209</EventRecordID>
<Channel>Application</Channel>
<Computer>PRESTON</Computer>
<Security />
</System>
<EventData>
<Data>3005</Data>
<Data>An unhandled exception has occurred.</Data>
<Data>9/28/2011 10:06:57 PM</Data>
<Data>9/28/2011 10:06:57 PM</Data>
<Data>e98e825c14f949d299d5537a5e483ace</Data>
<Data>18</Data>
<Data>1</Data>
<Data>0</Data>
<Data>/LM/W3SVC/2/ROOT-1-129617212029800000</Data>
<Data>Full</Data>
<Data>/</Data>
<Data>C:\inetpub\cup\</Data>
<Data>PRESTON</Data>
<Data>
</Data>
<Data>3304</Data>
<Data>w3wp.exe</Data>
<Data>IIS APPPOOL\ASP.NET v4.0</Data>
<Data>Exception</Data>
<Data>Client authorization failed. User is not logged in
at umbraco.presentation.webservices.TreeDataService.ProcessRequest(HttpContext context)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
</Data>
<Data>http://xxxxxxxxx/umbraco/webservices/TreeDataService.ashx?rnd=545e63b73cf84a72be91f9a7949a87f9&id=2217&treeType=content&contextMenu=true&isDialog=false&rnd2=35</Data>
<Data>/umbraco/webservices/TreeDataService.ashx</Data>
<Data>150.70.64.194</Data>
<Data>
</Data>
<Data>False</Data>
<Data>
</Data>
<Data>IIS APPPOOL\ASP.NET v4.0</Data>
<Data>5</Data>
<Data>IIS APPPOOL\ASP.NET v4.0</Data>
<Data>False</Data>
<Data> at umbraco.presentation.webservices.TreeDataService.ProcessRequest(HttpContext context)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
</Data>
</EventData>
</Event>
So, it looks like I’m getting a “Client authorization failed” error when calling the /umbraco/webservices/TreeDataService.ashx handler. I had a dig around the source code, and this error gets thrown in this function in TreeDataService.ashx.cs:
public static void Authorize()
{
if (!BasePages.BasePage.ValidateUserContextID(BasePages.BasePage.umbracoUserContextID))
throw new Exception("Client authorization failed. User is not logged in");
}
The second one is an “Information” entry which looks like this:
Log Name: Application
Source: ASP.NET 4.0.30319.0
Date: 9/28/2011 10:07:45 PM
Event ID: 1315
Task Category: Web Event
Level: Information
Keywords: Classic
User: N/A
Computer: PRESTON
Description:
Event code: 4005
Event message: Forms authentication failed for the request. Reason: The ticket supplied was invalid.
Event time: 9/28/2011 10:07:45 PM
Event time (UTC): 9/28/2011 10:07:45 PM
Event ID: 6fe61196a8c3498bbeccdff68edd19e0
Event sequence: 81
Event occurrence: 25
Event detail code: 50201
Application information:
Application domain: /LM/W3SVC/2/ROOT-1-129617212029800000
Trust level: Full
Application Virtual Path: /
Application Path: C:\inetpub\cup\
Machine name: PRESTON
Process information:
Process ID: 3304
Process name: w3wp.exe
Account name: IIS APPPOOL\ASP.NET v4.0
Request information:
Request URL: http://xxxxxxxxx/umbraco/webservices/legacyajaxcalls.asmx/GetSecondsBeforeUserLogout
Request path: /umbraco/webservices/legacyajaxcalls.asmx/GetSecondsBeforeUserLogout
User host address: 81.157.243.222
User:
Is authenticated: False
Authentication Type:
Thread account name: IIS APPPOOL\ASP.NET v4.0
Name to authenticate:
Custom event details:
Event Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="ASP.NET 4.0.30319.0" />
<EventID Qualifiers="16384">1315</EventID>
<Level>4</Level>
<Task>3</Task>
<Keywords>0x80000000000000</Keywords>
<TimeCreated SystemTime="2011-09-28T22:07:45.000000000Z" />
<EventRecordID>1210</EventRecordID>
<Channel>Application</Channel>
<Computer>PRESTON</Computer>
<Security />
</System>
<EventData>
<Data>4005</Data>
<Data>Forms authentication failed for the request. Reason: The ticket supplied was invalid.</Data>
<Data>9/28/2011 10:07:45 PM</Data>
<Data>9/28/2011 10:07:45 PM</Data>
<Data>6fe61196a8c3498bbeccdff68edd19e0</Data>
<Data>81</Data>
<Data>25</Data>
<Data>50201</Data>
<Data>/LM/W3SVC/2/ROOT-1-129617212029800000</Data>
<Data>Full</Data>
<Data>/</Data>
<Data>C:\inetpub\cup\</Data>
<Data>PRESTON</Data>
<Data>
</Data>
<Data>3304</Data>
<Data>w3wp.exe</Data>
<Data>IIS APPPOOL\ASP.NET v4.0</Data>
<Data>http://xxxxxxxxxx/umbraco/webservices/legacyajaxcalls.asmx/GetSecondsBeforeUserLogout</Data>
<Data>/umbraco/webservices/legacyajaxcalls.asmx/GetSecondsBeforeUserLogout</Data>
<Data>81.157.243.222</Data>
<Data>
</Data>
<Data>False</Data>
<Data>
</Data>
<Data>IIS APPPOOL\ASP.NET v4.0</Data>
<Data>
</Data>
</EventData>
</Event>
I think this may be related, since they’re both web services, and they’re both related to authorisation/authentication.
Does anyone have any idea what the cause of this might be? Something related to the timeout for the lock screen? I’m at a bit of a loss….
Cheers,
Mike
Creating a custom data editor setting type
Version 4.6.1 of Umbraco introduced Data Editor Settings, which make it really easy to add custom settings to usercontrolwrapper-based data types.
It’s as simple as adding two lines of code to your user control’s code-behind like this:
[DataEditorSetting("Limit", description = "Maximum number of characters")]
public string Limit { get; set; }
There are 21 default data editor setting types, which should cover most scenarios without writing any code at all, but occasionally you may have a requirement that sits outside those types. This isn’t a problem because it’s really easy to create your own data editor setting types…
Finding ‘similar’ nodes based on Ultimate Picker selections
On a recent project, I had a “Case Study” doctype, which used the Axendo Ultimate Picker XPath to ‘tag’ each case study with particular attributes using a CheckBoxList (so multiple attributes can be selected for a case study).
On each case study page on the website, I then needed to be able to show a selection of other case studies which were ‘similar’ to the current one, based on the attributes selected.
The solution I came up with is an XSLT extension which:
- examines the current node’s selected attributes;
- loops through all other case studies and looks at how many attributes match the current node;
- creates a generic list of custom objects to store each case study node together with the “number of matches”;
- sorts this list in descending order of “number of matches”;
- shuffles this list so that all case studies with equal number of matches are in a random order;
- returns an XPathNodeIterator to the XSLT containing the required number of node IDs
URL Rewriting and SEO
After reading Scott Guthrie’s article – Fix Common SEO Problems Using the URL Rewrite Extension – here is my attempt at implementing rewriting rules for an Umbraco site. It’s essentially the same as Scott’s article, with a few tweaks for Umbraco.
- Canonical home page – I’ve added a hard-coded canonical rewrite of the root content node (as the root node in Umbraco can be accessed via /nodename.aspx as well as /default.aspx).
- Directory URLs – I’m using DirectoryUrls for my Umbraco site, which allows the URL with or without the “.aspx” extension, so I’ve added a rule to trim the “.aspx” extension (except in the /umbraco folder).
- Canonical host name – This example redirects all requests with a “www” prefix to the equivalent URL without the www.
- Trailing slash – I’m removing trailing slashes from all requests.
- Lower case – I’m forcing all URLs to lower-case, but I’ve added exclusions for static assets (css, images, js) as well as .axd resource files. Again, I’ve excluded the /umbraco folder.
Here’s the code from my web.config:
<rewrite>
<rules>
<!-- SEO: Canonical home page - redirect from home page /nodename to home page with no path -->
<!-- assumes root node is called "Home" -->
<rule name="Canonical home page" stopProcessing="true">
<match url="^(home|default\.aspx)$" />
<action type="Redirect" redirectType="Permanent" url="/" />
</rule>
<!-- SEO: Using Directory URLs, so force trim all .aspx -->
<!-- exclude umbraco folder -->
<rule name="Trim aspx for directory URLs" stopProcessing="true">
<match url="(.*)\.aspx$" />
<conditions>
<add input="{REQUEST_URI}" pattern="^/umbraco/" negate="true" />
</conditions>
<action type="Redirect" redirectType="Permanent" url="{R:1}" />
</rule>
<!-- SEO: Canonical host name - consistent use/absence of www. -->
<!-- in this case, we are redirecting to host name without www -->
<rule name="Canonical host name" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" pattern="^yourdomain\.com$" negate="true" />
</conditions>
<action type="Redirect" redirectType="Permanent" url="http://yourdomain.com/{R:1}" />
</rule>
<!-- SEO: Remove trailing slash from URLs -->
<rule name="Remove trailing slash" stopProcessing="true">
<match url="(.*)/$" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Redirect" redirectType="Permanent" url="{R:1}" />
</rule>
<!-- SEO: Force lower-case for URLs -->
<!-- exclude umbraco folder, and all static requests to images, css, js and axd resource files -->
<rule name="LowerCaseRule1" stopProcessing="true">
<match url=".*[A-Z].*" ignoreCase="false" />
<conditions>
<add input="{REQUEST_URI}" pattern="^/umbraco/" negate="true" />
<add input="{URL}" pattern="^.*\.(axd|css|js|jpg|jpeg|png|gif)$" negate="true" ignoreCase="true" />
</conditions>
<action type="Redirect" redirectType="Permanent" url="{ToLower:{URL}}" />
</rule>
</rules>
</rewrite>
These are all 301 permanent redirects.
Feel free to suggest improvements or amendments – trying to get to a “best-practice” approach, so all advice is welcome!
Cheers,
Mike
Create media folder when a content node is published
On my site, I have a “Client” document type. When someone creates (or publishes) a “Client” on the site, I want to automatically create a media folder in a particular location (Media/Case Studies/{client name}) – if it doesn’t already exist – ready for the user to upload images for case studies for that client.
I’ve written an event handler, which works, but is massively inefficient. It seems to me that there must be a much easier way of doing this.
See below for the current event handler (ick) – anyone got a tidier solution?
public class CreateClientMediaFolder : umbraco.BusinessLogic.ApplicationBase
{
public CreateClientMediaFolder()
{
Document.AfterPublish += new Document.PublishEventHandler(Document_AfterPublish);
}
void Document_AfterPublish(Document sender, PublishEventArgs e)
{
if (sender.ContentType.Alias == "Client")
{
string clientName = sender.Text;
MediaType folderType = MediaType.GetByAlias("folder");
Media[] m = (Media[])Media.GetMediaOfMediaType(folderType.Id);
foreach (Media f in m)
{
if ((f.Text == "Case Studies") && (f.ChildCount > 0))
{
// check to see if this Media item has a child called clientName
bool folderExists = false;
// see if folder already exists
Media[] children = (Media[])f.Children; // ick - iterating through Children v bad
foreach (Media child in children)
{
if (child.Text == clientName)
{
folderExists = true;
break;
}
}
if (!folderExists)
{
Media newFolder = Media.MakeNew(clientName, folderType, new User(0), f.Id);
// sort Case Studies media folder (f) into alphabetical order?
}
break;
}
}
}
}
}
The problem with packages in a multiple-developer environment.
I know this comes up over and over again, but I’m trying to come up with a reasonably robust way of having multiple developers work on the same Umbraco project, while enabling source-control.
The accepted wisdom seems to be to use a shared database, a clean install of Umbraco, and a separate (source-controlled) Web Application Project which copies the necessary files (project dll, css, templates, user controls, xslt, images etc) across to the Umbraco site using post-build events in Visual Studio.
The idea is that, if a new developer needs to jump onto the project, they do a clean install (pointing to the shared database), grab the separate WAP from source control and do a build and they should be up and running.
In reality, though, it seems to be more complicated than that.
Package problems…
If packages have been installed during the development process (either local packages, or from the repository), then it’s possible that they will install new files, or update existing files in the Umbraco site. These files will then be unavailable (or out-of-date) on any new developer set-up as detailed above, as well as any other existing developers working on the project (as the changes will be outside source-control).
One option could be to keep track of all packages installed during the development process (possibly in a text file in the WAP), and then have the new developer install all the packages (in the same order) when they create their new set-up.
A package can also make changes to the database. If packages are re-installed by a new developer, but a shared database is in use, they may be overwriting database entries which have been changed since the package was originally installed.
Additionally, some of the changes made by a package may be to existing config files, which means that config files can’t just be copied across from the WAP, as any config changes made by a package will be overwritten next time the WAP is built.
The more I think about this, the more it seems unworkable in a real development environment, as the risk of the projects on the development machines becoming out of sync seems prohibitively high.
The alternative, though, seems to be a single-developer-per-project approach, which also isn’t commercially realistic.
Anyone found a neat workable way round these kinds of issues?
Thanks,
Mike
Master page weirdness resolved!
Found it, and it’s an odd one….
In the previous post, after creating the template in Umbraco, I created a master page file in Visual Studio, and copied/pasted the template code from the Umbraco back-end into my new template file in VS.
It turns out that an invisible rogue (non-ANSI-Latin I) character is appended when you copy/paste the code from the Umbraco editor. Opening the master page file in TextPad revealed the rogue character and converted it to a “?” at the end of the file.
Deleting the “?” and saving the file back to the VS solution, and then building copies the file *without the rogue character* to Umbraco, and all is good…
See screencast:
I’ll log something on Codeplex…
Cheers,
Mike

