Wednesday, September 05, 2012

Repeated authentication prompts from SharePoint

In the past few weeks I had two clients with a similar issue - both had some users expiriencing multiple requests for user name and password whenever they accessed the site. With one client entering the user name and password sometimes worked, and sometimes would request 10 times and then show the site, and sometimes would just result in a blank, empty page. With the other client, they would always get to a "internet explorer cannot display the web page" error page.

If you research the issue on your favorite search engine, you will find a lot of references to authentication providers (forms, claims and so on), registry issues, trusted sites or intranet zone settings or maybe the users are on the server and the loopback check was not disabled. Well, none of these were valid in the case of these two clients - for one thing, the users were not on the server - they were on their desktops. For another thing - even when the site was added to trusted sites it still happened. Most perpelxingly - with one client it only happenned to users on windows XP, not the users who were on Windows7...

After wasting a lot of time troublshooting the issue, I finally realised what must be different between those users and the rest, and why it sometimes worked and sometimes it didn't - it was the proxy server!

Turns out both clients had a proxy server, with proxy settings deployed to desktops via group policy. The proxy would behave differently every time it was asked for the new web site address, and would cause an authentication prompt for each image on the page. In one organisation, the proxy settings that were deployed were different for Windows XP users - which explains why only those users expirienced the issues.

The solution? I told the network admins to either add the web site to the proxy exception list in IE (via group policy) or fix the proxy server itself.

Tuesday, August 28, 2012

Setting a default to the site collection administrator value

If you are like me, you may find yourself constantly creating site collections manually to test and retest something or other, and scripting the site collection creation doesnt always make sense - depending on what you are testing.

Today I got tired of entering the user name over and over again in the site collection administrator box - it is always the name of my user - which is the only user in my domain as it is a stand along development box. So...I hacked the page for site collection so it would have a default and I won't have to worry about it. Note that this should only be done in development boxes, and at your own risk.

My solution was to edit the built-in "createsite.aspx" file, sitting at "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\ADMIN\createsite.aspx". In that file I located the "PeopleEditor" control with ID "PickerOwner" and added CommaSeparatedAccounts="mydomain\ishai". Save, and done!

Thursday, August 23, 2012

Activating Features using PowerShell does not trigger feature event code

If you ever try to activate a feature using powershell, and the code the feature was supposed to run doesnt run (or it runs, but doesnt reflect your changes) consider this- PowerShell, much like IIS, scans the GAC when it is started and caches the assemblies there. If you redeployed your code with modifications to your feature event handler (or anything else) and use an already open powershell window, the code will fail or will run the old version of the code, because it is cached.

Lesson learnt: always close the powershell window and open a new one when deploying a package...

Tuesday, August 21, 2012

Setting the "AllowedContentTypes" for a document set doesnt work

I really liked Cory's article on how to deploy documents sets using declartive XMl. However, when implementing it, I noticed two issues that prevented sharepoint from using the AllowedContentTypes declartion I used.

The first - the culprit was Inherits="TRUE" Version="0" in the content type declaration. If I removed those, sharepoint created the content type with the allowed content types properly defined.

The second one is that the content type that is referenced inside the AllowedContentTypes has to be created by a seperate feature. I had carefully made sure that all the document content types are declared before the document sets, but nothing worked until I seperated the document sets to a seperate feature, with a dependancy on the document content types' feature.

Duplicate content type "report" error

If you have a visual studio project that deploys a content type with the name "Report" - it may work...until you try to deploy it to a different site template. Different site templates in sharepoint contain different built-in content types, which explains why you should test your content type deploying solutions on different templates before announcing them ready for production!

Tuesday, July 31, 2012

CAML Query on datetime columns

I always forget (and end up looking it up again), so I might as well write a blog post so I can search my own blog instead of the entire internet.

The issue is when you are doing a CAML query to get items from a sharepoint list, and want to specify a filter based on a datetime column in that list - to be greater than the current date for example.

There are two issues when querying datetime fields - the first, is comparing datet time values in the correct format, and the second is relevant if you want the query to include the time, and not just the date.
To handle the first, the query requires you to convert the date value you are comparing to, to a format recognised by sharepoint's caml. To do so, you should use
the SPUtility.CreateISO8601DateTimeFromSystemDateTime function on the date value you want to compare to.
Here is an example of testing that the "Expires" column is greater or equal to the current date:

<geq>
             <fieldref name="Expires">
             <value type="DateTime">" + SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Now) + @"</value>
          </fieldref></geq>

