Hi all,
It’s been a while. Today I posted a new blog at CustomWare site.
If you are interested in finding a complete reference for custom actions locations, group IDs and sample screenshots, please check out these links:
All about SharePoint programming, configuration, technology, best practices and news
Hi all,
It’s been a while. Today I posted a new blog at CustomWare site.
If you are interested in finding a complete reference for custom actions locations, group IDs and sample screenshots, please check out these links:
Today I installed and configured JIRA 4 Beta 3 in my local PC to check if the product developed by us works as expected with the new version of JIRA 4 Beta 3 API Web Service.
Installation and setting up of JIRA 4 Beta 3 doesn't trouble me much, then I proceed with testing of our product abd it works perfectly without the need for code changes.
So I investigated further the Web Service Definition Language (WSDL) for JIRA 4 Beta 3 and compared to previous version of JIRA 3.13.4 and 3.13.5. It turned out there are total of 8 new methods that have been added with this new version of JIRA 4 Beta 3 API Web Service, these includes:
In JIRA 3.13.4 and 3.13.5, there are total of 100 methods exposed by JIRA API Web Service - based on my initial investigation, none of existing methods are deprecated or updated in JIRA 4 Beta 3 (Don't count on this, let wait until Atlassian release a final documentation on JIRA API Web Service)
Brad has a great post on how to Hover (MouseOver) Highlight and Click to Stay Highlighted in a SharePoint List and the BEST thing he did mentioned my name (“a guy called Sukri”) – Thanks Brad.
Note:
The entire solution step by step with code segment can be found at CustomWare site: SharePoint - Customising List Default View - Implementing mousehover & click highlighting in Default List View
The server-packages of June Cumulative Update for Microsoft Office SharePoint Server 2007 and Windows SharePoint Services 3.0 are ready for download. See below:
Download Information
Windows SharePoint Services 3.0 June cumulative update package
http://support.microsoft.com/hotfix/KBHotfix.aspx?kbnum=971538
Office SharePoint Server 2007 June cumulative update package
http://support.microsoft.com/hotfix/KBHotfix.aspx?kbnum=971537
Detail Description
Description of the Windows SharePoint Services 3.0 June cumulative update package
http://support.microsoft.com/kb/971538
Description of the Office SharePoint Server 2007 June cumulative update package
http://support.microsoft.com/kb/971537
When configure SharePoint Single Sign-On (SSO), sometimes you’ll get “You do not have the rights to perform this operation.” error message on the “Manage Settings for Single Sign-On” page and subsequently “User DOMAIN\USERID failed to configure the single sign-on server. The error returned was ERROR NUMBER. Verify this account has sufficient permissions and try again.” error message is displayed in the Windows Event Viewer and SharePoint Log.
To fix this issue, you have to make sure “Single Sign-On Administrator Account” account name to start the Microsoft Single Sign-On Service MUST meet all of the following:
Also most important setting is to MAKE SURE, the same “Single Sign-On Administrator Account” account name is used at both “Manage Server Settings for Single Sign-On” page and “Service Accounts” page as shown below:
When displaying custom data through SPGridView you won’t get the same look and feel of the default SharePoint List View. SPMenuField provides a data bound drop-down menu to be used in place of BoundField, TemplateField, or similar controls.
The following describe steps required to add drop-down menu items to a SPGridView control in Web Part.
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Collections.Generic;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
public class SampleGrid : WebPart
{
}
protected override void CreateChildControls()
{
// Why UseDefaultStyles = false?
// See http://sharepointmalaya.blogspot.com/2009/07/how-to-make-spgridview-to-have-same.html for details
this.UseDefaultStyles = false;
// ObjectDataSource
ObjectDataSource dataSource = new ObjectDataSource();
dataSource.ID = "dataSource";
dataSource.SelectMethod = "SelectData";
dataSource.TypeName = this.GetType().AssemblyQualifiedName;
dataSource.ObjectCreating += new ObjectDataSourceObjectEventHandler(objectCreating);
this.Controls.Add(dataSource);
// SPGridView
spGridView = new SPGridView();
spGridView.ID = "spGridView";
spGridView.DataSourceID = dataSource.ID;
spGridView.AutoGenerateColumns = false;
spGridView.AllowPaging = true;
spGridView.PageSize = 10;
spGridView.AllowSorting = true;
spGridView.EmptyDataText = string.Empty;
this.Controls.Add(spGridView);
// SPGridViewPager
pager = new SPGridViewPager();
pager.GridViewId = spGridView.ID;
this.Controls.Add(pager);
// SPMenuField - Name field
SPMenuField nameCol1 = new SPMenuField();
nameCol1.HeaderText = "Name";
nameCol1.TextFields = "Name";
nameCol1.NavigateUrlFields = "Name,Email,WebSite";
nameCol1.NavigateUrlFormat = "/_layouts/sharepointmalaya/DispDetails.aspx?WebPartID=" + this.ID + "&FilterName={0}&ReturnUrl=" + Page.Request.Url.ToString();
nameCol1.TokenNameAndValueFields = "KEYNAME=Name,KEYEMAIL=Email,KEYWEBSITE=WebSite";
nameCol1.SortExpression = "Name";
nameCol1.MenuTemplateId = "menuTemplate";
// MenuTemplate
MenuTemplate menuTemplate = new MenuTemplate();
menuTemplate.ID = "menuTemplate";
this.Controls.Add(menuTemplate);
spGridView.Columns.Add(nameCol1);
// MenuTemplate - View Item
MenuItemTemplate menuItemTemplate0 = new MenuItemTemplate("View Item", "~/_layouts/images/LIST.GIF");
menuItemTemplate0.ClientOnClickNavigateUrl = "/_layouts/sharepointmalaya/DispDetails.aspx?WebPartID=" + this.ID + "&FilterName={%KEYNAME%}&ReturnUrl=" + Page.Request.Url.ToString();
menuTemplate.Controls.Add(menuItemTemplate0);
// MenuTemplate - Seperator
MenuSeparatorTemplate menuSepTemplate = new MenuSeparatorTemplate();
menuTemplate.Controls.Add(menuSepTemplate);
// MenuTemplate - Open WebSite
MenuItemTemplate menuItemTemplate1 = new MenuItemTemplate("Open WebSite", "~/_layouts/images/ASP16.GIF");
menuItemTemplate1.ClientOnClickNavigateUrl = "javascript:window.open('%KEYWEBSITE%');";
menuTemplate.Controls.Add(menuItemTemplate1);
// MenuTemplate - Send Email
MenuItemTemplate menuItemTemplate2 = new MenuItemTemplate("Send Email", "~/_layouts/images/EML16.GIF");
menuItemTemplate2.ClientOnClickScript = "javascript:document.location.href='MailTo:%KEYEMAIL%;'";
menuTemplate.Controls.Add(menuItemTemplate2);
// BoundField - Email field
BoundField nameCol2 = new BoundField();
nameCol2.DataField = "Email";
nameCol2.SortExpression = "Email";
nameCol2.HeaderText = "Email";
spGridView.Columns.Add(nameCol2);
// BoundField - WebSite field
BoundField nameCol3 = new BoundField();
nameCol3.DataField = "WebSite";
nameCol3.SortExpression = "WebSite";
nameCol3.HeaderText = "WebSite";
spGridView.Columns.Add(nameCol3);
this.ChildControlsCreated = true;
}
SPMenuField.TokenNameAndValueFields = "KEYNAME=Name,KEYEMAIL=Email,KEYWEBSITE=WebSite";
“%TOKEN_NAME%” OR “%KEYWEBSITE%”
public DataTable SelectData()
{
DataTable table = new DataTable();
table.Columns.Add("Name");
table.Columns.Add("Email");
table.Columns.Add("WebSite");
table.Rows.Add("SharePoint Malaya","sharepointmalaya@gmail.com","http://sharepointmalaya.blogspot.com");
table.Rows.Add("Faris","faris@gmail.com","http://sharepointmalaya.blogspot.com");
table.Rows.Add("Farhana","farhana@gmail.com","http://sharepointmalaya.blogspot.com");
return table;
}
private void objectCreating(object sender, ObjectDataSourceEventArgs e)
{
e.ObjectInstance = this;
}
protected override void Render(HtmlTextWriter writer)
{
if (ChildControlsCreated)
spGridView.DataBind();
base.Render(writer);
}
Get sample code here:
When you attempt to develop a Web Part that uses an SPGridView control, you’ll notice the following differences to your SPGridView look and feel compared to the out of the box SharePoint List View:
Screenshot below shows the differences:
If you’re good in CSS and HTML, then you’ll find CSS Reference Chart for SharePoint 2007 is helpful and you should be able to change your SPGridView styles to have the same look and feel of of the out of the box SharePoint List View.
Instead of doing above you can assign the WebPart.UseDefaultStyles of your Web Part to false. See code below:
protected override void CreateChildControls()
{
this.UseDefaultStyles = false;
By setting the UseDefaultStyles to false, your SPGridView styles will have the same look and feel of the out of the box SharePoint List View. See screenshot below:
Please note that UseDefaultStyles only applicable for SharePoint Web Part and not ASP.NET Web Part – for ASP.NET Web Part please use SPChromeSettings.UseDefaultStyles.
If you are building a custom Web Part to upload document to SharePoint Document Library, then you need to validate user’s base permission so that unauthorised user can’t perform upload. You can’t validate based on their permission levels since at anytime base permissions of any permission level can be changed by administrator. Plus, in object model there is no specific method to get the permission level or what permission level assigned to a group or a user.
This article describes how to perform document upload to SharePoint and validate user base permissions so that only authorized users are able to perform the upload.
In SharePoint, the out-of-the-box permission level allowed user with "Contribute" permission level or higher (i.e. "Full Control", "Design", "Manage Hierarchy" and "Approve") to upload document to SharePoint. The following code displays the base permissions for each permission level:
SPSite oSite = new SPSite("http://examplesite");
SPWeb oWeb = oSite.OpenWeb();
SPRoleDefinitionBindingCollection usersRoles = oWeb.AllRolesForCurrentUser;
foreach (SPRoleDefinition roleDefinition in usersRoles)
retVal += roleDefinition.BasePermissions.ToString() + " | ";
System.Diagnostics.Debug.WriteLine(retVal);
“Full Control” permission level:
“Design” permission level:
“Manage Hierarchy” permission level:
“Approve” permission level:
“Contribute” permission level:
“Read” permission level:
and for "Site Collection Administrator" user, base permission as follows:
To validate whether user access rights to upload document to SharePoint, the following conditions shall be used:
See code below for details:
public static void IsUserBasePermissionValidToUpload(SPWeb oWeb)
{
try
{
if (oWeb.Exists)
{
// If user is site collection administrator or admin
if (oWeb.UserIsWebAdmin || oWeb.UserIsSiteAdmin)
return;
// Get roles for current user
SPRoleDefinitionBindingCollection usersRoles = oWeb.AllRolesForCurrentUser;
// Validate if user has rights to upload document
foreach (SPRoleDefinition roleDefinition in usersRoles)
{
if (roleDefinition.BasePermissions.ToString().Contains(SPBasePermissions.FullMask.ToString())
|| roleDefinition.BasePermissions.ToString().Contains(SPBasePermissions.AddListItems.ToString())
|| roleDefinition.BasePermissions.ToString().Contains(SPBasePermissions.EditListItems.ToString())
|| roleDefinition.BasePermissions.ToString().Contains(SPBasePermissions.ApproveItems.ToString()))
return;
}
// If user has invalid rights, then throw exceptions
throw new Exception("Unauthorised to upload document to SharePoint Document Library. " +
"You are currently signed in as: " + oWeb.CurrentUser.LoginName);
}
}
catch (Exception ex)
{
throw ex;
}
}
When you need to redirect to pages located at _layouts folder, the safest way is to use SPUtility.Redirect method. The following are sample to redirect to settings.aspx page:
SPUtility.Redirect("settings.aspx", SPRedirectFlags.UseSource | SPRedirectFlags.RelativeToLayoutsPage, HttpContext.Context);
If you want to redirect to custom pages at _layout folder, see below:
SPUtility.Redirect("sharepointmalaya/customadminsettings.aspx", SPRedirectFlags.Static | SPRedirectFlags.RelativeToLayoutsPage | SPRedirectFlags.RelativeToLocalizedLayoutsPage, HttpContext.Current);
Details on the SPRedirectFlags enumerations can be found here.
There are many approaches to check if MOSS or WSS is installed at specific installation site. One of the approach is to check the Windows Registry key.
If MOSS is installed, there will be registry entries in the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office Server\12.0
If WSS is installed, there will be registry entries in the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\12.0
Please note that if MOSS is installed both registry entries as shown above will be exist at installation sites.
I’ve created a helper class SharePointConfig.cs which exposes method and properties which are useful to those who are interested use this approach. See code below:
public class SharePointConfig
{
private const string MOSS_REGISTRY_PATH = @"SOFTWARE\Microsoft\Office Server\12.0";
private const string MOSS_BUILD_VERSION = "BuildVersion";
private const string MOSS_TEMPLATE_PATH = "TemplatePath";
private const string WSS_REGISTRY_PATH = @"SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\12.0";
private const string WSS_BUILD_VERSION = "BuildVersion";
private const string WSS_TEMPLATE_PATH = "TemplatePath";
private bool _ismossinstalled;
private bool _iswssinstalled;
private string _buildversion;
private string _templatepath;
/// <summary>
/// Initializes a new instance of the <see cref="SharePointConfig"/> class.
/// </summary>
public SharePointConfig()
{
GetSharePointConfig();
}
/// <summary>
/// Gets a value indicating whether this instance is MOSS installed.
/// </summary>
/// <value>
/// <c>true</c> if this instance is MOSS installed; otherwise, <c>false</c>.
/// </value>
public bool IsMOSSInstalled
{
get { return _ismossinstalled; }
}
/// <summary>
/// Gets a value indicating whether this instance is WSS installed.
/// </summary>
/// <value>
/// <c>true</c> if this instance is WSS installed; otherwise, <c>false</c>.
/// </value>
public bool IsWSSInstalled
{
get { return _iswssinstalled; }
}
/// <summary>
/// Gets the build version.
/// </summary>
/// <value>The build version.</value>
public string BuildVersion
{
get { return _buildversion; }
}
/// <summary>
/// Gets the template path.
/// </summary>
/// <value>The template path.</value>
public string TemplatePath
{
get { return _templatepath; }
}
/// <summary>
/// Loads the share point config.
/// </summary>
public void GetSharePointConfig()
{
try
{
// Assume current user has full rights to registry settings
SPSecurity.RunWithElevatedPrivileges(delegate()
{
// Get MOSS registry key
RegistryKey theRegistry = Registry.LocalMachine.OpenSubKey(MOSS_REGISTRY_PATH);
if (theRegistry != null)
{
// Get registry values
_buildversion = theRegistry.GetValue(MOSS_BUILD_VERSION).ToString();
_templatepath = theRegistry.GetValue(MOSS_TEMPLATE_PATH).ToString();
_ismossinstalled = MossOrWSSIsFound();
}
else
{
// Get WSS registry key
theRegistry = Registry.LocalMachine.OpenSubKey(WSS_REGISTRY_PATH);
if (theRegistry != null)
{
// Get registry values
_buildversion = theRegistry.GetValue(WSS_BUILD_VERSION).ToString();
_templatepath = theRegistry.GetValue(WSS_TEMPLATE_PATH).ToString();
_iswssinstalled = MossOrWSSIsFound();
}
}
});
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// Mosses the or WSS is found.
/// </summary>
/// <returns></returns>
private bool MossOrWSSIsFound()
{
bool retVal = false;
try
{
if (!string.IsNullOrEmpty(_buildversion) && !string.IsNullOrEmpty(_templatepath))
{
Version buildVersion = new Version(_buildversion);
if (buildVersion.Major == 12)
retVal = true;
}
}
catch (Exception ex)
{
throw ex;
}
return retVal;
}
}
The following tables list the members exposed by the SharePointMalaya.SSOHelper.SSOConfiguration type.
SharePointConfig - Initializes a new instance of the SharePointConfig class, get registry key for either MOSS or WSS.
IsMOSSInstalled - Gets a value indicating whether MOSS instance is installed.
IsWSSInstalled - Gets a value indicating whether WSS instance is installed.
BuildVersion - Gets either MOSS or WSS build version.
TemplatePath - Gets either MOSS or WSS template path.
Get source code here:
Sample Web Part
If you want to display “Open tool pane” link in Web Part for SharePoint, just like the one displayed in the Content Editor Web Part and several others out-of-the-box Web Parts. Then add the following JavaScript code to your Web Part class:
lblErrorMessage.text = "<a href=\"javascript:MSOTlPn_ShowToolPane2Wrapper('Edit', this,'" + this.ID + "')\">Open tool pane</a>"
Get source code here:
Screenshots
I’ve created a helper component SharePointMalaya.SSOHelper.SSOConfiguration that helped to provide the specific methods to retrieve username and password from the given SharePoint SSO provider application name.
The SharePointMalaya.SSOHelper.SSOConfiguration source code details are shown below:
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Web;
using Microsoft.SharePoint;
using MSSO = Microsoft.SharePoint.Portal.SingleSignon;
namespace SharePointMalaya.SSOHelper
{
/// <summary>
///
/// </summary>
public class SSOConfiguration
{
#region Member Variables
private string _username;
private string _password;
private bool _isexistssoprovider;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="SSOConfiguration"/> class.
/// </summary>
/// <param name="ssoApplicationName">Name of the sso application.</param>
public SSOConfiguration(string ssoApplicationName)
{
try
{
ConnectToSSO(ssoApplicationName);
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
#region Public Properties
/// <summary>
/// Gets the username.
/// </summary>
/// <value>The username.</value>
public string Username
{
get { return _username; }
}
/// <summary>
/// Gets the password.
/// </summary>
/// <value>The password.</value>
public string Password
{
get { return _password; }
}
/// <summary>
/// Gets a value indicating whether SSO provider is exist.
/// </summary>
/// <value>
/// <c>true</c> if this instance is exist SSO provider; otherwise, <c>false</c>.
/// </value>
public bool IsExistSSOProvider
{
get { return _isexistssoprovider; }
}
#endregion
#region Private Methods
/// <summary>
/// Connects to SSO.
/// </summary>
/// <param name="ssoApplicationName">Name of the sso application.</param>
private void ConnectToSSO(string ssoApplicationName)
{
try
{
MSSO.ISsoProvider provider = MSSO.SsoProviderFactory.GetSsoProvider();
if (provider != null)
{
MSSO.SsoCredentials creds = provider.GetCredentials(ssoApplicationName);
IntPtr pUserName = IntPtr.Zero;
IntPtr pPassword = IntPtr.Zero;
try
{
// Get the non-secure string version of the credentials
pUserName = Marshal.SecureStringToBSTR(creds.UserName);
_username = Marshal.PtrToStringBSTR(pUserName);
pPassword = Marshal.SecureStringToBSTR(creds.Evidence[1]);
_password = Marshal.PtrToStringBSTR(pPassword);
_isexistssoprovider = true;
}
finally
{
//Zero out and free the BSTR pointers
if (IntPtr.Zero != pUserName)
{
Marshal.ZeroFreeBSTR(pUserName);
}
if (IntPtr.Zero != pPassword)
{
Marshal.ZeroFreeBSTR(pPassword);
}
}
}
}
catch (MSSO.SingleSignonException ssoEx)
{
throw ssoEx;
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
}
}
The following tables list the members exposed by the SharePointMalaya.SSOHelper.SSOConfiguration type.
SSOConfiguration - Initializes a new instance of the SSOConfiguration class, connects to SSO provider and get the username and password.
Username - Gets the username from SSO provider.
Password - Gets the password from SSO provider.
IsExistSSOProvider - Gets a value indicating whether SSO provider is exist.
Example
The following is code sample on how to connect to the SSO provider and retrieve stored SSO username and password:
if (!string.IsNullOrEmpty(txtSSOApplicationName.Text))
{
// Instantiate SSOConfiguration and connect to SharePoint SSO provider by passing SSO Application Name
SSOConfiguration objSSOConfiguration = new SSOConfiguration(txtSSOApplicationName.Text);
// Check if SSO provider is found
if (objSSOConfiguration.IsExistSSOProvider)
{
// Assign stored SSO Username and Password to controls
lblSSOUsername.Text = objSSOConfiguration.Username;
lblSSOPassword.Text = objSSOConfiguration.Password;
}
}
The following are screenshot showing a user logon to SharePoint site and retrieve his/her username and password from “SSO_Provider1” SSO Provider application name.
Get source code here:
In any SharePoint project, sometimes there is a need to create an external custom RDBMS database to host non-related SharePoint information outside SharePoint's Content Database for example user credentials for form-based authentication, look up data, etc. To do this, the obvious solution is to use either one of following techniques:
None of the above technique is wrong!
However, I found technique no. 1 (install custom RDBMS database using .SQL file) is time-consuming and more prone to error - especially if customer who doing installation is not technical at all or the .SQL file doesn't obey the rules. For technique no. 2 - you need strong knowledge in Microsoft Windows Installer packaging tools and you need to download/configure MSI Redistributable package if you don't have one. So, the best solution is to utilize the SharePoint Feature Framework.
Features are the backbone of SharePoint development because every custom development project can and really should be deployed as a feature. Features give tremendous control over SharePoint configurations and capabilities at the administrator level. This means that developers can create features and then turn them over to SharePoint administrators without having to get involved repeatedly in small configuration changes.
I have developed a REUSEABLE FEATURE(SharePointMalaya.Feature.CustomDBInstaller.dll) that able to automate the installation of custom RDBMS database to any SharePoint’s database server. All you need to do is to generate SQL scripts using MS Server Management Studio, save the SQL scripts to SharePointMalaya.Feature.CustomDBInstaller feature folder, build WSP, install and activate the feature at SharePoint site.
SharePointMalaya.Feature.CustomDBInstaller feature comprises of SharePoint Event Handler which inherits from base abstract class SPFeatureReceiver to trap the activation, deactivation, installation, or uninstallation of a Feature. See codes below:
private const string FEATURE_FOLDER_PATH = "TEMPLATE\\FEATURES\\SharePointMalaya.Feature.CustomDBInstaller\\";
private const string TSQL_SCRIPT_INSTALLDB_FOLDER_PATH = FEATURE_FOLDER_PATH + "T-SQL\\Install\\";
private const string TSQL_SCRIPT_UNINSTALLDB_FOLDER_PATH = FEATURE_FOLDER_PATH + "T-SQL\\UnInstall\\";
/// <summary>
/// Occurs after a Feature is activated.
/// </summary>
/// <param name="properties">An <see cref="T:Microsoft.SharePoint.SPFeatureReceiverProperties"></see> object that represents the properties of the event.</param>
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
try
{
// Run with an account with higher privileges than the current user
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite oSite = properties.Feature.Parent as SPSite)
{
SPWeb oWeb = null;
if (oSite != null)
oWeb = oSite.RootWeb;
else
oWeb = properties.Feature.Parent as SPWeb;
if (oWeb.Exists)
{
// Turn off security validation
oWeb.AllowUnsafeUpdates = true;
// Execute T-SQL scripts from <<FEATUREFOLDER>>\T_SQL\Install folder
ExecuteSQLScripts(oSite, TSQL_SCRIPT_INSTALLDB_FOLDER_PATH);
// Turn on security validation
oWeb.AllowUnsafeUpdates = false;
}
else
throw new Exception("Unable to open site.");
}
});
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// Occurs when a Feature is deactivated.
/// </summary>
/// <param name="properties">An <see cref="T:Microsoft.SharePoint.SPFeatureReceiverProperties"></see> object that represents the properties of the event.</param>
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
try
{
// Run with an account with higher privileges than the current user
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite oSite = properties.Feature.Parent as SPSite)
{
SPWeb oWeb = null;
if (oSite != null)
oWeb = oSite.RootWeb;
else
oWeb = properties.Feature.Parent as SPWeb;
if (oWeb.Exists)
{
// Turn off security validation
oWeb.AllowUnsafeUpdates = true;
// Execute T-SQL scripts to uninstall from <<FEATUREFOLDER>>\T_SQL\UnInstall folder
ExecuteSQLScripts(oSite, TSQL_SCRIPT_UNINSTALLDB_FOLDER_PATH);
// Turn on security validation
oWeb.AllowUnsafeUpdates = false;
}
else
throw new Exception("Unable to open site.");
}
});
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// Executes the SQL scripts.
/// </summary>
/// <param name="oSite">The o site.</param>
/// <param name="scriptsPath">The scripts path.</param>
private void ExecuteSQLScripts(SPSite oSite, string scriptsPath)
{
SqlConnection objCon = null;
SqlCommand objCmd = null;
try
{
// Get SharePoint content database connection string
string connectionString = oSite.ContentDatabase.DatabaseConnectionString;
// Get T-SQL script files for installing database from Feature folder
string[] fileEntries = Directory.GetFiles(SPUtility.GetGenericSetupPath(scriptsPath));
// files exist then open connection to database and sort file by name
if (fileEntries.Length > 0)
{
// Create and open connection object
objCon = new SqlConnection(connectionString);
objCon.Open();
// Sort file name
Array.Sort(fileEntries);
// Loop for each files in directory
foreach (string fileName in fileEntries)
{
// Proceed if file name is not empty and file extension is .SQL
if (!string.IsNullOrEmpty(fileName) && fileName.EndsWith(".sql"))
{
string tsqlScript = string.Empty;
using (StreamReader reader = new StreamReader(fileName))
{
// Reading all lines in file and parse T-SQL
tsqlScript = PrepareTSQL(reader.ReadToEnd());
// Proceed if content of the file is not empty
if (!string.IsNullOrEmpty(tsqlScript))
{
// Create command object
objCmd = new SqlCommand(tsqlScript, objCon);
objCmd.CommandType = CommandType.Text;
// Execute non query
objCmd.ExecuteNonQuery();
}
}
}
}
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (objCmd != null) objCmd.Dispose();
if (objCon.State == ConnectionState.Open) objCon.Close();
if (objCon != null) objCon.Dispose();
}
}
/// <summary>
/// Prepares the TSQL.
/// </summary>
/// <param name="tsqlScript">The TSQL script.</param>
/// <returns></returns>
private string PrepareTSQL(string tsqlScript)
{
string retVal = string.Empty;
try
{
// Replace "GO" statement with empty string since GO is not a valid command in ADO.NET
retVal = tsqlScript.Replace("GO", string.Empty);
}
catch (Exception) { }
return retVal;
}
Get source code here:
The following are four (4) simple steps to update the SQL scripts to SharePointMalaya.Feature.CustomDBInstaller feature folder, build WSP, install and activate the feature:
Step 1: Generate SQL Scripts using MS Server Management Studio
Step 2: Drop the SQL Scripts to either 'Install' or 'UnInstall' folder
Step 3: Build WSP
Step 4: Install and Activate SharePoint Feature
Brad has provided a workaround on how to use a JavaScript technique to manipulate SharePoint Form Field using SharePoint Designer 2007. The code in his blog supported the following SharePoint Field Types, but NOT Choice (Radio Buttons) field type:
Let say you have a requirement from a customer to develop a SharePoint list for storing user credentials which has the following UI mock-up:
The requirement stated that when ‘Anonymous’ authentication mode radio button is selected, hide Username and Password textbox else display Username and Password textbox.
The following are steps required to add JavaScript to the SharePoint Form List page (NewForm.aspx and EditForm.aspx):
<script language="javascript" type="text/javascript">
_spBodyOnLoadFunctionNames.push("selectedAuthenticationMode");
function selectedAuthenticationMode() {
// to get the array for radio buttons
var myRadioButtonsArray = getTagFromIdentifierAndTitle("input", "RadioButtons", "Authentication_x0020_Mode");
for (var x = 0; x < myRadioButtonsArray.length; x++) {
if (myRadioButtonsArray[x].value == 'ctl00') // per-user static authentication mode
{
// create client event handler - onclick
myRadioButtonsArray[x].parentElement.onclick = function() {
// display username and password textbox
var controlUserName = findacontrol("Username");
controlUserName.parentNode.parentNode.style.display = "";
var controlPassword = findacontrol("Password");
controlPassword.parentNode.parentNode.style.display = "";
};
}
else // anonymous authentication mode
{
// create client event handler - onclick
myRadioButtonsArray[x].parentElement.onclick = function() {
// unhide username and password field
var controlUserName = findacontrol("Username");
controlUserName.parentNode.parentNode.style.display = "none";
var controlPassword = findacontrol("Password");
controlPassword.parentNode.parentNode.style.display = "none";
};
}
}
}
function getTagFromIdentifierAndTitle(tagName, identifier, title, option) {
var len = identifier.length;
var tags = document.getElementsByTagName(tagName);
for (var i = 0; i < tags.length; i++) {
var idString = tags[i].id;
var nameString = tags[i].name;
// get selected radio button value only
if (option == "value" && tags[i].type == "radio" && (identifier == "RadioButtons" && nameString.indexOf(identifier) == nameString.length - len)) {
var tagParentHTML = tags[i].parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.innerHTML;
if (tagParentHTML.indexOf('FieldInternalName="' + title + '"') > -1) {
var radioButtons = document.getElementsByName(nameString);
var radioValue = "";
for (var x = 0; x < radioButtons.length; x++) {
if (radioButtons[x].checked) {
radioValue = radioButtons[x].parentElement.title;
break;
}
}
var o = document.createElement("INPUT");
o.type = "hidden";
o.value = radioValue;
return o;
}
}
// get radio buttons group
if (tags[i].type == "radio" && (identifier == "RadioButtons" && nameString.indexOf(identifier) == nameString.length - len)) {
var tagParentHTML = tags[i].parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.innerHTML;
if (tagParentHTML.indexOf('FieldInternalName="' + title + '"') > -1) {
return document.getElementsByName(nameString);
}
}
// all other input or select type
else if (tags[i].title == title && (identifier == "" || idString.indexOf(identifier) == idString.length - len)) {
return tags[i];
}
}
return null;
}
function findacontrol(FieldName) {
var arr = document.getElementsByTagName("!");
// get all comments
for (var i = 0; i < arr.length; i++) {
// now match the field name
if (arr[i].innerHTML.indexOf('FieldInternalName=\"' + FieldName + '\"') > -1) {
return arr[i];
}
}
}
</script>
Instead of having to create a new custom Web Part or a XSLT List Form page for a SharePoint List, this approach provides uncomplicated customization and the best thing is the out-of-the-box functionalities of the List Form View for a SharePoint List are still intact.
Sample Screenshot