Posted by kipusoep on jan 3, 2012 in
Asp.NET,
C#.NET,
IIS,
MS SQL,
Umbraco
So this is the second blogpost I’m writing about Umbraco, ELMAH and authentication.
My previous blogpost wasn’t really good, because with forms-authentication authenticated members could also access elmah, which is not the way to go. So I’ve dropped MADAM.
This time I’ve managed to get both forms-authentication for umbraco and basic/windows-authentication for ELMAH. The trick is to create a subfolder called ‘elmah’, which we’ll convert to an application and enable basic/windows-authenticatioin for this app.
This is kind of tricky, because all web.config configurations will be inherited by the web.config for any sub-application. Also ELMAH filters the errors in the database based on the current Application string property, for example “/LM/W3SVC/24/ROOT”, but if you configure the elmah.axd handler in a sub-application, the application for the handler will be “/LM/W3SVC/24/ROOT/elmah” and you won’t see any logged errors of the main application.
To overcome this I had to make changes to ELMAH’s source code. I’ve cloned the Mercurial repo and changed some files. This way it’ll be easy to keep it up-to-date without losing my changes. There’s one extra thing I’ve changed; I’ve disabled logging the current user’s password, because of privacy reasons.
A step-by-step guide to get ELMAH and umbraco to play nicely side-by-side:
- Download this zipfile (which contains 3 other zip files)
- Unzip the file ‘1. elmah.zip‘ in the root of your project and include the whole folder in Visual Studio (so it’ll get deployed with WebDeploy)
- Unzip the file ‘2. elmah assemblies.zip‘ somewhere in your project, where all third party assemblies reside and optionally add a reference in Visual Studio (if you’d like to use Error Signalling and if you’re using something like WebDeploy)
- Unzip the file ‘3. sqlce assemblies.zip‘ in the root of your project and include both folders in Visual Studio. Inside VS select all files underneath the AMD64 and X86 folders and go to their properties. Set ‘Build action’ to ‘None’ and ‘Copy to Output Directory’ to ‘Copy if newer’ (screenshot below)

