Thursday, June 10, 2010
HTTP 401.1 and DisableLoopbackCheck
We looked at IIS logs and saw one of quite common HTTP errors there. It was HTTP 401.1 again. I remembered of the most common cause of that error, made a workaround on my colleague's VM and thought it would be good to blog about it as it happened so many times to people I know.
The error was generated because of a security feature (or security fix) called loopback security check. The feature is present in Windows Server 2003 SP1 and later (including Windows Server 2008).
I will not write here about how to work around this problem because it was already explained in detail in the following KB article: http://support.microsoft.com/kb/896861.
A nice explanation about loopback check and effects it can have on your WSS or MOSS installation can be found here: http://www.harbar.net/archive/2009/07/02/disableloopbackcheck-amp-sharepoint-what-every-admin-and-developer-should-know.aspx
Tuesday, March 30, 2010
Creating a 2048 bit certificate request from VisualSVN Server
I went to VisualSVN Manager, made a certificate request, pasted it into the certificate request form on the website of one of certificate authorities and submitted the form. I was surprised when I saw an error message saying that certificate request has to be generated with a private key with at least 2048 bit encryption. I went back to VisualSVN Manager to find the step where I can specify the type of the key I want to use but I was not able to find such setting in the certificate request wizard.
It took me a few minutes to find a few posts on the net and to combine them into a working solution so I thought it would be nice to share those findings with others.
Here are the steps you need to take in order to generate a 2048 bit certificate request using VisualSVN Manager:
- You first need to create a new private key for VisualSVN Manager to use it when creating a request. To do that you should follow the next steps:
- Open command prompt
- Type the following command:
openssl.exe genrsa 2048 > private.key - After that you will be able to find a new file called "private.key" in your working folder. Edit the file in a text editor and leave it for now.
- Check if your new private key has the right length by executing next command in command prompt:
openssl.exe rsa -noout -text -in private.key - Check the output of command executed under 1.d. and see if you can find next text in it: "Private-Key: (2048 bit)"
- Now you need to update "server.pem" file for your VisualSVN Server. To do that follow the next steps:
- Open Windows Explorer and navigate to root folder of your VisualSVN Server installation (it was in "C:\Program Files\VisualSVN Server\" on my server)
- Find "server.pem" file (it was in "conf" folder on my server)
- Edit "server.pem" file with a text editor
- Replace everything between "-----BEGIN RSA PRIVATE KEY-----" and "-----END RSA PRIVATE KEY-----" with the content from "private.key" you generate in step 1.b. and save changes for "server.pem".
- You should now re-create the self signed certificate for your VisualSVN Server to be able to use Subversion until you acquire and setup a new signed certificate. To do that follow the next steps:
- Open VisualSVN Manager
- Select "Action" and then "Properties" in menu
- Go to "Certificate" tab and click no "Change certificate..." button
- Choose "Create new self-signed certificate" option and click "Next >" button
- Click on "Next" and "Finish" buttons until you finish with self-signed certificate creation.
- Check if the new self-signed certificate has the right key length by executing next command:
openssl.exe x509 -noout -text -in server.pem - NB: you will have to put the full path to "server.pem" to be able to see
results; when you get the output of above command you should look for the
following text: "RSA Public Key: (2048 bit)" - if it is there then you have
a 2048 bit key - The only thing you still need to do is to create a new 2048 bit certificate. To do that follow the next steps:
- Open VisualSVN Manager
- Select "Action" and then "Properties" in menu
- Go to "Certificate" tab and click no "Change certificate..." button
- Choose "Prepare certificate request" option and click "Next >" button
- Fill-in the name of your domain that will be used by Subversion for SSL communication
- Click Next and fill-in the other required information
Saturday, March 20, 2010
SharePoint Custom Error Page
SafeMode
<SafeMode MaxControls="200" CallStack="false" DirectFileDependencies="10" TotalFileDependencies="50" AllowPageLevelTrace="false">CustomErrors
<customErrors mode="On" >
SafeMode
<SafeMode MaxControls="200" CallStack="true" DirectFileDependencies="10" TotalFileDependencies="50" AllowPageLevelTrace="false">CustomErrors
<customErrors mode="Off" >
SafeMode
<SafeMode MaxControls="200" CallStack="true" DirectFileDependencies="10" TotalFileDependencies="50" AllowPageLevelTrace="false">CustomErrors
<customErrors mode="On" defaultRedirect="/Pages/Error.aspx">
Saturday, January 24, 2009
VisualStudio Add-In for templated/skinned Web Parts generation

A new VisualStudio Add-In was recently released on codeplex. The Add-In is used for Web Parts generation based on prepared ASCX controls/templates. We call those ASCX controls "skins" because you can create multiple ASCX controls for a single web part (those controls can have different layout, styles, etc) and choose a different "skin" during runtime.
How to use it
It's very simple to develop web parts using the Add-In and the process goes like this:
- Create an ASCX control that defines layout of a web part
- Create a new web parts project
- Right click on ASCX control, choose "Generate Web Part"
- Go to generated web part and add your custom code-behind logic
- Deploy web part by choosing "Deploy" option for web parts project.
A step-by-step tutorial together with Add-In installation is avaialable on codeproject: http://www.codeproject.com/KB/sharepoint/webparts_generator_addin.aspx
Sunday, October 26, 2008
Programmatically uploading master pages to master pages gallery in MOSS 2007
- blog is a separate website with its own Master Pages gallery
- the master page must be uploaded to blog's Master Pages gallery as soon as blog website is created
- uploaded master page must be assigned to blog as soon as blog website is created
- regular users (non-administrators) should be able to create blog websites
We decided to use "feature-stapling" mechanism in MOSS to be able to get notified when a new blog website is created and to be able to performed the required operations. I will not write about the feature-stapling mechanism in this blog post because it is fully covered in other blog posts (like in: http://www.sharepointnutsandbolts.com/2007/05/feature-stapling.html).
We made a custom master page, put it in a folder on file system of a MOSS server and added one feature property to hold full path to master page.
Out class that will handle master page uploading and assigning inherits from SPFeatureReceiver class and the method that peforms required operations executes in elevated privileges context.
Next listing shows the code that performs above mentioned operations:
private void UploadMasterPage(string pathToBlogMasterPage, SPWeb web)
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite blogSite = new SPSite(web.Site.Url))
{
using (SPWeb blogWeb = blogSite.OpenWeb(web.ID))
{
byte[] contents = null;
using (Stream fStream =
File.Open(pathToBlogMasterPage, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
contents = new byte[fStream.Length];
fStream.Position = 0;
fStream.Read(contents, 0, (int)fStream.Length);
fStream.Close();
}
//We need to extract a server relative URL of current web
string webRelativeUrl = web.Site.ServerRelativeUrl + web.Url.Replace(web.Site.Url, "");
string url = webRelativeUrl + "/_catalogs/masterpage/" + BlogCustomMasterpage;
SPFile currentFile = web.Files.Add(url, contents);
web.MasterUrl = web.MasterUrl.Replace(BlogDefaultMasterpage, BlogCustomMasterpage);
web.CustomMasterUrl =
web.CustomMasterUrl.Replace(BlogDefaultMasterpage, BlogCustomMasterpage);
web.Update();
}
}
});
}
NB: pathToBlogMasterPage is extracted from SPFeatureReceiverProperties instance and web is an instance of SPWeb that represents the newly created blog website.
Sunday, October 19, 2008
Paste formatted C# source code into blogger posts
It is very simple to use:
- copy source code from your IDE (like VisualStudio)
- paste source code into the source code box on this website: http://www.manoli.net/csharpformat/
- click on "format my code" button
- click on the "select all" button
- copy the HTML code
- go to your blog post
- switch to HTML mode (click on "Edit Html" tab)
- paste copied HTML code
There is one more thing you should do. Either add a link to "csharp.css" file (the file is available for download on the website) to template of your blogger blog or select "embed stylesheet" option before clicking on "format my code" button.
NB: You should be able to use the same tool with other blog engines or any other HTML pages.
Properly disposing SPWeb.Webs items
One of dispose patterns that he showed is about SPWeb.Webs items disposal. He first showed one of the wrong ways you can use SPWeb.Webs collection:
void WebsLeak()
{
using (SPSite siteCollection = new SPSite("http://moss"))
{
using (SPWeb outerWeb = siteCollection.OpenWeb())
{
foreach (SPWeb innerWeb in outerWeb.Webs)
{
// SPWeb innerWeb leak
}
} // SPWeb object outerWeb.Dispose() automatically called
} // SPSite object siteCollection.Dispose() automatically called
}
Then he showed the right way to handle SPWeb.Webs collection:
void WebsBestPractice()
{
using (SPSite siteCollection = new SPSite("http://moss"))
{
using (SPWeb outerWeb = siteCollection.OpenWeb())
{
foreach (SPWeb innerWeb in outerWeb.Webs)
{
innerWeb.Dispose();
}
} // SPWeb object outerWeb.Dispose() automatically called
} // SPSite object siteCollection.Dispose() automatically called
}
You can see on line 9 that "innerWeb" is disposed as it should be. The thing is that Roger didn't show that innerWeb instance must be used in either "using" block or in "try" block with disposal in "finally" block. If "innerWeb" is not used in "using" block (or in "try & finally") then it may happen that an exception is thrown before innerWeb.Dispose method is called.
I didn't think it is significant and assumed developers will recognize this as a potential leak and will always use "innerWeb" in "using" block. After some time I saw this mistake in source code of web parts being used in production environment and I instructed developers who wrote the code to fix the potential issue. Then I saw the same bug a few days ago on a lecture called "MOSS 2007 for developers - how to avoid mistakes" on a Microsoft conference I attended in Novi Sad.
I thought I should blog about this and point other developers to this issue. Next code shows one of the proper ways SPWeb.Webs should be used and disposed:
void WebsBestPractice()
{
using (SPSite siteCollection = new SPSite("http://moss"))
{
using (SPWeb outerWeb = siteCollection.OpenWeb())
{
SPWebCollection innerWebs = outerWeb.Webs;
if (innerWebs != null && innerWebs.Count > 0)
{
foreach (SPWeb innerWeb in innerWebs)
{
using (innerWeb)
{
//use innerWeb here
}
}
}
} // SPWeb object outerWeb.Dispose() automatically called
} // SPSite object siteCollection.Dispose() automatically called
}
You can see in line 12 that "innerWeb" is used in "using" block. No matter if an exception happens in line 14, the "innerWeb" will be disposed.