RolandK RolandK - 1 month ago 12
ASP.NET (C#) Question

Kentico: Retrieving the rendered content of a page programmatically

I want my customers to be able to design their own pages in Kentico with a selection of given widgets. So they create a page, select a template with a widget zone and then place any widget they want.

What I want to do is, I want to develop a widget that retrieves the content of one of these pages, and then processes/encapsulates it. Or in more technical words, I'd like to have the page content as a HTML string in my widget class.

Unfortunately, the Kentico API provides no method of retrieving a page's content, or at least, I couldn't figure out how. There is a Kentico web part, "page placeholder", which does exactly what I need, however, I can't find a way to use its functionality inside a widget. I assumed I can use a

cms:CMSPagePlaceholder
tag inside my widget.ascx, but for some reason it's invisible there (I can select many different other controls from the Kentico CMS namespace, though).

I also tried receiving the content via the
System.Net.WebClient
class - without success. All I get is


(401) Unauthorized


I can open the given URL in my browser, however. (Bonus points for you if you can tell my why that is. I've stumbled over this 401 error in a different context (accessing the staging webservice) and can't quite figure out why. Same thing with staging: I can access the staging web service's URL in the browser but not from within Kentico... Very strange)

Some background information: I'm developing from a client where my physical files are stored and I'm accessing a shared database on a server. The physical files are basically duplicates on my client an the server. I'm only pushing my changed web part files. The server Kentico instance has a different URL than my client's Kentico instance, and I'm redirecting my client's URLs to the server (via "site" setting).

Long story short, how do I get a document's rendered HTML for my widget? If that was possible, it'd make my life a lot easier.

Answer

Trying to render contents of a page programmatically could be very troublesome. I would say the approach with the WebClient is the only sensible way to go. Depending on the authentication method of your Kentico instance you have to provide the right set of credentials so that you don't get the 401 error. If you use Windows authentication you need to provide the web request with NetworkCredential object. If you're using Forms authentication you can copy the cookies so that the request 'impersonates' the currently logged-in user.

This is an example of authenticating System.Net.WebClient against the ASP.NET Forms authentication:

public class CookieReplicatingWebClient : WebClient
{
    protected override WebRequest GetWebRequest(Uri address)
    {
        var request = (HttpWebRequest)base.GetWebRequest(address);
        if (request != null)
        {
            HttpCookieCollection cookies = HttpContext.Current.Request.Cookies;

            CookieContainer cookieContainer = new CookieContainer();

            for (int i = 0; i < cookies.Count; i++)
            {
                // Clone cookies
                HttpCookie httpCookie = cookies[i];
                if (httpCookie != null)
                {
                    cookieContainer.Add(new Cookie { Domain = request.RequestUri.Host, Name = httpCookie.Name, Path = httpCookie.Path, Secure = httpCookie.Secure, Value = httpCookie.Value });
                }
            }

            request.CookieContainer = cookieContainer;
        }
        return request;
    }
}

protected void Page_Load(object sender, EventArgs e)
{
    using (WebClient client = new CookieReplicatingWebClient())
    {
        // Request secured area (of Kentico's Corporate sample site)
        string htmlCode = client.DownloadString("http://localhost/Kentico82/Partners/Gold-partners.aspx");
    }
}