The second issue is when we want to make the same comparison, but include the time in the query. we have the "Expires" field set to accept both date and a time, the query above will only compare the date - so even items that should have expired an hour ago, would still show - until tomorrow.
To fix that, we need to add IncludeTimeValue='TRUE' to the value node:
<value includetimevalue="TRUE" type="DateTime">" + SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Now) + @"</value>

Thursday, July 26, 2012

Securing custom application pages

When you create a custom application page in sharepoint (a page deployed to the layouts folder) as part of a visual studio project, often you will want to make sure it is used by the right people. Especially if the actions on the page happen with elevated privilages.

The only security settings you get out of the box is setting rules on when the links to those pages are shown through custom actions. In a custom action you can specify required permissions on the site, and so the link isnt shown to people who are not supposed to use the page.

The problem is - any user can open the page if they just type the URL in the browser. To avoid this, I always add a bit of script that checks if the user is allowed to use the page. Where? In the Page_Load function!

Here is an example of how I secured a page to only show to web administrators, and I also added a check that a required feature has to be activated in the site or the page will not display. For this purpose, I made sure all the controls in the web page are in a panel called pnlControls - so I can easily hide them when the user shouldnt be using the page. I also created a lable called lblErrors outside the panel - so I can so an error to the user if they are not supposed to use the page. An alternative would be to just redirect the user to the site's home page.


Here is the sample:

protected void Page_Load(object sender, EventArgs e)
{
            lblErrors.Visible=false;
            if (!IsFeatureActivated(SPContext.Current.Web, new Guid(Constants.C_SiteActionsFeatureID)))
            {
                lblErrors.Visible=true;
                lblErrors.Text = "The required feature is not activated in this site. This page is not available when the feature is not activated.";
                pnlControls.Visible = false;
                return;
            }
            if (!SPContext.Current.Web.UserIsWebAdmin)
            {
                lblErrors.Visible = true;
                lblErrors.Text = "You don't have permissions to view this page. Only web administrators are allowed to use the functionality on this page.";
                pnlControls.Visible = false;
                return;
            }
}

public static bool IsFeatureActivated(SPWeb web, Guid featureId)
        {
            return web.Features[featureId] != null;
        }

Friday, July 20, 2012

Troubleshooting SharePoint 2010 issues

Friend and colleague in Extelligent Design Jeremy Taylor is doing a webcast on Troubleshooting SharePoint 2010 issues (with some 2013 coverage). Head over to his blog to register!
http://www.jeremytaylor.net/webcast/

Wednesday, July 11, 2012

Reporting code errors when running code in SPLongOperation

As we all know, SPLongOperation is a great device to run a bit of code that takes a long time, while showing the user a turning cogwheel, and then redirecting when the operation is done.
However, when I checked, I saw people are on the search for a way to properly report on errors that happen during the long operation.
Some solutions involve redirecting to a new page, and passing the errors' details in the query string, or in some other way. Another way is to use the "EndScript" method to show a javascript "alert" (a messagebox, with the details.
I'd like to propose a different way. The page that is showing the cogwheel can be modified using the same javascript ("EndScript" method) by injecting html with the error details into the 's4-simple-card-content' div. This is critical if the page that is doing the long operation was opened as a dialog - in which case redirecting can be confusing, and we want to show the error if there was one, or close the dialog if there wasnt.
Example:

SPLongOperation longOp = new SPLongOperation(this.Page);
StringBuilder sbErrors = new StringBuilder();
longOp.Begin();try
{
throw new Exception("Sample");
}
catch(Exception ex)
{
  sbErrors.Append("An error occurred: " + ex.MEssage);
}

if
(sbErrors.Length > 0)
{
longOp.EndScript(
"document.getElementById('s4-simple-card-content').innerHTML = \"Errors have occurred during the submission. Details: " + sbErrors.ToString() + " \";");
}
//close the dialog if there were no errors

longOp.EndScript("window.frameElement.commitPopup();");

Thursday, May 17, 2012

SharePoint Upgrade or Migrate

Hello again everyone.
In March I have published an article in IDM magazine (australia) about upgrading sharepoint and what is the difference between that and migration, and the pros and cons of each one. I even gave tips to successfull upgrade\migration projects. If you want to read it, I have now republished it in my company's site:
http://www.extelligentdesign.com/Articles/UpgradingSharePoint.aspx
Feel free to drop me comments on the article here (and please feel free to tell people about it).