diff --git a/src/Umbraco.Web/Routing/PublishedContentRequest.cs b/src/Umbraco.Web/Routing/PublishedContentRequest.cs
index 5698b36b1c..b3c5ac3db9 100644
--- a/src/Umbraco.Web/Routing/PublishedContentRequest.cs
+++ b/src/Umbraco.Web/Routing/PublishedContentRequest.cs
@@ -14,7 +14,9 @@ namespace Umbraco.Web.Routing
/// by one specified template, using one specified Culture and RenderingEngine.
///
public class PublishedContentRequest
- {
+ {
+ private bool _readonly;
+
///
/// Triggers once the published content request has been prepared, but before it is processed.
///
@@ -74,6 +76,11 @@ namespace Umbraco.Web.Routing
{
if (Prepared != null)
Prepared(this, EventArgs.Empty);
+
+ if (!HasPublishedContent)
+ Is404 = true; // safety
+
+ _readonly = true;
}
///
@@ -82,6 +89,12 @@ namespace Umbraco.Web.Routing
/// The cleaned up Uri has no virtual directory, no trailing slash, no .aspx extension, etc.
public Uri Uri { get; private set; }
+ private void EnsureWriteable()
+ {
+ if (_readonly)
+ throw new InvalidOperationException("Cannot modify a PublishedContentRequest once it is read-only.");
+ }
+
#region PublishedContent
///
@@ -105,6 +118,7 @@ namespace Umbraco.Web.Routing
get { return _publishedContent; }
set
{
+ EnsureWriteable();
_publishedContent = value;
IsInternalRedirectPublishedContent = false;
TemplateModel = null;
@@ -119,6 +133,8 @@ namespace Umbraco.Web.Routing
/// preserve or reset the template, if any.
public void SetInternalRedirectPublishedContent(IPublishedContent content)
{
+ EnsureWriteable();
+
// unless a template has been set already by the finder,
// template should be null at that point.
var initial = IsInitialPublishedContent;
@@ -152,6 +168,8 @@ namespace Umbraco.Web.Routing
///
public void SetIsInitialPublishedContent()
{
+ EnsureWriteable();
+
// note: it can very well be null if the initial content was not found
_initialPublishedContent = _publishedContent;
IsInternalRedirectPublishedContent = false;
@@ -222,6 +240,8 @@ namespace Umbraco.Web.Routing
///
public bool TrySetTemplate(string alias)
{
+ EnsureWriteable();
+
if (string.IsNullOrWhiteSpace(alias))
{
TemplateModel = null;
@@ -270,10 +290,20 @@ namespace Umbraco.Web.Routing
get { return Domain != null; }
}
- ///
- /// Gets or sets the content request's culture.
- ///
- public CultureInfo Culture { get; set; }
+ private CultureInfo _culture;
+
+ ///
+ /// Gets or sets the content request's culture.
+ ///
+ public CultureInfo Culture
+ {
+ get { return _culture; }
+ set
+ {
+ EnsureWriteable();
+ _culture = value;
+ }
+ }
// note: do we want to have an ordered list of alternate cultures,
// to allow for fallbacks when doing dictionnary lookup and such?
@@ -332,6 +362,7 @@ namespace Umbraco.Web.Routing
/// where we want to allow developers to indicate a request is 404 but not to cancel it.
public void SetIs404()
{
+ EnsureWriteable();
Is404 = true;
}
@@ -358,6 +389,7 @@ namespace Umbraco.Web.Routing
/// redirect. Redirect will or will not take place in due time.
public void SetRedirect(string url)
{
+ EnsureWriteable();
RedirectUrl = url;
IsRedirectPermanent = false;
}
@@ -370,6 +402,7 @@ namespace Umbraco.Web.Routing
/// redirect. Redirect will or will not take place in due time.
public void SetRedirectPermanent(string url)
{
+ EnsureWriteable();
RedirectUrl = url;
IsRedirectPermanent = true;
}
@@ -383,6 +416,8 @@ namespace Umbraco.Web.Routing
/// redirect. Redirect will or will not take place in due time.
public void SetRedirect(string url, int status)
{
+ EnsureWriteable();
+
if (status < 300 || status > 308)
throw new ArgumentOutOfRangeException("status", "Valid redirection status codes 300-308.");
@@ -416,6 +451,8 @@ namespace Umbraco.Web.Routing
/// not be used, in due time.
public void SetResponseStatus(int code, string description = null)
{
+ EnsureWriteable();
+
// .Status is deprecated
// .SubStatusCode is IIS 7+ internal, ignore
ResponseStatusCode = code;
diff --git a/src/Umbraco.Web/Routing/PublishedContentRequestEngine.cs b/src/Umbraco.Web/Routing/PublishedContentRequestEngine.cs
index 4f87a3532e..daeaa85cb8 100644
--- a/src/Umbraco.Web/Routing/PublishedContentRequestEngine.cs
+++ b/src/Umbraco.Web/Routing/PublishedContentRequestEngine.cs
@@ -74,28 +74,22 @@ namespace Umbraco.Web.Routing
// trigger the Prepared event - at that point it is still possible to change about anything
// even though the request might be flagged for redirection - we'll redirect _after_ the event
+ //
+ // also, OnPrepared() will make the PublishedContentRequest readonly, so nothing can change
+ //
_pcr.OnPrepared();
- // we don't take care of anything xcept finding the rendering engine again
- // so if the content has changed, it's up to the user to find out the template
+ // we don't take care of anything so if the content has changed, it's up to the user
+ // to find out the appropriate template
// set the culture on the thread -- again, 'cos it might have changed in the event handler
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = _pcr.Culture;
- // if request has been flagged to redirect then return
- // whoever called us is in charge of actually redirecting
- if (_pcr.IsRedirect)
+ // if request has been flagged to redirect, or has no content to display,
+ // then return - whoever called us is in charge of actually redirecting
+ if (_pcr.IsRedirect || !_pcr.HasPublishedContent)
return;
- if (!_pcr.HasPublishedContent)
- {
- // safety
- _pcr.Is404 = true;
-
- // whoever called us is in charge of doing what's appropriate
- return;
- }
-
// we may be 404 _and_ have a content
// can't go beyond that point without a PublishedContent to render
diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs
index b44026febe..471e7403ad 100644
--- a/src/Umbraco.Web/UmbracoContext.cs
+++ b/src/Umbraco.Web/UmbracoContext.cs
@@ -274,7 +274,7 @@ namespace Umbraco.Web
///
/// Gets/sets the PublishedContentRequest object
///
- internal PublishedContentRequest PublishedContentRequest { get; set; }
+ public PublishedContentRequest PublishedContentRequest { get; set; }
///
/// Exposes the HttpContext for the current request