Sunday, January 29, 2012

Sharepoint Designer “checked out” problem

Sometimes in Sharepoint Designer showing “checked out” even though they were not!

To solve this problem, You need to clear a local web cache. This Works in SharePoint Designer 2007 and SharePoint Designer 2010.

Areas to clear:
  • %APPDATA%\Microsoft\Web Server Extensions\Cache
  • %USERPROFILE%\AppData\Local\Microsoft\WebsiteCache\
In WInXP
  • %USERPROFILE%\Local Settings\Application Data\Microsoft\WebsiteCache

Capatcha using Javascript

Most of the websites use the technique of captcha for validation / verification purpose whenever someone tries accomplish membership or want to submit a piece of information. The generation of captcha can be done in various ways. We can use server side scripting or even we can use client side scripting.
I am need to host SharePoint 2010 in shared environment and does not allow me to deploy server side control. Then tha best way to use captcha is javascript.

Here is a sample code of capatcha using javascript:

<html>
<head>
<title>Captcha</title>

<script type="text/javascript">

//Created / Generates the captcha function
function DrawCaptcha()
{
var a = Math.ceil(Math.random() * 10)+ '';
var b = Math.ceil(Math.random() * 10)+ '';
var c = Math.ceil(Math.random() * 10)+ '';
var d = Math.ceil(Math.random() * 10)+ '';
var e = Math.ceil(Math.random() * 10)+ '';
var f = Math.ceil(Math.random() * 10)+ '';
var g = Math.ceil(Math.random() * 10)+ '';
var code = a + ' ' + b + ' ' + ' ' + c + ' ' + d + ' ' + e + ' '+ f + ' ' + g;
document.getElementById("txtCaptcha").value = code
}

// Validate the Entered input aganist the generated security code function
function ValidCaptcha(){
var str1 = removeSpaces(document.getElementById('txtCaptcha').value);
var str2 = removeSpaces(document.getElementById('txtInput').value);
if (str1 == str2) return true;
return false;

}

// Remove the spaces from the entered and generated code
function removeSpaces(string)
{
return string.split(' ').join('');
}


</script>



</head>
<body onload="DrawCaptcha();">
<table>
<tr>
<td>
Welcome To Captcha<br />
</td>
</tr>
<tr>
<td>
<input type="text" id="txtCaptcha"
style="background-image:url(1.jpg); text-align:center; border:none;
font-weight:bold; font-family:Modern" />
<input type="button" id="btnrefresh" value="Refresh" onclick="DrawCaptcha();" />
</td>
</tr>
<tr>
<td>
<input type="text" id="txtInput"/>
</td>
</tr>
<tr>
<td>
<input id="Button1" type="button" value="Check" onclick="alert(ValidCaptcha());"/>
</td>
</tr>
</table>
</body>
</html>

This is simple but you can complicate it to eliminate cracking.

SharePoint Designer 2010 Workflow does not Start Automatically, when an item is created or modified

I Create a new "List Workflow" through Sharepoint Designer 2010 and set the workflow setting with Start workflow automatically when an item is create or modified.




Then save and publish the workflow. Now goto the list and create or edit the items, the attached workflow not invoke.

I found my problem . I need to login into another non system account user.


Saturday, January 28, 2012

How to Remove {generate-id()} from a Customized Form in SharePoint

If you wrote xslt in SharePoint Designer html tag with id it automatically adds {generate-id()}

example


when it saved in SharePoint designer it will be:


There is many articles take about solution for this:
http://sympmarc.com/2007/10/12/how-to-remove-generate-id-from-a-customized-form-in-sharepoint/

But I see it is very useful to make id of any element unique prevent conflict of elements between different webparts.


Thursday, January 26, 2012

Use email in SharePoint 2010 Sandbox

In SharePoint 2010 Sandbox. In Sandbox Microsoft.SharePoint.Utilitiesis not avaliable. When tried to use System.Net.Mail methods available to us. SmtpClient constructor give me error.
I found another way using SharePoint Designer workflow. You can trigger a workflow to run programmatically and also supply information to the workflow and set the initiation values. Here's the code to start a workflow:


///
/// Method to handle starting the appropriate Workflow as specified by the Site Collection Workflow Name property
///

private void StartWorkflow()
{
SPWorkflowAssociation wfa = SPContext.Current.Web.WorkflowAssociations.GetAssociationByName(this.SiteCollectionWorkflowName, CultureInfo.InvariantCulture);
wfa.AssociationData = this.GetWorkflowInitiationData();
SPContext.Current.Site.WorkflowManager.StartWorkflow(null, wfa, this.GetWorkflowInitiationData(), SPWorkflowRunOptions.Asynchronous);
}


///
/// Method to construct the Workflow Initiation/Association Data
///

