/// <summary> /// Writes the supplied <see cref="ISyndicationResource"/> to the specified <see cref="HttpContext"/> response stream and sets the appropriate headers. /// </summary> /// <param name="context"> /// An <see cref="HttpContext"/> object that provides references to the intrinsic server objects /// (for example, <b>Request</b>, <b>Response</b>, <b>Session</b>, and <b>Server</b>) used to service HTTP requests. /// </param> /// <param name="resource">The <see cref="ISyndicationResource"/> to be written to the response stream.</param> /// <exception cref="ArgumentNullException">The <paramref name="context"/> is a null reference (Nothing in Visual Basic).</exception> /// <exception cref="ArgumentNullException">The <paramref name="resource"/> is a null reference (Nothing in Visual Basic).</exception> private void WriteResource(HttpContext context, ISyndicationResource resource) { //------------------------------------------------------------ // Validate parameters //------------------------------------------------------------ Guard.ArgumentNotNull(context, "context"); Guard.ArgumentNotNull(resource, "resource"); //------------------------------------------------------------ // Process conditional GET information if present // (If conditions met, handler execution stops.) //------------------------------------------------------------ SyndicationResourceHandler.ProcessConditionalGetInformation(context, resource); //------------------------------------------------------------ // Modify response meta-data information //------------------------------------------------------------ context.Response.ContentType = SyndicationResourceHandler.ContentFormatAsMimeType(resource.Format); context.Response.AppendHeader("Content-Disposition", SyndicationResourceHandler.GetContentDisposition(resource.Format)); //------------------------------------------------------------ // Save XML representation of resource to output stream //------------------------------------------------------------ SyndicationResourceSaveSettings settings = new SyndicationResourceSaveSettings(); settings.AutoDetectExtensions = true; settings.MinimizeOutputSize = false; resource.Save(context.Response.OutputStream, settings); //------------------------------------------------------------ // Modify response caching expiration information //------------------------------------------------------------ this.ModifyCacheExpiration(context); }
/// <summary> /// Enables a factory to reuse an existing HTTP handler instance. /// </summary> /// <param name="handler">The <see cref="IHttpHandler"/> object to reuse.</param> public void ReleaseHandler(IHttpHandler handler) { //------------------------------------------------------------ // Local members //------------------------------------------------------------ SyndicationResourceHandler syndicationHandler = null; //------------------------------------------------------------ // Verify handler is reusable //------------------------------------------------------------ if (handler.IsReusable) { lock (factoryHandlerLock) { if (factoryHandlers.Count < handlerPoolLimit) { syndicationHandler = handler as SyndicationResourceHandler; if (syndicationHandler != null) { factoryHandlers.Push(syndicationHandler); } } } } }
//============================================================ // PROTECTED METHODS //============================================================ #region OnPreRender(EventArgs e) /// <summary> /// Raises the <see cref="Control.PreRender">PreRender</see> event. /// </summary> /// <param name="e">An <see cref="EventArgs"/> object that contains the event data.</param> /// <remarks> /// <para>This method notifies the server control to perform any necessary pre-rendering steps prior to saving view state and rendering content.</para> /// <para> /// During this step in the ASP.NET page life-cycle, the <see cref="SyndicationAutoDiscoveryHyperlink"/> will attempt to add /// a <i><link rel="alternate" type="{MIME Type}" title="{Text}" href="{NavigateUrl}" /></i> to the page header section if /// it is available to be modified. /// </para> /// <para> /// The MIME media type of the link will be automatically selected based on the <see cref="Format">format</see> /// unless the <see cref="MediaType">media type</see> has been explicitly specified. /// </para> /// <para> /// The <i>title</i> attribute will only be rendered if the control's <see cref="Text"/> property has been specified. /// </para> /// </remarks> protected override void OnPreRender(EventArgs e) { //------------------------------------------------------------ // Local members //------------------------------------------------------------ string mimeType = String.Empty; string href = String.Empty; string title = String.Empty; //------------------------------------------------------------ // Do not render control is invisible or disabled //------------------------------------------------------------ if (!this.Visible || !this.Enabled) { base.OnPreRender(e); return; } //------------------------------------------------------------ // As the page header control collection cannot be // modified during the PreRender phase, exit this event // handler to prevent raising an exception. //------------------------------------------------------------ if (this.Parent is System.Web.UI.HtmlControls.HtmlHead) { base.OnPreRender(e); return; } else if (this.Parent is System.Web.UI.WebControls.ContentPlaceHolder && this.Parent.Parent is System.Web.UI.HtmlControls.HtmlHead) { base.OnPreRender(e); return; } //------------------------------------------------------------ // Render auto-discovery link //------------------------------------------------------------ href = this.NavigateUrl != null?this.NavigateUrl.ToString() : String.Empty; mimeType = SyndicationResourceHandler.ContentFormatAsMimeType(this.Format); if (!String.IsNullOrEmpty(this.Text)) { title = this.Text; } if (this.Page.Header != null) { string controlContent = String.Format(null, "\r\n<link rel=\"alternate\" type=\"{0}\" href=\"{1}\" />", mimeType, href); if (!String.IsNullOrEmpty(title)) { controlContent = String.Format(null, "\r\n<link rel=\"alternate\" type=\"{0}\" href=\"{1}\" title=\"{2}\" />", mimeType, href, title); } LiteralControl link = new LiteralControl(controlContent); this.Page.Header.Controls.Add(link); } base.OnPreRender(e); }
/// <summary> /// Outputs server control content to a provided <see cref="HtmlTextWriter"/> object and stores tracing information about the control if tracing is enabled. /// </summary> /// <param name="writer">The <see cref="HtmlTextWriter"/> object that receives the control content.</param> /// <remarks> /// <para> /// The MIME media type of the link will be automatically selected based on the <see cref="Format">format</see> /// unless the <see cref="MediaType">media type</see> has been explicitly specified. /// </para> /// <para> /// The <i>title</i> attribute will only be rendered if the control's <see cref="Text"/> property has been specified. /// </para> /// </remarks> /// <exception cref="ArgumentNullException">The <paramref name="writer"/> is a null reference (Nothing in Visual Basic).</exception> public override void RenderControl(HtmlTextWriter writer) { //------------------------------------------------------------ // Local members //------------------------------------------------------------ string mimeType = String.Empty; string href = String.Empty; string title = String.Empty; //------------------------------------------------------------ // Validate parameter //------------------------------------------------------------ if (writer == null) { throw new ArgumentNullException("writer"); } //------------------------------------------------------------ // Do not render control is invisible or disabled //------------------------------------------------------------ if (!this.Enabled || !this.Visible) { return; } //------------------------------------------------------------ // Determine if link is positioned in HTML head //------------------------------------------------------------ if (this.Parent is System.Web.UI.HtmlControls.HtmlHead) { //------------------------------------------------------------ // Render auto-discovery link //------------------------------------------------------------ href = this.NavigateUrl != null?this.NavigateUrl.ToString() : String.Empty; mimeType = SyndicationResourceHandler.ContentFormatAsMimeType(this.Format); if (!String.IsNullOrEmpty(this.Text)) { title = this.Text; } writer.AddAttribute(HtmlTextWriterAttribute.Rel, "alternate"); writer.AddAttribute(HtmlTextWriterAttribute.Type, mimeType); writer.AddAttribute(HtmlTextWriterAttribute.Href, href); if (!String.IsNullOrEmpty(title)) { writer.AddAttribute(HtmlTextWriterAttribute.Title, title); } writer.RenderBeginTag(HtmlTextWriterTag.Link); writer.RenderEndTag(); writer.WriteLine(); } }
/// <summary> /// Processes conditional GET header information for the supplied <see cref="ISyndicationResource"/>. /// </summary> /// <param name="context"> /// An <see cref="HttpContext"/> object that provides references to the intrinsic server objects /// (for example, <b>Request</b>, <b>Response</b>, <b>Session</b>, and <b>Server</b>) used to service HTTP requests. /// </param> /// <param name="resource">The <see cref="ISyndicationResource"/> that is used when determining if conditional GET operation requirements were met.</param> /// <remarks> /// <para> /// This method will retrieve conditional GET information from the request headers, and if present, will set the appropriate /// response header information and status for the supplied <paramref name="resource"/>. If a modification date is available for /// the supplied <paramref name="resource"/>, the conditional GET header information will be set so that clients may optionally /// cache this infomration when making future requests. /// </para> /// <para>If a conditional GET operation was fulflled, no additional processing or modification of the response should be performed.</para> /// </remarks> /// <exception cref="ArgumentNullException">The <paramref name="context"/> is a null reference (Nothing in Visual Basic).</exception> /// <exception cref="ArgumentNullException">The <paramref name="resource"/> is a null reference (Nothing in Visual Basic).</exception> private static void ProcessConditionalGetInformation(HttpContext context, ISyndicationResource resource) { //------------------------------------------------------------ // Local members //------------------------------------------------------------ string eTag = String.Empty; string ifModifiedSince = String.Empty; bool resourceIsUnmodified = false; //------------------------------------------------------------ // Validate parameters //------------------------------------------------------------ Guard.ArgumentNotNull(context, "context"); Guard.ArgumentNotNull(resource, "resource"); //------------------------------------------------------------ // Perform conditional GET processing //------------------------------------------------------------ eTag = context.Request.Headers["If-None-Match"]; ifModifiedSince = context.Request.Headers["if-modified-since"]; if (!String.IsNullOrEmpty(eTag) || !String.IsNullOrEmpty(ifModifiedSince)) { DateTime lastModified = SyndicationResourceHandler.GetLastModificationDate(resource); if (lastModified == DateTime.MinValue) { return; } if (!String.IsNullOrEmpty(eTag)) { //------------------------------------------------------------ // Determine if not modified by comparing last modified date-time //------------------------------------------------------------ resourceIsUnmodified = eTag.Equals(lastModified.Ticks.ToString(CultureInfo.InvariantCulture)); } else if (!String.IsNullOrEmpty(ifModifiedSince)) { //------------------------------------------------------------ // Determine if not modified by comparing if modified since date-time //------------------------------------------------------------ if (ifModifiedSince.IndexOf(";", StringComparison.OrdinalIgnoreCase) > -1) { ifModifiedSince = ifModifiedSince.Split(';').GetValue(0).ToString().Trim(); // Wed, 29 Dec 2004 18:34:27 GMT; length=126275 } DateTime ifModifiedDate; if (DateTime.TryParse(ifModifiedSince, out ifModifiedDate)) { resourceIsUnmodified = (lastModified <= ifModifiedDate); } } //------------------------------------------------------------ // Set conditional GET response information //------------------------------------------------------------ if (resourceIsUnmodified) { context.Response.StatusCode = 304; context.Response.SuppressContent = true; context.Response.End(); // HTTP handler execution stops. } else { if (lastModified <= DateTime.Now) { context.Response.Cache.SetLastModified(lastModified); } else { context.Response.Cache.SetLastModified(context.Timestamp); } context.Response.Cache.SetETag(lastModified.Ticks.ToString(CultureInfo.InvariantCulture)); } } }
//============================================================ // PUBLIC METHODS //============================================================ #region GetHandler(HttpContext context, string requestType, string url, string pathTranslated) /// <summary> /// Returns an instance of a class that implements the <see cref="IHttpHandler"/> interface. /// </summary> /// <param name="context"> /// An instance of the <see cref="HttpContext"/> class that provides references to /// intrinsic server objects (for example, <b>Request</b>, <b>Response</b>, <b>Session</b>, and <b>Server</b>) used to service HTTP requests. /// </param> /// <param name="requestType">The HTTP data transfer method (<b>GET</b> or <b>POST</b>) that the client uses.</param> /// <param name="url">The <see cref="HttpRequest.RawUrl">RawUrl</see> of the requested resource.</param> /// <param name="pathTranslated">The <see cref="HttpRequest.PhysicalApplicationPath">PhysicalApplicationPath</see> to the requested resource.</param> /// <returns>A new <see cref="SyndicationResourceHandler"/> object that processes the request.</returns> /// <exception cref="ArgumentNullException">The <paramref name="context"/> is a null reference (Nothing in Visual Basic).</exception> /// <exception cref="ArgumentNullException">The <paramref name="requestType"/> is a null reference (Nothing in Visual Basic).</exception> /// <exception cref="ArgumentNullException">The <paramref name="requestType"/> is an empty string.</exception> /// <exception cref="ArgumentNullException">The <paramref name="url"/> is a null reference (Nothing in Visual Basic).</exception> /// <exception cref="ArgumentNullException">The <paramref name="url"/> is an empty string.</exception> /// <exception cref="HttpException">The factory was unable to create a <see cref="SyndicationResourceHandler"/> for the request.</exception> public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated) { //------------------------------------------------------------ // Local members //------------------------------------------------------------ SyndicationResourceHandler handler = null; //------------------------------------------------------------ // Validate parameters //------------------------------------------------------------ Guard.ArgumentNotNull(context, "context"); Guard.ArgumentNotNullOrEmptyString(requestType, "requestType"); Guard.ArgumentNotNullOrEmptyString(url, "url"); //------------------------------------------------------------ // Return reusable handler if available //------------------------------------------------------------ lock (factoryHandlerLock) { if (factoryHandlers.Count > 0) { handler = (SyndicationResourceHandler)factoryHandlers.Pop(); return(handler); } } //------------------------------------------------------------ // Attempt to create handler //------------------------------------------------------------ try { handler = (SyndicationResourceHandler)Activator.CreateInstance(typeof(SyndicationResourceHandler)); //------------------------------------------------------------ // Get factory name //------------------------------------------------------------ string fullName = url.Substring(url.LastIndexOf('/') + 1); string factoryName = fullName.Substring(0, fullName.IndexOf('.')); //------------------------------------------------------------ // Set syndication format of handler based on factory path //------------------------------------------------------------ if (String.Compare(factoryName, "Apml", StringComparison.OrdinalIgnoreCase) == 0) { handler.Format = SyndicationContentFormat.Apml; } else if (String.Compare(factoryName, "Atom", StringComparison.OrdinalIgnoreCase) == 0) { handler.Format = SyndicationContentFormat.Atom; } else if (String.Compare(factoryName, "BlogML", StringComparison.OrdinalIgnoreCase) == 0) { handler.Format = SyndicationContentFormat.BlogML; } else if (String.Compare(factoryName, "Opml", StringComparison.OrdinalIgnoreCase) == 0) { handler.Format = SyndicationContentFormat.Opml; } else if (String.Compare(factoryName, "Rsd", StringComparison.OrdinalIgnoreCase) == 0) { handler.Format = SyndicationContentFormat.Rsd; } else if (String.Compare(factoryName, "Rss", StringComparison.OrdinalIgnoreCase) == 0) { handler.Format = SyndicationContentFormat.Rss; } return(handler); } catch (Exception exception) { //------------------------------------------------------------ // Rethrow exception as HttpException with param information //------------------------------------------------------------ throw new HttpException(String.Format(null, "The SyndicationHttpHandlerFactory was unable to create a handler for requestType='{0}', url='{1}', pathTranslated='{2}'.", requestType, url, pathTranslated), exception); } }