not the last of his kind
Programming
Common coding issues when working with anonymous SharePoint sites
Jun 8th
Working with anonymous SharePoint sites can be tricky sometimes. If you’re not careful, your customization codes (Web parts, custom controls, custom pages, etc.) can popup the login dialog box to anonymous users. As anonymous users they don’t have a user account, so obviously they won’t be able to enter their user ID and password. Or it simply produces an error page that either way, prevents anonymous users from accessing your site.
This post addresses some common coding issues when you work with anonymous SharePoint sites, so you can avoid it earlier.
1. Determining whether the current user is an anonymous user
How to check whether the current user is an anonymous user? I may have overlooked it, but as far as I know there is no built-in API methods for this purpose. Fortunately it’s very easy and terse. You can test the value of SPContext.Current.Web.CurrentUser. If it is null then it is accessed by an anonymous user. Here is a sample code:
if (SPContext.Current.Web.CurrentUser == null) { // Anonymous user section } else { // Authenticated user section }
2. Beware when using SPWeb.CurrentUser
As described on the previous point, when an anonymous user is accessing a Site, the value of SPContext.Current.Web.CurrentUser will always be null. Double-check whenever you are using the property. Always make sure that you have checked for the null value, or you will end up getting the nasty “System.NullReferenceException – Object reference not set to an instance of an object.” exception.
3. Anonymous user does not have a user profile
It is an obvious yet easily overlooked one. It is a common practice to utilize the UserProfile API to store user’s personalization. Since an anonymous user does not have a user profile, provide another mean to store his/her personalization data. It could be SharePoint lists, database tables, files, or even browser cookies.
4. Working with the Publishing Feature API
I’m referring to the API under the Microsoft.SharePoint.Publishing assembly and namespace. I haven’t checked all of the API members, but not all will work with anonymous users. For example, the PublishingWeb.IsPublishingWeb(SPWeb web) works, but the PublishingWeb.GetPublishingWeb(SPWeb web) doesn’t. In fact, it will prompt the anonymous user to login by entering the user ID and password. The workaround is get an elevated SPWeb instance that has the System Account’s credential and then use the GetPublishingWeb() method on that instance. The following snippet illustrates it:
var currentWeb = SPContext.Curent.Web; // the method is available to anonymous users if (PublishingWeb.IsPublishingWeb(currentWeb)) { SPSecurity.RunWithElevatedPrivileges(delegate() { using (var site = new SPSite(curentWeb.Url)) { using (var web = site.OpenWeb()) { // the method is not available to anonymous users var pubWeb = PublishingWeb.GetPublishingWeb(web); // Do something with pubWeb } } }); }
I will update this post when I find more things related to anonymous SharePoint sites. Please leave a comment if you have something to contribute, too.
System.Net.WebException: An exception occurred during a WebClient request
Apr 26th
When using either WebClient or HttpWebRequest to download file from a remote location, sometimes I got the following exception:
System.Net.WebException: An exception occurred during a WebClient request
For some reasons, IIS (the Web server) may deny to serve a request that doesn’t specify the user-agent property in the request header. So, although it’s not really obvious, this can be solved pretty easily by specifying the particular user-agent property. You can set it to anything, it doesn’t matter as long as it exists.
For example, here how you provide the property using WebClient:
using (var wc = new WebClient()) { wc.Credentials = CredentialCache.DefaultCredentials; wc.Headers.Add(HttpRequestHeader.UserAgent, "anything"); wc.DownloadFile(fileUrlToDownload, fileNameToSafe); }
And, here how to do it with HttpWebRequest:
var req = (HttpWebRequest)HttpWebRequest.Create(fileUrlToDownload); req.Credentials = CredentialCache.DefaultCredentials; req.UserAgent = "anything"; var resp = (HttpWebResponse)req.GetResponse(); using (var stream = resp.GetResponseStream()) { using (var fstream = new FileStream(fileNameToSafe) { var buffer = new byte[8192]; var maxCount = buffer.Length; int count; while ((count = stream.Read(buffer, 0, maxCount)) > 0) fstream.Write(buffer, 0, count); } } resp.Close();
You may also notice that downloading a file using WebClient is much simpler than using HttpWebRequest. The later, however, gives you much more control.
A singleton base class to implement the singleton pattern in C#
Mar 2nd
The singleton design pattern is one of the most controversial pattern. Some people even call it anti-pattern, evil, or stupid. I won’t go into the debate now, but I just want to share something for those who need to use singletons.
Although it is one of the easiest pattern to understand, it is also very easy to code it poorly, leading to unexpected side effects such as poor performance or being not thread-safe.
Jon Skeet has written a very good article describing different implementations of the singleton pattern in C#. He gives a nice example on how you can write a singleton code that is thread-safe and lazy-instantiating. The code is less than 20 lines and you can use it as a template for your singletons.
Since in some projects I have created several singleton objects, it started to get repetitive. Therefore I decided to write a base class based on this pattern as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | using System; using System.Globalization; using System.Reflection; public abstract class SingletonBase<t> where T : class { /// <summary> /// A protected constructor which is accessible only to the sub classes. /// </summary> protected SingletonBase() { } /// <summary> /// Gets the singleton instance of this class. /// </summary> public static T Instance { get { return SingletonFactory.Instance; } } /// <summary> /// The singleton class factory to create the singleton instance. /// </summary> class SingletonFactory { // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit static SingletonFactory() { } // Prevent the compiler from generating a default constructor. SingletonFactory() { } internal static readonly T Instance = GetInstance(); static T GetInstance() { var theType = typeof(T); T inst; try { inst = (T)theType .InvokeMember(theType.Name, BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.NonPublic, null, null, null, CultureInfo.InvariantCulture); } catch (MissingMethodException ex) { throw new TypeLoadException(string.Format( CultureInfo.CurrentCulture, "The type '{0}' must have a private constructor to " + "be used in the Singleton pattern.", theType.FullName) , ex); } return inst; } } } |
For an example of usage, we will create a singleton class that generates a sequence number:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // Must seal the class so no sub-classes can be defined. public sealed class SequenceGeneratorSingleton : SingletonBase<sequenceGeneratorSingleton> { // Must have a private constructor so no instance can be created externally. SequenceGeneratorSingleton() { _number = 0; } private int _number; public int GetSequenceNumber() { return _number++; } } |
Then, a console application will call the sequence generator class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Program { static void Main(string[] args) { Console.WriteLine("Sequence: " + SequenceGeneratorSingleton.Instance .GetSequenceNumber().ToString()); // Print "Sequence: 0" Console.WriteLine("Sequence: " + SequenceGeneratorSingleton.Instance .GetSequenceNumber().ToString()); // Print "Sequence: 1" Console.WriteLine("Sequence: " + SequenceGeneratorSingleton.Instance .GetSequenceNumber().ToString()); // Print "Sequence: 2" } } |
To recap, in order to create a singleton class using the singleton base class, you need to do the following:
- Define a sealed class which derives fromĀ
SingletonBase<T>, where T is the class name you are defining. It ensures that you cannot create subclasses from this singleton class. - Define a single parameterless private constructor inside the class. It ensures that no instances of this class can be created externally.
- Access the class’ singleton instance and public members by calling theĀ
Instanceproperty.
I have also included the code in LiquidSilver, which you can view or download from the repository.
Recent Comments