/// A string containing the XML schema and values necessary for the Association Data
private String GetWorkflowInitiationData()
{
String schema = "http://www.w3.org/2001/XMLSchema\" " +
"xmlns:dms=\"http://schemas.microsoft.com/office/2009/documentManagement/types\" " +
"xmlns:dfs=\"http://schemas.microsoft.com/office/infopath/2003/dataFormSolution\" " +
"xmlns:q=\"http://schemas.microsoft.com/office/infopath/2009/WSSList/queryFields\" " +
"xmlns:d=\"http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields\" " +
"xmlns:ma=\"http://schemas.microsoft.com/office/2009/metadata/properties/metaAttributes\" " +
"xmlns:pc=\"http://schemas.microsoft.com/office/infopath/2007/PartnerControls\" " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
"{0}" +
"
";



StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}", this.SendToEmailAddress);
sb.AppendFormat("{0}", this._subject.Text);
sb.AppendFormat("{0}", this._comments.Text);
sb.AppendFormat("{0}", this._email.Text);
sb.AppendFormat("{0}", this.AutoResponseSubject);
sb.AppendFormat("{0}", this.AutoResponseText);
return String.Format(schema, sb.ToString());
}




SharePoint 2010 SPQuery Paging

For better performance you can do paging in SharePoint without returning all items. But There you can only arrows prev and next page, you cannot use numbering page.

This sample code of paging:

<asp:DropDownList ID="DropDownListSortColumns" runat="server"
onselectedindexchanged="DropDownListSortColumns_SelectedIndexChanged" AutoPostBack=true>
<asp:ListItem>IDasp:ListItem>
<asp:ListItem>Titleasp:ListItem>
<asp:ListItem>Createdasp:ListItem>
<asp:ListItem>Modifiedasp:ListItem>

asp:DropDownList>
<asp:DropDownList ID="DropDownListSortOrder" runat="server"
onselectedindexchanged="DropDownListSortOrder_SelectedIndexChanged" AutoPostBack=true>
<asp:ListItem Value="True">Ascendingasp:ListItem>
<asp:ListItem Value="False">Descendingasp:ListItem>
asp:DropDownList>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns=true class="style1">
asp:GridView>

<table style="float:right; width:100px">
<tr>
<td>
<asp:LinkButton ID="LinkButtonPrevious" runat="server"
onclick="LinkButtonPrevious_Click"><<asp:LinkButton>
td>
<td>
<asp:Label ID="LabelPaging" runat="server" Text="Label">asp:Label>td>
<td>
<asp:LinkButton ID="LinkButtonNext" runat="server"
onclick="LinkButtonNext_Click">>>asp:LinkButton>
td>
tr>
table>


Step Two:

Now we need to handle the data load events , sort column change events and the paging buttons events . For that we need to write event handlers

protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
LoadData(1);
}
}

private void LoadData(int currentPage)
{
ViewState["CurrentPage"] = currentPage;
FillData(ViewState["Next"] as string, DropDownListSortColumns.SelectedValue,Convert.ToBoolean( DropDownListSortOrder.SelectedItem.Value));
}

private void FillData(string pagingInfo, string sortColumn, bool sortAscending)
{
int currentPage = Convert.ToInt32(ViewState["CurrentPage"]);
uint rowCount = 5;
string columnValue;
string nextPageString = "Paged=TRUE&p_ID={0}&p_" + sortColumn + "={1}";
string PreviousPageString = "Paged=TRUE&PagedPrev=TRUE&p_ID={0}&p_" + sortColumn + "={1}";
SPListItemCollection collection;

//first make a call to fetch the desired result set
//here is the actual call to the dal function
collection = DAL.GetTestItems(sortColumn, sortAscending, pagingInfo, rowCount);
DataTable objDataTable = collection.GetDataTable();
GridView1.DataSource = objDataTable;
GridView1.DataBind();

//now we need to identify if this is a call from next or first

if (null != collection.ListItemCollectionPosition)
{
if (collection.Fields[sortColumn].Type == SPFieldType.DateTime)
{
columnValue = SPEncode.UrlEncode( Convert.ToDateTime(collection[collection.Count - 1][sortColumn]).ToUniversalTime().ToString("yyyyMMdd HH:mm:ss"));
}
else
{
columnValue = SPEncode.UrlEncode( Convert.ToString(collection[collection.Count - 1][sortColumn]));
}

nextPageString = string.Format(nextPageString, collection[collection.Count - 1].ID, columnValue);
}
else
{
nextPageString = string.Empty;
}

if (currentPage > 1)
{

if (collection.Fields[sortColumn].Type == SPFieldType.DateTime)
{
columnValue = SPEncode.UrlEncode(Convert.ToDateTime(collection[0][sortColumn]).ToUniversalTime().ToString("yyyyMMdd HH:mm:ss"));
}
else
{
columnValue =SPEncode.UrlEncode( Convert.ToString(collection[0][sortColumn]));
}

PreviousPageString = string.Format(PreviousPageString, collection[0].ID, columnValue);
}
else
{
PreviousPageString = string.Empty;
}


if (string.IsNullOrEmpty(nextPageString))
{
LinkButtonNext.Visible = false;
}
else
{
LinkButtonNext.Visible = true;
}


if (string.IsNullOrEmpty(PreviousPageString))
{
LinkButtonPrevious.Visible = false;
}
else
{
LinkButtonPrevious.Visible = true;
}


ViewState["Previous"] = PreviousPageString;
ViewState["Next"] = nextPageString;
LabelPaging.Text = ((currentPage - 1) * rowCount) + 1 + " - " + currentPage * rowCount;
}