- Add the following to your web.config:
<system.data>
<DbProviderFactories>
<remove invariant=”System.Data.SqlServerCe.4.0″ />
<add name=”Microsoft SQL Server Compact Data Provider 4.0″ invariant=”System.Data.SqlServerCe.4.0″ description=”.NET Framework Data Provider for Microsoft SQL Server Compact” type=”System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91″ />
</DbProviderFactories>
</system.data>
- Add the following to your web.config (inside the runtime\assemblyBinding element):
<dependentAssembly>
<assemblyIdentity name=”System.Data.SqlServerCe” publicKeyToken=”89845dcd8080cc91″ culture=”neutral” />
<bindingRedirect oldVersion=”0.0.0.0-4.0.0.0″ newVersion=”4.0.0.0″ />
</dependentAssembly>
- If you were using ELMAH already in your project, remove any elmah.axd handlers in your web.config
- If you’ve registered none-umbraco httpModules, please add them to the removal list in ~\elmah\web.config so they won’t be loaded for the ELMAH sub-application
- Open IIS Manager and navigate to your website underneath ‘Sites’. Expand you site so you’ll see the directories underneath it and right-click the ‘elmah’ folders and select ‘Convert to Application’ and select the AppPool your site is running in
- Next make sure this newly created sub-application is selected in the tree and open up ‘Authentication’. Enable ‘Basic Authentication’ and you’re ready to start logging and reading errors!
The ELMAH page can be accessed by navigating to ‘/elmah/’ or just ‘/elmah/elmah.axd’.
The SQL CE error log database will be stored in ‘~/App_Data/’. You could monitor the size of this file as it will grow to max 1024MB.
Posted by kipusoep on nov 29, 2011 in
Asp.NET,
C#.NET,
IIS,
Umbraco
Warning – read first: There is an issue with this approach; when you’re authenticated via Forms Authentication (like being logged in on the website), you’re ALSO allowed to access elmah.axd.
I have looked for a solution, but I haven’t figured one yet. Do you have the solution? Please reply on this blog and I’ll include your information.
We’re using
ELMAH in every single umbraco project we built, it’s an awesome error logging module for .NET.
To protect ELMAH, we were using Basic Authentication, which is built-in in .NET and IIS.
But since umbraco v4.7.1, umbraco relies on Forms Authentication for the Members. As you might know, it’s impossible to have Basic AND Forms Authentication enabled at the same time, so the quick conclusion was to go with Forms Authentication, else umbraco’s membership provider wouldn’t work anymore.
So now we have a problem: whenever someone’s logged in as a member, he/she can access elmah.axd (assuming that you’ve got elmah.axd protected as described here).
Wouldn’t it be awesome if we could still use some sort of Basic Authentication AND Forms Authentication? Ofcourse! That’s where MADAM steps in (from the creator of ELMAH, isn’t that coincidental?).
So here’s a guide how to set-up your project (which I assume already has ELMAH running and configured, as described here for example):
Add the MADAM assembly to the bin folder (+ reference if you use VS)
Some stuff in the web.config:
- Add sectionGroup for madam:
<sectionGroup name="madam">
<section type="Madam.FormsAuthenticationDispositionSectionHandler, Madam"/>
<section type="System.Configuration.SingleTagSectionHandler, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</sectionGroup>
- Add httpModules to system.web/httpModules and system.webServer/modules:
<add name="FormsAuthenticationDisposition" type="Madam.FormsAuthenticationDispositionModule, Madam"/></pre>
<!-- IMPORTANT! The actual HTTP authentication module MUST appear AFTER the FormsAuthenticationDisposition module. -->
<add name="BasicAuthentication" type="Madam.BasicAuthenticationModule, Madam"/>
- Extend the <authentication mode=”Forms” /> tag in <system.web>:
<authentication mode="Forms">
<forms>
<credentials passwordFormat="SHA1">
<user name="elmah" password="<<<YOUR_SHA1_HASHED_PASSWORD>>"/>
</credentials>
</forms>
</authentication>
- Add a location element to protect elmah.axd:
<location path="elmah.axd">
<system.web>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</location>
- Add a madam element, like after the elmah element:
<madam>
<userSecurityAuthority realm="ELMAH" provider="Madam.FormsUserSecurityAuthority" exposeClearTextPassword="false "/>
<formsAuthenticationDisposition>
<discriminators all="true">
<!-- This discriminator helps detect redirection to the Forms login page. -->
<discriminator inputExpression="Response.RedirectLocation" pattern="login\.aspx\?returnurl\=" type="Madam.RegexDiscriminator"/>
<!-- These discriminators are based on the various locations and requests for which Forms should be discriminated. The conditions expressed by these discriminators are OR'ed together in the absence of the all attribute. -->
<discriminator>
<discriminator inputExpression="Request.RawUrl" pattern="^/elmah\.axd"/>
</discriminator>
</discriminators>
</formsAuthenticationDisposition>
</madam>
That’s “all”
Good luck!
Posted by kipusoep on nov 9, 2011 in
Asp.NET,
C#.NET,
Umbraco
Lately I’ve been upgrading some websites built on umbraco 4.0.x.
Most of these websites were using object tags in the TinyMCE editor to show rich content, like flash, but since we upgraded those websites to 4.7.1, the object tag wasn’t displayed anymore in the HTML of the TinyMCE editor.
So when changing and publishing such page, the object tags get removed from the front-end, because they were missing in TinyMCE itself.
This is really annoying ofcourse, because some pages couldn’t be edited anymore. I’ve looked around the net for solutions/other people experiencing the same problem.
There are some bug reports on Codeplex, but these are other problems than I was facing.
So I just thought; let’s upgrade TinyMCE included in umbraco from version 3.4 to 3.4.7 and this fixed my problem.
There are some bug reports on Codeplex to upgrade TinyMCE (and jQuery) to the latest version. Please vote for them!
Posted by kipusoep on jul 23, 2010 in
Asp.NET,
C#.NET,
CSS,
Umbraco,
XHTML
Using Umbraco with VS2010
… and masterpages, jQuery vsdoc, dotless, SquishIt
Welcome all to this magnificent blogpost about using Umbraco 4.5 with Visual Studio 2010 and everything you’ll need to know about some other tools!
First things first; we, at InfoCaster, use Visual Studio 2010 and .NET to develop our Umbraco web applications. We try not to use XSLT, just because .NET is much better
and everyone at InfoCaster knows .NET, unlike XSLT. I always like to say that .NET with LINQ can do like everything, but XSLT can’t or does things inefficient. It’s not even possible to assign a value to a variable for a second time. How variable is that ‘variable’ then? But that’s another discussion!
So a few months ago I started developing our own ‘Umbraco Website Starter project’. It’s like a clean Umbraco installation wrapped in a Visual Studio solution, with some extra’s, like some handy extension methods, pre-installed packages and default properties for the homepage (title prefix/suffix, Google analytics code, meta data etc.).
Now I migrated it to Umbraco 4.5 and removed all packages and installed the necessary packages again. I’d like to tell you all what I did and how.
Blueprint CSS
We’re using Blueprint CSS from now on to have a good start on creating our templates and stylesheets, this is combined with SquishIt.
.Less
We’re using .Less for our custom stylesheet. You can read everything about how to set this up in VS(2010), so I’m not going to explain that: http://www.dotlesscss.com/
I’m using SquishIt to generate the CSS files out of the .css.less files. These .css.less files can be opened with VS2010 with css highlighting / autocompletion by using this plug-in: http://visualstudiogallery.msdn.microsoft.com/en-us/dd5635b0-3c70-484f-abcb-cbdcabaa9923
<%= Bundle.Css()
.Add("~/css/blueprint/screen.css")
.Add("~/css/style.css.less")
.WithMedia("screen, projection")
.Render("~/css/output/screen_#.css")
%>
SquishIt and jQuery vsdoc
SquishIt download page: http://www.codethinked.com/post/2010/05/26/SquishIt-The-Friendly-ASPNET-JavaScript-and-CSS-Squisher.aspx
VS2010 has better intellisense features when it comes to JavaScript. So why not use jQuery with vsdoc and let SquishIt minimize and combine it for production environments?
Great idea! BUT this is how SquishIt requires it’s mark-up:
<%= Bundle.JavaScript()
.Add("~/js/jquery-1.4.2.js")
.Add("~/js/jquery-ui-1.8.1.js")
.Render("~/js/combined_#.js")
%>
Hmm… That’s not going to work with intellisense/vsdoc, because Visual Studio looks for real <script> tags…
So what I did is this:
<asp:Literal runat="server" ID="ltlScripts">
<script type="text/javascript" src="~/scripts/jquery-1.4.2.js"></script>
</asp:Literal>
Then you can just add any JavaScript reference you’d like
To enable vsdoc intellisense, you must also have the vsdoc file in the same folder as the realy jQuery file
The literal is being parsed in code-behind by using regex and it gets rewritten:
Regex scriptTagRegex = new Regex(@"<script(.*)type=""text/javascript""(.*)src=""(.*)"".*></script>");
IJavaScriptBundle jsBundle = Bundle.JavaScript();
IJavaScriptBundleBuilder jsBundleBuilder = null;
foreach (Match match in scriptTagRegex.Matches(ltlScripts.Text))
{
if (jsBundleBuilder == null)
jsBundleBuilder = jsBundle.Add(match.Groups[3].Value);
else
jsBundleBuilder.Add(match.Groups[3].Value);
}
ltlScripts.Text = jsBundleBuilder.Render("~/scripts/output/js_#.js");
Simple as that
(using SquishIt.Framework.JavaScript)
Default meta properties
(title prefix/suffix, meta tags, meta description, meta title, favicon, Google analytics)
This is the markup I have as <head>:
<head runat="server">
<title>Title will be filled from codebehind</title>
<!-- meta data -->
<meta name="author" content="InfoCaster B.V." />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="keywords" content="<%= CurrentNode.GetPropertyValueRecursive("pageKeywords") %>" />
<meta name="description" content="<%= CurrentNode.GetPropertyValueRecursive("pageDescription") %>" />
<asp:Literal runat="server" ID="ltlFavicon">
<!-- favicon -->
<link rel="shortcut icon" href="#HandledInCodeBehind" type="image/x-icon" />
</asp:Literal>
<!-- css -->
<%= Bundle.Css()
.Add("~/css/blueprint/screen.css")
.Add("~/css/style.css.less")
.WithMedia("screen, projection")
.Render("~/css/output/screen_#.css")
%>
<%= Bundle.Css()
.Add("~/css/blueprint/print.css")
.WithMedia("print")
.Render("~/css/output/print_#.css")
%>
<!--[if lt IE 8]>
<%= Bundle.Css()
.Add("~/css/blueprint/ie.css")
.WithMedia("screen, projection")
.Render("~/css/output/ie_#.css")
%>
<![endif]-->
<asp:ContentPlaceHolder runat="server" ID="cphHead" />
<!-- js @ bottom -->
<asp:Literal runat="server" ID="ltlGoogleAnalytics">
<!-- Google Analytics -->
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', '{0}']);
_gaq.push(['_trackPageview']);
(function () {{
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
}})();
</script>
</asp:Literal>
</head>
The title, favicon and Google analytics gets set from code-behind.
The meta tags/description are filled by using a recursive extension method I wrote.
I also added a content placeholder in the head and also at the end of the XHTML document, right before the </body>, so it’s possible to load custom CSS (head) and JS (bottom) per sub masterpage.
This is the code-behind which belongs to this mark-up:
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
#region Page stuff (google analytics, favicon, title)
// Google analytics
if (!string.IsNullOrEmpty(CurrentNode.GetPropertyValueRecursive("analyticsCode")))
ltlGoogleAnalytics.Text = string.Format(
ltlGoogleAnalytics.Text,
CurrentNode.GetPropertyValueRecursive("analyticsCode")
);
else
ltlGoogleAnalytics.Visible = false;
// Favicon
int faviconId;
if (!string.IsNullOrEmpty(CurrentNode.GetPropertyValueRecursive("favicon")) && int.TryParse(CurrentNode.GetPropertyValueRecursive("favicon"), out faviconId))
ltlFavicon.Text = string.Format(
"{0}{1}{2}",
ltlFavicon.Text.Substring(0, ltlFavicon.Text.IndexOf("href=\"") + ("href=\"").Length),
new Media(faviconId).getProperty("umbracoFile").Value,
ltlFavicon.Text.Substring(ltlFavicon.Text.IndexOf("href=\"\"") + ("href=\"").Length)
);
else
ltlFavicon.Visible = false;
// Title
Page.Title = string.Format(
"{0}{1}{2}",
CurrentNode.GetPropertyValueRecursive("titlePrefix"),
CurrentNode.GetPropertyValueOrDefault("pageTitle", CurrentNode.Name),
CurrentNode.GetPropertyValueRecursive("titleSuffix")
);
#endregion
}
Easy right?
Extension methods
I wrote some extension methods to ease some default tasks.
These extension methods are duplicated, for use in multilingual sites.
You can download the .cs file right here, it contains enough comments/documentation. Look at the end of this post
Masterpage intellisense VS2010 bug
There is a bug in VS2010 when using Umbraco’s masterpage as root master (umbraco.presentation.masterpages._default). The intellisense doesn’t work anymore. I’ve created a bug report on Microsoft Connect about this: https://connect.microsoft.com/VisualStudio/feedback/details/567771/no-asp-tag-intellisense-in-some-cases-when-using-masterpages
I’ve got a ‘dirty’ work-around. I don’t know if this work-around works with the ‘Canvas-editing’ feature in Umbraco (we and our customers don’t use it).
Just let every main masterpage (with <html> tags) inherit: umbraco.presentation.masterpages._default
#Protip: Creating new templates
When using Visual Studio, it’s nice to have code-behind files for your templates (at least, that’s how we do stuff). If you create a template in Umbraco, it creates a masterpage without code-behind…
Then you would have to add a code-behind manually, link it with the mark-up and create designer file. That sucks right?
Just do this:
- Create a nested masterpage in VS and use your ‘master’-masterpage as masterpage in the masterpages folder. Lol, there’s a lot of ‘masterpage’ in that sentence hehe.
- VS creates a masterpage for you with code-behind, sweet!
- VS opens the mark-up of this newly created masterpage, keep it opened!
- Then go to your Umbraco back-end and create a template like you would normally do. Give it the same name as you defined in step 1.
This should create an Umbraco template by using the already created masterpage as file.
- Now return to Visual Studio. It should notify you that the file has changed and gives you the option to reload the file. Reload and then use CTRL+Z to undo the changes made by Umbraco (else the code-behind won’t be linked to the mark-up) and save it.
- You’re done!
Downloads
‘Master’-Masterpage with code-behind: StefanKip.InfoCaster.Umbraco.masterpage
Extension methods: UmbracoExtensions.cs (remove ending .txt)
Posted by kipusoep on mei 12, 2010 in
Asp.NET,
C#.NET,
Umbraco
I just released an update for the 301 URL Tracker for Umbraco: http://bit.ly/301URLTracker
Changelist
- [Bug fix (critical)] The 404 Handler returned ’301 URL Tracker’ as HTTP Status instead of ’301 Moved Permanently’
- [New feature] View/manage Url Mappings on the node itself with the new 301 URL Tracker Datatype (ofcourse you must add a property, with the 301 URL Tracker Datatype, to a Document Type and !!!REMOVE IT WHEN YOU ARE GOING TO UN-INSTALL THE 301 URL TRACKER !!!)
- [New feature] Create RegEx Url Mappings (url mappings will be tried to match first, if no match found RegEx matching kicks in, ordered by Insertion date ascending)
- [New feature] Option to disable the 301 URL Tracker (add to appSettings: <add key=”infocasterDisable301URLTracker” value=”true” />
- [New feature] When clicking on the ’301 URL Tracker’ node in the tree, there’s a button to view all not found requests
Posted by kipusoep on apr 28, 2010 in
Asp.NET,
C#.NET,
Umbraco
Just released my second package for Umbraco; the 301 URL Tracker.
I could really use some feedback for my graduation report, so please leave some when you’ve given it a run!
Release notes
About the 301 URL Tracker package
The 301 URL Tracker package is created by InfoCaster. The original idea comes from Soeteman Software.
The purpose of the 301 URL Tracker package, is to create some SEO friendlyness.
Search engines crawl your website and store links to all pages within your website.
The 301 URL Tracker keeps track of all the url changes of these pages:
- When a document is moved it gets a new url
- When a document is renamed it gets a new url
The old urls are stored and when someone requests one of these old urls, they are automatically transfered to the correct new url, with a 301 HTTP response.
Search engines recognize this HTTP response and replace the old location with the new location.
All features of the 301 URL Tracker package:
- Keeps track of url changes and redirects requests from these ‘old’ urls to the new ones
- Ability to create custom url mappings, e.g. when you get a new website, the urls can be changed. This way you can map old urls to new ones
- Remove any url mapping; automatically tracked urls and custom mapped urls
Some hints
- When a document gets a new url, the old url is saved and the document is automatically added to the 301 URL Tracker tree (including all child documents)
- When one wants to create a custom url mapping, just right-click on the 301 URL Tracker node and click ‘Create’. Select the document to create the custom url mapping for
- The reason for an automatic mapping is shows next to the mapping url. When creating custom mappings, you can add your own note to the mapping
- To delete all url mappings for a document, just right-click on the document in the 301 URL Tracker tree and press ‘Delete’. Important note: the documents underneath the deleted one will NOT be removed, although it looks like they are
- The url mappings are ordered by date descending. To view the creation date of a mapping, hover with the mouse over the url of a mapping entry
- When a document with configured url mappings gets recycled, it won’t show up in the 301 URL Tracker tree anymore (and the url mappings won’t work)
- When a document gets moved back from the recycle bin, it shows up again in the 301 URL Tracker tree. When a document gets deleted for real, the url mappings get deleted too
Graduation project
This package is part of my graduation project. Yes, I’m trying to graduate with Umbraco as graduation topic. So I would like to call in your help!
I really need feedback for my graduation report. So please, if you have a spare moment, leave some feedback in the ‘Feedback forum’ below.
Thank you all very much in advance!
Requirements
Tested on
- .NET 3.5
- SQL Server 2008
- Windows 7 Ultimate
- IIS 7.5
Posted by kipusoep on mrt 28, 2009 in
Asp.NET,
C#.NET,
IIS
The last weeks am employee of one of our clients and me had some problems getting a project, I’ve build, running on IIS 6.
There was a website configured in IIS for the main webapplication, which was already running on their server, and my project would be placed in a subdirectory of that webapplication.
So I deliverd the project with the following files:
- Aspx pages
- A bin directory
- Stylesheet directory
- Images directory
- No web.config, because the root application already has one
We just couldn’t get it to work properly and I thought IIS was caching assemblies, even after a IIS reset and server reboot.
After some time someone found the problem; the assemblies in the bin directory cannot be placed in a subdirectory, if a website isn’t configured for that specific directory. So we placed the assemblies in the root webapplication’s bin directory, and it worked!