Archive
SharePoint 2010: Configuring incoming emails on a Production Environment (non-Exchange Server)
Recently I needed to setup incoming emails on a SharePoint 2010 site sadly, after researching this subject a lot, I was not able to find a blog that provided a complete answer of how to set this up on a Production Environment. There are some variations in the way this can be setup but the method I will be explaining in this blog involves a non-Exchange Server method.
Assumptions
I am assuming that:
- You have setup an SMTP server on one of your SharePoint WFE’s (Web Front End) if you are not sure on how to do this then please check out this post.
- You have a domain name registered and that you can modify the DNS records
The Solution
The solution involves:
- Setting up the DNS Records
- Configuring the SMTP Server
- Configuring Central Administration
- Configuring a SharePoint List
Setting up the DNS Records
In this example I am using a domain name: http://www.shareheaven.co.uk that is registered with GoDaddy.com.
Login to your domain name’s control panel and add a DNS A (Host) record in the following format:
Where the host (‘notify’ in this example) can be anything of your liking. The IP address should be the IP address of the server that hosts the SMTP Server.
Next we need to add a DNS MX Record in the following format:
Wait for the DNS changes to take effect, you can use this website to check if the changes have taken effect.
Configuring the SMTP Server
On the SMTP Server we will need to add an alias. Open IIS 6.0 Manager > Expand your SMTP Server in the list on the left hand side > Right click on ‘Domains’ > New > Domains.
On this screen (screen shot above) select Alias and click Next and then fill it out as below (based on your domain name):
Configuring Central Administration
Next we need to setup Central Administration to enable incoming emails in our SharePoint Farm, in Central Admin browse to System Settings > Configure incoming e-mail settings and set it up as below:
Configuring a SharePoint List
Finally, we can now setup a SharePoint List to receive incoming emails. In this example I will be setting up a Document Library to receive incoming emails. Browse to Library Settings > Incoming e-mail settings of the SharePoint List you would like to setup to receive incoming emails. Fill out the form as below and click ‘OK’:
Testing the Solution
To test the solution send an email to the email address we setup to receieve incoming emails which in our example was: test@shareheaven.co.uk (replace shareheaven with your domain name of course!):
Screen shot below shows the .eml file arriving in the drop folder of the SMTP Server:
A SharePoint Timer Job picks up this email, processes it and then adds an item in the Document Library:
Archiving documents in SharePoint 2010 OTB
There might be other ways of setting this up but I thought I should write about a way of achieving this by purely utilising SharePoint 2010 out-of-the-box features.
Scenario
You have a document library, we will call it Documents, that has a custom Content Type (we will call it ER Documents). Based on a certain criteria, lets say 6 months after a document has been approved, you would like to archive the document by moving it to another document library called ‘ER Compliance Archived Documents’.
Assumptions
You have two identical document libraries setup with the same content type enabled.
The Solution
The solution involves:
- Enabling the Content Organizer Feature
- Creating a Content Organizer Rule
- Configuring a ‘send to’ connection
- Configuring the Document Library
Enabling the Content Organizer Feature
On the root web of your Site Collection browse to Site Actions > Site Settings > Manage Site Features and activate the ‘Content Organizer’ Feature.
After this feature is activated you will notice two new options in Site Settings (highlighted in the screenshot below) and a new document library called ‘Drop Off Library’:
Click on ‘Content Organizer Settings’ and make a note of the Web Service URL:
Creating a Content Organizer Rule
Click on the ‘Content Organizer Rules’ link and add a new item to create a new rule and set it up as below (click on the image if it appears a bit blurred):
This rule basically specifies where and how to route the archived documents.
Configuring a ‘send to’ connection
Browse to Central Administration > General Application Settings > Configure send to connections. Select the correct Web Application and create a new send to connection by filling out the form as below pasting the Web Service URL you copied earlier:
Click on ‘Add Connection’ and then ‘OK’.
Configuring the Document Library
Browse to the main ‘Documents’ document library > Library Settings > Information management policy settings > ER Documents (this is our content type) > Check ‘Enable Retention’ and fill the form out as below:
Testing the solution
Add a document that matches the archiving criteria (i.e. Approval Date more than 6 months ago).
Go to Central Administration > Monitoring > Review job definitions > select your Web Application and manually run the ‘Information management policy’ timer job. This job process and marks the documents, that match the criteria we have setup, for transfer. After the job has completed manually run the ‘Expiration policy’ timer job this timer job does the actual transfer of the marked documents.
After this the relevant documents that match the Information management policy criteria will be moved to the archived library.
You can also test this manually by browsing to the ‘Documents’ document library> Accessing the context menu > Send to > ER Compliance Archive (screenshot below).
The document should then appear in the archive document library. Please note that the manual send to method moves the document immediately but it is a useful way of testing whether you have configured the routing correctly.
SharePoint 2010: Exaction SharePoint User Manager
I have developed two commercial SharePoint User Manager Products for Exaction:
- Exaction (AD) SharePoint User Manager
- Exaction (SQL) SharePoint User Manager
This product is also available in MOSS 2007.
Please click here to go to the Exaction site and view more details.
The Exaction SharePoint User Manager solutions provide a set of user friendly SharePoint web parts that allow the end-user the ability to easily manage SharePoint user accounts. The Exaction (SQL) SharePoint User Manager solution is designed to typically work in an FBA enabled site with ASP.NET Membership as the provider where the users are stored in an SQL database (please view this post to see how this can be setup) whereas the Exaction (AD) SharePoint User Manager solution is designed to typically work in a site that uses Windows Authentication.
Below are some of the key features it has to offer:
- Ability to view a complete list of users
- Ability to sort and filter User data
- Ability to add, edit and delete FBA Users
- Ability to Reset passwords, unlock, enable and disable accounts
- Configurable password policy settings
- Ability to retrieve forgotten password
- Configurable auto-generated email notifications
- Ability to send out bulk email notifications to all system active or inactive users
- Export user data to excel
- Configurable security
- Easy to use and intuitive user interface
- Quick installation and configuration
- Easily customisable UI
- Several built in skins
The solution contains the following three web parts:
- User Manager web part
- Manage My Account web part
- Forgot My Password web part
1 User Manager web part
The User Manager web part uses a Telerik RadGrid to display a list of Users. Apart from providing the ability to view a list of all users the web part also provides the ability to:
- Filter the data
- Sort the data by any column
- Paginate data and to specify page size
- Edit existing User accounts
- Add new users
- Delete a user account (Admin function)
- Unlock user accounts
- Activate and de-activate user accounts
- Export data to excel (Admin function)
- Notify All Active And Inactive Users (Admin function)
As it uses the Telerik RadGrid to display the data it comes with several built in Skins and is fully customisable (please refer to http://demos.telerik.com/aspnet-ajax/grid/examples/overview/defaultcs.aspx to see an overview of the features provided by the Telerik RadGrid)
The screen shot below shows the initial view seen by the end user when accessing the Web Part:
1.1 Adding a new User
The User Manager web part provides an easy and convenient way of adding new users to the system and adding them to SharePoint groups at the same time to grant them access to the Site.

When a user is successfully created a password is automatically generated and the details are emailed to the newly created user.
1.2 Deleting existing Users
Users can be easily deleted by clicking on the
icon on the Grid. Clicking on the cross prompts the end user to confirm that they would like to delete this record. Upon confirmation the account is deleted, please look at the screen shot below:
This feature i.e. Deleting a User can be enabled, disabled and you can specify the SharePoint Group that will have permissions to perform this action.
1.3 Activating and Deactivating User Accounts
Based on the status of the User account the Grid will display an action that will allow the end user to Activate or Deactivate an account. For example if the user account is active then it will display the ‘Deactivate’ action. Clicking on this action will de-activate the user account. On the other hand if the user account has already been deactivated then it will display the ‘Activate’ action. Clicking on this action will activate the User Account. Please note that attempting to deactiviate an account will first prompt the end user to confirm that they are sure they want to proceed with the action.
1.4 Editing existing user accounts
Clicking on the edit
icon opens up a modal dialog box that allows the end user to edit existing user account details.
The form also provides the means to change a user’s password and a means to modify the user’s SharePoint Group memberships.
1.5 Unlocking User Accounts
If a user’s account has been locked out due to repeated login failures then the
icon will appear on the Grid for that User Account. Clicking on the icon will unlock the user account.
1.6 Filtering Data
By default the User Manager Grid allows the end user to filter the data by First name, surname, username, email address and full name.
1.7 Export data to excel
Clicking on the export to excel button will export the data to an excel spreads heet. The data that will be exported will take into consideration the filters that have been applied to the view i.e. only data that matches the filtering criteria will be exported.
1.8 Notify System Users
Clicking on the ‘Notify Users’ button allows you to send notifications to all system users.
While the notifications are being generated:
After the process is complete the screen shot below displays a confirmation that the notifications were sent successfully to x number of users:
2 Manage my account web part
The Manage Account Web Part allows the logged in user to manage their account details. Changing the email address, first name and surname also updates the SharePoint profile as well as updating the membership provider store.
The Web Part also allows the user the means to change their password.
3 Forgotten my password web part
This web part allows a user to retrieve their password by filling out the form below:
Once the end user provides the username and the email address for the account an email is sent out to the registered account’s email address confirming the password.
If you require more information on the product then please click here to go to the Exaction site and view more details.
SharePoint 2010: Basic List search / filter WebPart
I have created a very simple SharePoint list search / filter WebPart which was inspired by the following blog post. This WebPart allows you to search records in a list where a selected field contains a specified text. It is useful in scenarios where you dont have SharePoint Search setup and just need a simple way of performing some search operations in a SharePoint List.
Adding the web part to SharePoint List View
Simply drop this web part on top of a page that contains a SharePoint View and it will allow you to apply a very simple search criteria.
The screenshot below shows the WebPart in action:
The field name DropDownList allows you to select from the fields that are present in the view. Once you select the field and add the text to search by, the relevant results are displayed:
You can also specify multiple text values by seperating the text with a semi-colon (;):
In the above example the specified criteria will display all the records where the manufacturer’s name contains ‘Honda’ OR ‘Audi’. The screenshot below shows the pagination working as expected:
Adding the web part to a page with an XsltListViewWebPart
You can also add this web part to a page that contains an XsltListViewWebPart. The web part will automatically detect that it has been added to a page (rather than a List View) and display a message asking you to select an XsltListViewWebPart that you would like to apply the filters to:
The screen shot below shows how to select the XsltListViewWebPart:
You can download the solution by clicking on the link below:
You can view the codeplex project site by clicking on the link below:
Please note that this is setup as a Farm Solution and not a Sandboxed Solution therefore it will not work if you deploy it to the SharePoint Solutions Gallery, you need to deploy the SharePoint Solution via Central Administration, via stsadm commands or via PowerShell commands.
How to it works
On a page that contains a ListViewWebPart you can apply filter by adding a couple of query strings:
- FilterName
- FilterMultiValue
In our example, when a user types ‘honda’ and then clicks on the search button we simply append ‘?FilterName=LinkTitle&FilterMultiValue=*honda*;’ to the query string and redirect the user to that page. Please note that ‘LinkTitle’ is the internal name of the ‘Manufacturer’ field.
The * in the *honda* is used to do a wildcard search (contains). If you would like to search for multiple texts you can seperate them by a semi-colon for example ‘FilterMultiValue=*honda*;*audi*;’ will search for records where the ‘Manufacturer’ name either contains ‘honda’ or ‘audi’. If you would like to search for an exact match rather than apply a contains filter then simply remove the *’s from the filter value text.
Although, this WebPart does not allow you to filter / search by more than one field this is very much possible. To apply filters on additional fields you simply need to append ‘FilterField1=Model&FilterValue1=Accord’ to the URL. You can apply further filters by incrementing the number i.e. FilterField2, FilterField3 …. and so on. I am not sure if there is a limit on this.
Please note that I haven’t found a way to get the wildcard search to work with this (multiple filters) approach.
Building the WebPart
In your Visual Studio solution (assuming you have created a Blank SharePoint Project) add a ‘Visual WebPart’. A Visual WebPart loads a UserControl that contains most of the code. Below is the code of the .ascx file:
<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"
Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Register TagPrefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages"
Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="ListSearchUserControl.ascx.cs"
Inherits="Exaction.ListSearch.WebParts.ListSearch.ListSearchUserControl" %>
<script type="text/javascript" src="/_layouts/Exaction.ListSearch.Javascripts/jquery.min.js"></script>
<table>
<tr>
<td>
<strong>Search Criteria:</strong>
</td>
<td>
<asp:TextBox ID="TbSearchText" runat="server" Width="300px"></asp:TextBox>
</td>
<td>
</td>
<td>
<strong>Field name:</strong>
</td>
<td>
<asp:DropDownList ID="DdlListFields" runat="server">
</asp:DropDownList>
</td>
<td>
</td>
<td>
<div align="right">
<asp:Button ID="BtnSearch" runat="server" OnClick="BtnSearch_Click" Text="Search" />
<asp:Button ID="BtnClearFilter" runat="server" Visible="false" OnClick="BtnClearFilter_Click"
Text="Clear Criteria" />
</div>
</td>
</tr>
</table>
<script type="text/javascript">
$(document).ready(function () {
var base_RefreshPageTo = RefreshPageTo;
RefreshPageTo = function (event, url) {
var filterName = getQuerystring('FilterName');
var filterValue = getQuerystring('FilterMultiValue');
var newUrl = url + '&FilterName=' + filterName + '&FilterMultiValue=' + filterValue;
if (filterName != '' && filterValue != '') {
base_RefreshPageTo(event, newUrl);
}
else {
base_RefreshPageTo(event, url);
}
return;
}
});
function getQuerystring(key, default_) {
if (default_ == null) default_ = "";
key = key.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regex = new RegExp("[\\?&]" + key + "=([^&#]*)");
var qs = regex.exec(window.location.href);
if (qs == null)
return default_;
else
return qs[1];
}
</script>
The code above is pretty self-explanatory but very briefly it contains the UI elements (TextBox, Labels, DropDownList and Buttons) and some jQuery. The jQuery code overrides the ‘RefreshPageTo’ SharePoint javascript function. This is basically to get our filtering to work with pagination. If you have a SharePoint List View that is displaying paginated date to you then clicking on the next or previous page calls the ‘RefreshPageTo’ JavaScript function. The problem is that when this function is called it clears the querystrings we use to filter the data. To ensure that the filtering is maintained we override this function, modify the URL ensuring the filtering querystrings are present and then pass it in as the second parameter to the function.
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Collections.Specialized;
using Microsoft.SharePoint;
using System.Collections.Generic;
using Exaction.ListSearch.UI.Entities;
using System.Text;
namespace Exaction.ListSearch.WebParts.ListSearch
{
/// <summary>
/// User control that deals with the registration process
/// </summary>
public partial class ListSearchUserControl : UserControl
{
/// <summary>
/// Gets the share point list field items.
/// </summary>
/// <param name="filterCriteria">The filter criteria.</param>
private List<OptionEntity> GetSharePointListFieldItems()
{
List<OptionEntity> fieldItems = new List<OptionEntity>();
fieldItems = new List<OptionEntity>();
OptionEntity item;
SPField field;
StringCollection viewFieldCollection = SPContext.Current.ViewContext.View.ViewFields.ToStringCollection();
foreach (string viewField in viewFieldCollection)
{
field = SPContext.Current.List.Fields.GetFieldByInternalName(viewField);
item = new OptionEntity();
item.Id = field.InternalName;
item.Title = field.Title;
fieldItems.Add(item);
}
return fieldItems;
}
protected override void CreateChildControls()
{
base.CreateChildControls();
List<OptionEntity> items = GetSharePointListFieldItems();
DdlListFields.DataSource = items;
DdlListFields.DataTextField = "Title";
DdlListFields.DataValueField = "Id";
DdlListFields.DataBind();
}
/// <summary>
/// Raises the <see cref="E:System.Web.UI.Control.Load"/> event.
/// </summary>
/// <param name="e">The <see cref="T:System.EventArgs"/> object that contains the event data.</param>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!IsPostBack)
{
if (Request.QueryString["FilterName"] != null)
{
DdlListFields.SelectedValue = Request.QueryString["FilterName"].ToString();
}
if (Request.QueryString["FilterMultiValue"] != null)
{
TbSearchText.Text = Request.QueryString["FilterMultiValue"].ToString().Replace("*", "");
BtnClearFilter.Visible = true;
}
}
}
/// <summary>
/// Handles the Click event of the BtnSearch control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected void BtnSearch_Click(object sender, EventArgs e)
{
string redirectUrlFormat = "{0}?FilterName={1}&FilterMultiValue={2}";
string[] selectionCollection = TbSearchText.Text.ToString().Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
StringBuilder sbValues = new StringBuilder();
foreach (string selection in selectionCollection)
{
sbValues.Append("*" + selection.Trim() + "*;");
}
string urlToRedirectTo = string.Format(redirectUrlFormat, Request.Url.GetLeftPart(UriPartial.Path), DdlListFields.SelectedValue, sbValues.ToString());
Response.Redirect(urlToRedirectTo);
}
/// <summary>
/// Handles the Click event of the BtnClearFilter control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected void BtnClearFilter_Click(object sender, EventArgs e)
{
Response.Redirect(Request.Url.GetLeftPart(UriPartial.Path));
}
}
}
The code behind above initialises the controls and handles the Search and Clear Search Criteria Button click events.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Exaction.ListSearch.UI.Entities
{
public class OptionEntity
{
#region "Fields"
public string Id { get; set; }
/// <summary>
/// Gets or sets the title.
/// </summary>
/// <value>The title.</value>
public string Title { get; set; }
#endregion
#region "Constructor"
public OptionEntity()
{
}
#endregion
}
}
We set a collection of the OptionEntity items as the DataSource of the Field name DropDownList.
That is basically it. In this simple manner you have a WebPart that you can drop on top of any List View and apply some basic free text Filterting.
Known issues
There are two minor known issues which I haven’t found a solution for yet:
- Adding the WebPart on top of the page of a List View takes the focus away from the ListViewWebPart which in turn hides the ribbon. Once you click on the ListViewWebPart and focus on it then the ribbon becomes visible.
- This WebPart does not work properly with Views that use groupings that are collapsed by default, it works if the groupings are expanded by default
- As pointed out by Goran (see comments) it might not work with External SharePoint Lists
I hope you find this WebPart useful. Please post your comments and feedback and it would be helpful if you can rate this post.
SharePoint 2010 Login issue only using IE (Internet Explorer) on an FBA enabled Site
Recently I bought a new laptop (OS: Windows 7 Professional). Using IE9 I opened up one of our SharePoint 2010 sites and tried to login and it just refreshed the login page with no error messages displayed. Using IE9 on my old laptop had never caused this issue.
I searched a lot on the interwebs to see if other people had encountered this issue and I found a lot of people in a similar situation but all the suggestions I found to solve this issue a) did not work for me, b) were unacceptable in any case. They included suggestions like adding the site as a trusted site and then making x,y and z changes to your browser settings.
One of our SharePoint 2010 site is a public facing site where people register and can gain access to the site. Imagine telling those 1000′s of users you need to make x,y,z changes to your browser settings in order to gain access to our site.
What I noticed was that I was having this issue when I clicked on the “remember me” checkbox on the login page (selecting this option issues a persistent cookie). If I did not check this option then I was able to login without any problems.
To cut a long story short, by a complete freak accident, I was able to fix this issue by making a small change in the web.config of the Web Application. If your site uses Claims Based Authentication you will see the following section in your web.config file:
<microsoft.identityModel>
<service saveBootstrapTokens="true">
<audienceUris />
<issuerNameRegistry type="Microsoft.SharePoint.IdentityModel.SPPassiveIssuerNameRegistry, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<securityTokenHandlers>
<clear />
<add type="Microsoft.IdentityModel.Tokens.X509SecurityTokenHandler, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add type="Microsoft.SharePoint.IdentityModel.SPSaml11SecurityTokenHandler, Microsoft.SharePoint.IdentityModel, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c">
<samlSecurityTokenRequirement>
<nameClaimType value="http://schemas.microsoft.com/sharepoint/2009/08/claims/userid" />
</samlSecurityTokenRequirement>
</add>
<add type="Microsoft.SharePoint.IdentityModel.SPTokenCache, Microsoft.SharePoint.IdentityModel, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
</securityTokenHandlers>
<federatedAuthentication>
<wsFederation passiveRedirectEnabled="false" issuer="https://none" realm="https://none" />
<cookieHandler mode="Custom" path="/" >
<customCookieHandler type="Microsoft.SharePoint.IdentityModel.SPChunkedCookieHandler, Microsoft.SharePoint.IdentityModel, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
</cookieHandler>
</federatedAuthentication>
</service>
</microsoft.identityModel>
I made the following change (persistentSessionLifetime=”60″):
<cookieHandler mode="Custom" path="/" persistentSessionLifetime="60">
I am not sure why but this fixed the issue for me.
Hope this helps someone else.
SharePoint 2010: List column that renders as a dynamic hyperlink
A while back I worked on a project where we needed to add a column to a SharePoint List that would display a link based on values in other columns. For example: “/myWeb/pages/mycustomPage.aspx?Reference=[ValueToComeFromAnotherColumn] i.e. similar to the way the Title field link is rendered where the URL is dynamic and based on the ID of the row in question.
In MOSS 2007 we did this by adding a calculated column that constructed the HTML using our specified formula. However, the problem was that the link would appear as:
<a href="myWeb/pages/mycustomPage.aspx?Reference=45">View</a>
To ensure it rendered as a nice and friendly hyperlink we used a script created by Christophe from PathToSharePoint.com (his blogs on the subject dont seem to exist anymore). It worked pretty well in MOSS 2007 but we found that in MOSS 2010 it didnt work if your list view had grouping by any column.
Initially I tried to get the script to work but then realised that there was a much better way to do this in SharePoint 2010. In 2010 you can control how any field is rendered by creating a custom XSLT stylesheet. In our scenario we created an XSL file which was deployed at “C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\XSL”. The XSL file must be named in the following format fldtypes_*.xsl, where * is any valid filename string value for example fldtypes_MyCustomDefinitions.xsl. Our XSL file looked something like this:
<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal">
<xsl:template match="FieldRef[@Name='FormLink']" mode="Computed_body">
<xsl:param name="thisNode" select="."/>
<a target="_blank" href="/appeal/pages/appealapplication.aspx?ApplicationRef={$thisNode/@ApplicationRef}">View Application</a>
</xsl:template>
</xsl:stylesheet>
The important bit is the match attribute in the xsl:template element where we specify the internal name of the Field we want this custom rendering applied to. What this basically does is that where ever a field with an internal name of FormLink is being rendered in a view it will render it as a hyperlink. Below is the definition for our SharePoint List Field:
<Field ReadOnly="TRUE" ID="{2DD3638A-56A0-4021-B2B9-7BBB19E191F1}" Name="FormLink" StaticName="FormLink" DisplayName="Application" Type="Computed" Group="My Custom Group" SourceID="http://schemas.microsoft.com/sharepoint/v3" />
That is all there is to it, now when ever and where ever our field is rendered in a view it renders it in our custom way.
Update: For this to work, the column you are referencing must exist in the view. In my example above I am referencing a column called “ApplicationRef” therefore for it to work in my scenario the SharePoint List View I want it to work in must have “ApplicationRef” column otherwise the value wont be picked up. Hope this makes sense.
I have created a sample Visual Studio SharePoint Project that demonstrates this functionality. Please click on the link below to download it. Just deploy the solution from Visual Studio and it will create a list with a dynamic hyperlink column.
[Update: 08/10/2012] Depending on your scenario you might find this simpler solution more feasible: http://trainerms.wordpress.com/2012/10/06/dynamic-hyperlinks-in-sharepoint-lists/
Be very, very careful when you use SPSite.OpenWeb()!
I recently came across what can only be described as a shocking and dangerous bug in the SharePoint API.
According to the MSDN documentation the SPSite.OpenWeb() method:
“Returns the site that is associated with the URL that is used in an SPSite constructor.”
Below is an example of how it is very commonly used:
using (SPSite site = new SPSite("http://www.myserver.com/parentSite/childSite"))
{
using (SPWeb web = site.OpenWeb())
{
//Do your stuff
}
}
Going by the MSDN documentation the code above should return the web site located at http://www.myserver.com/parentSite/childSite. This is further confirmed by the following statement:
“When used in conjunction with an SPSite constructor, the OpenWeb method returns the lowest-level site specified by the URL that is passed as parameter for the constructor.”
This is all true if the site located at the specified url exists. But what if it doesnt exist?
Consider a scenario where an SPWeb with the url http://www.myserver.com/parentSite exists but an SPWeb with the url http://www.myserver.com/parentSite/childSite does not exist. In this scenario you would expect the code above to throw an exception, however, it does no such thing instead it ends up opening a completely different SPWeb. In this specific scenario it returns an SPWeb with the url http://www.myserver.com/parentSite. If an SPWeb didnt exist at this url as well then it would have returned the RootWeb! (i.e. http://www.myserver.com if it existed)
In other words you would end up opening and performing actions on a totally different SPWeb! As you can imagine this can have very dangerous consequences as I only very recently found!

