protected void LinkButtonPrevious_Click(object sender, EventArgs e)
{
LoadData(Convert.ToInt32(ViewState["CurrentPage"]) - 1);
}

protected void LinkButtonNext_Click(object sender, EventArgs e)
{
LoadData(Convert.ToInt32(ViewState["CurrentPage"]) + 1);
}

protected void DropDownListSortColumns_SelectedIndexChanged(object sender, EventArgs e)
{
ViewState.Remove("Previous");
ViewState.Remove("Next");
LoadData(1);
}

protected void DropDownListSortOrder_SelectedIndexChanged(object sender, EventArgs e)
{
ViewState.Remove("Previous");
ViewState.Remove("Next");
LoadData(1);
}


Step 3

Now the last step is to add the DAL class for this solution to complete

public class DAL
{

public static SPListItemCollection GetTestItems(string sortBy, bool sortAssending, string pagingInfo, uint rowLimit)
{
SPWeb objWeb = SPContext.Current.Web;
SPListItemCollection collection;
SPQuery objQuery = new SPQuery();
objQuery.RowLimit = rowLimit;
objQuery.Query = "";
objQuery.ViewFields = "";
if (!string.IsNullOrEmpty(pagingInfo))
{
SPListItemCollectionPosition position = new SPListItemCollectionPosition(pagingInfo);
objQuery.ListItemCollectionPosition = position;
}

collection = objWeb.Lists["Test"].GetItems(objQuery);
return collection;
}
}

Saturday, January 21, 2012

Use User Task WebPart to display Site Collections Tasks

Out of the box SharePoint ships with the User Tasks Web Part which allows you to display tasks assigned to the current user in the current Site.

If you want to display all Tasks in SiteCollection you can use CQWP or DataView. But there is an easy way to do that for the same user experience. The best approach is to change the value of a hidden property of the User Tasks Web Part QuerySiteCollection. This property is hidden and cannot be modified through the UI.

First export User Tasks WebPart and add property:

<QuerySiteCollection xmlns="http://schemas.microsoft.com/WebPart/v2/Aggregation">true</QuerySiteCollection>

before the </WebPart> tag

And import again. Check the result.

This will work with SharePoint 2007/SharePoint 2010.


Friday, January 20, 2012

Editing contents of a WSP (SharePoint 2010)

In Solution file WSP in SharePoint 2010, you can see the contents of the WSP by changing the file extension to CAB. You can then open the file like a ZIP file within Windows Explorer, or via WinRAR.

But you cannot modify it using one of these items:

  • Creating a new archive file within Windows Explorer – and changing to CAB or WSP extension.
  • Trying to delete or drag into an archive shown in Windows Explorer.
  • Creating a new archive with WinRAR – and/or dragging into a CAB file using WinRAR.
  • Using MAKECAB.EXE to create an archive via command line is difficult.

I found tool (IZArc) solve this problem. Steps involved to update the WSP are as follows :

  1. Rename the WSP to CAB
  2. Extract all contents to a folder – using Windows Explorer, or WinZip, WinRAR, or whatever
  3. Change the items you want.
  4. Create a new CAB file with the updated contents, using IZARC. (IZARC support many types Archived type must be CAB and include subfolders)
  5. Rename the newly created CAB to WSP
  6. Install to SharePoint


Thursday, January 19, 2012

SharePoint 2010 Sandbox Visual WebPart

When you use sandbox Visual Web Part and TemplateControl.LoadControl method is not working in a sandbox solution?
The reason is quite simple – your code in a sandbox solution actually executes in a console application – the SPUCWorkerProcess.exe. It is a console application has created an HttpContext and a Page instance, in which your web part class is also instantiated on that page. You don’t have some crucial asp.net pieces as the HostingEnvironment and the VirtualPathProvider – without these two the LoadControl method simply won’t work. And it is not that you don’t have access to the file system, even if you had, the LoadControl method still wouldn’t work because there wouldn’t be a VirtualPathProvider to provide the file to the asp.net compiler. The bad news is that the same holds for the TemplateControl.ParseControl method too.

Microsoft create template supports Visual Web Parts in the sandbox from Visual Studio 2010 you can use when download Visual Studio 2010 Sharepoint Power Tools



SharePoint 2010 Sandbox Form Post limitation

When try to use form created in sandbox solution. I found error when post data more than 128 KB. It is one limitation of more limitations in sandbox solutions.

We need to increase size to increase this limit requestlengthdiskthreshold.

Sandbox processes use SPUCHostService.exe/SPUCHostService.exe. which has extra web.config (C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\UserCode\web.config), When you updated requestlengthdiskthreshold value in this web.config problem will be solved. But this solution would not work on a hosting provider. There would be little chance they would change their UserCode settings for me.