Apr 18

We have developed a custom RSS WebPart to let the user customizes its home page and selects which RSS feeds to display. Later, we wanted to reuse that webpart to display some internal SharePoint RSS like the ones associated to a SPList.

Note: The RSS url of a SPList looks something like that: http://www.yoursite.com/_layouts/listfeed.aspx?List=71033e93%2D0bb4%2D4aaa%2Db438%2D76ddf6f408f4.

We have 3 different zones associated to our SharePoint web site: Default, Intranet and Internet.
All uses https. Default use Windows authentication and the two latter use FBA (Forms-Based Authentication).

To read the stream, we use that code:

HttpWebRequest webRequest = (HttpWebRequest) WebRequest.Create(rssUri);

XmlTextReader xmlReader = new XmlTextReader(webRequest.GetResponse().GetResponseStream());

rssDoc.Load(xmlReader);

// process your RSS here...

 

Handling HTTPS is very easy: .Net will raise an event to let us ensure the validity of a certificate but we really don't care (just return true).

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

HttpRequestCachePolicy policy = new HttpRequestCachePolicy(HttpRequestCacheLevel.BypassCache);

webRequest.CachePolicy = policy;

 

Now, Windows authentication is not a great problem too. As the WebPart code is executed under the user's account, we use:

webRequest.PreAuthenticate = true;

webRequest.Credentials = CredentialCache.DefaultNetworkCredentials;

 

And finally Form Based Authentication took some times to understand how to pass credentials. Using Fiddler, I was able to figurate that a cookie is sent by the browser. That cookie is the one specified in the web.config <authentication mode="Forms"> tag. If you don't specify anything, the default .ASPXAUTH name is used (defined in System.Web.Security.FormsAuthentication.FormsCookieName). So we will grab it and push it in our webRequest.

webRequest.PreAuthenticate = true;

string cookieName = System.Web.Security.FormsAuthentication.FormsCookieName;

HttpCookie authCookie = context.Request.Cookies[cookieName];

webRequest.CookieContainer = new CookieContainer(1);

webRequest.CookieContainer.Add(new Cookie(cookieName,

    authCookie.Value,

    authCookie.Path,

    authCookie.Domain ?? rssUri.Host));

 

Note that we ensure a domain is provided otherwise an exception will be thrown.

 

Finally, the complete code is a bit longer because we check the context of the current SPSite:

context.Response.ContentType = "text/html";

 

SPSite site = SPContext.Current.Site;

 

if (rssUrl.StartsWith("/")) // relative url

    rssUrl = site.Url + rssUrl;

 

Uri rssUri = new Uri(rssUrl);

HttpWebRequest webRequest = (HttpWebRequest) WebRequest.Create(rssUri);

 

 

// We need to give some extra credentials for our SharePoint sites.

// This case is checked by comparing the RSS Uri to the current SPSite uri

var contextUri = SPAlternateUrl.ContextUri;

if (rssUri.GetLeftPart(UriPartial.Authority) == contextUri.GetLeftPart(UriPartial.Authority))

{

    var altUrl = SPAlternateUrl.Lookup(rssUri);

    AuthenticationMode authMode = site.WebApplication.IisSettings[altUrl.UrlZone].AuthenticationMode;

 

    if (authMode == AuthenticationMode.Forms)

    {

        // Handle Forms Authentification for our internal SP site

        // We send the .ASPXAUTH cookie, containing our credentials

        webRequest.PreAuthenticate = true;

        string cookieName = System.Web.Security.FormsAuthentication.FormsCookieName;

        HttpCookie authCookie = context.Request.Cookies[cookieName];

        webRequest.CookieContainer = new CookieContainer(1);

        webRequest.CookieContainer.Add(new Cookie(cookieName,

            authCookie.Value,

            authCookie.Path,

            authCookie.Domain ?? rssUri.Host));

    }

    else if(authMode == AuthenticationMode.Windows)

    {

        webRequest.PreAuthenticate = true;

        webRequest.Credentials = CredentialCache.DefaultNetworkCredentials;

    }

}

 

 

// Handle SSL

ServicePointManager.ServerCertificateValidationCallback = VerifyServerCertificate;

HttpRequestCachePolicy policy = new HttpRequestCachePolicy(HttpRequestCacheLevel.BypassCache);

webRequest.CachePolicy = policy;

 

XmlTextReader xmlReader = new XmlTextReader(webRequest.GetResponse().GetResponseStream());

rssDoc.Load(xmlReader);

Tags:

Comments

Herbs

Posted on Wednesday, 22 April 2009 09:39

Well done. I think that many people will benefit from your work.

Olivier

Posted on Wednesday, 22 April 2009 13:21

Thank you Herbs, it's always a pleasure to know we don't blog for nothing Smile

EDI Services

Posted on Saturday, 4 July 2009 03:38

I am learning a lot about RSS. Look forward to learning more about it.

Gaetan

Posted on Thursday, 11 February 2010 04:34

Thanks Olivier for this great and very helpfull post!

Comments are closed