using System; using System.Linq; using System.Text; using System.Threading; using System.Web; using System.Xml; using System.Globalization; using System.Diagnostics; // legacy using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Models; using umbraco; using umbraco.BusinessLogic; using umbraco.NodeFactory; using umbraco.cms.businesslogic.web; using umbraco.cms.businesslogic.template; using umbraco.cms.businesslogic.member; using umbraco.interfaces; using Template = umbraco.cms.businesslogic.template.Template; namespace Umbraco.Web.Routing { /// /// Represents a request for one specified Umbraco IPublishedContent to be rendered /// by one specified template, using one specified Culture and RenderingEngine. /// internal class PublishedContentRequest { /// /// Triggers once the published content request has been prepared, but before it is processed. /// /// When the event triggers, preparation is done ie domain, culture, document, template, /// rendering engine, etc. have been setup. It is then possible to change anything, before /// the request is actually processed and rendered by Umbraco. public static event EventHandler Prepared; // the engine that does all the processing // because in order to keep things clean and separated, // the content request is just a data holder private PublishedContentRequestEngine _engine; /// /// Initializes a new instance of the class with a specific Uri and routing context. /// /// The request Uri. /// A routing context. public PublishedContentRequest(Uri uri, RoutingContext routingContext) { if (uri == null) throw new ArgumentNullException("uri"); if (routingContext == null) throw new ArgumentNullException("routingContext"); this.Uri = uri; this.RoutingContext = routingContext; _engine = new PublishedContentRequestEngine(this); this.RenderingEngine = RenderingEngine.Mvc; // default } /// /// Gets the engine associated to the request. /// internal PublishedContentRequestEngine Engine { get { return _engine; } } /// /// Prepares the request. /// internal void Prepare() { _engine.PrepareRequest(); } /// /// Updates the request when there is no template to render the content. /// internal void UpdateOnMissingTemplate() { _engine.UpdateRequestOnMissingTemplate(); } /// /// Triggers the Prepared event. /// internal void OnPrepared() { if (Prepared != null) Prepared(this, EventArgs.Empty); } /// /// Gets or sets the cleaned up Uri used for routing. /// /// The cleaned up Uri has no virtual directory, no trailing slash, no .aspx extension, etc. public Uri Uri { get; private set; } #region PublishedContent /// /// The identifier of the requested IPublishedContent, if any, else zero. /// private int _publishedContentId = 0; /// /// The requested IPublishedContent, if any, else null. /// private IPublishedContent _publishedContent = null; /// /// The initial requested IPublishedContent, if any, else null. /// /// The initial requested content is the content that was found by the finders, /// before anything such as 404, redirect... took place. private IPublishedContent _initialPublishedContent = null; /// /// Gets or sets the requested content. /// /// Setting the requested content clears Template. public IPublishedContent PublishedContent { get { return _publishedContent; } set { _publishedContent = value; this.Template = null; _publishedContentId = _publishedContent != null ? _publishedContent.Id : 0; } } /// /// Gets the initial requested content. /// /// The initial requested content is the content that was found by the finders, /// before anything such as 404, redirect... took place. public IPublishedContent InitialPublishedContent { get { return _initialPublishedContent; } } /// /// Gets or sets a value indicating whether the current published content is the initial one. /// public bool IsInitialPublishedContent { get { return _initialPublishedContent != null && _initialPublishedContent == _publishedContent; } set { _initialPublishedContent = _publishedContent; } } /// /// Gets the identifier of the requested content. /// /// Thrown when the content request has no content. public int PublishedContentId { get { if (this.PublishedContent == null) throw new InvalidOperationException("PublishedContentRequest has no document."); return _publishedContentId; } } /// /// Gets a value indicating whether the content request has a content. /// public bool HasPublishedContent { get { return this.PublishedContent != null; } } #endregion #region Template /// /// Gets or sets the template to use to display the requested content. /// public Template Template { get; set; } /// /// Gets a value indicating whether the content request has a template. /// public bool HasTemplate { get { return this.Template != null; } } #endregion #region Domain and Culture /// /// Gets or sets the content request's domain. /// public Domain Domain { get; internal set; } /// /// Gets or sets the content request's domain Uri. /// /// The Domain may contain "example.com" whereas the Uri will be fully qualified eg "http://example.com/". public Uri DomainUri { get; internal set; } /// /// Gets a value indicating whether the content request has a domain. /// public bool HasDomain { get { return this.Domain != null; } } /// /// Gets or sets the content request's culture. /// public CultureInfo Culture { get; set; } // TODO: fixme - do we want to have an ordered list of alternate cultures, // to allow for fallbacks when doing dictionnary lookup and such? #endregion #region Rendering /// /// Gets or sets whether the rendering engine is MVC or WebForms. /// public RenderingEngine RenderingEngine { get; internal set; } #endregion /// /// Gets or sets the current RoutingContext. /// public RoutingContext RoutingContext { get; private set; } /// /// The "umbraco page" object. /// private page _umbracoPage; /// /// Gets or sets the "umbraco page" object. /// /// /// This value is only used for legacy/webforms code. /// internal page UmbracoPage { get { if (_umbracoPage == null) throw new InvalidOperationException("The umbraco page object is only available once Finalize()"); return _umbracoPage; } set { _umbracoPage = value; } } #region Status /// /// Gets or sets a value indicating whether the requested content could not be found. /// /// This is set in the PublishedContentRequestBuilder. internal bool Is404 { get; set; } /// /// Gets a value indicating whether the content request triggers a redirect. /// public bool IsRedirect { get { return !string.IsNullOrWhiteSpace(this.RedirectUrl); } } /// /// Gets or sets the url to redirect to, when the content request triggers a redirect. /// public string RedirectUrl { get; set; } #endregion } }