Wednesday 18 April 2012

Ribbon customization : Adding functionality to Ribbon Button

SharePoint 2010 Ribbon customization : Add functionality to the button


pre-requisite
Ribbon Basics

Writing the script in scriptblock
In the basics you saw the command action of the button firing a javascript that was inline. Supposingly if you wanted to call a block of JS code .. you cannot write it inline. For that you will have to use a ScriptBlock attribute of the CustomAction node like the following..

Writing the script in an external js file
The same javascript function can be written in an external *.js file. To achieve this, right-click on the project and Add the layouts mapped folder. In the subfolder under the layouts folder, add a js file.

Next, modify the elements.xml as below

done.


Enabling EcmaScript(JavaScript) IntelliSense in VS2010
To add intellisense to SP COM, add the following lines at the top of the js file..



/// <reference name="MicrosoftAjax.js" />

/// <reference path="file://C:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/14/TEMPLATE/LAYOUTS/SP.core.debug.js" />

/// <reference path="file://C:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/14/TEMPLATE/LAYOUTS/SP.debug.js" />



After adding the above lines, you will notice that the intellisense for the sharepoint client object model is active.

Using Client Object Model to dispplay SharePoint Status bar
Lets modify the HelloWorld function to show the message in the status bar of SharePoint. Below is the modified javascript..

/// <reference name="MicrosoftAjax.js" />

/// <reference path="file://C:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/14/TEMPLATE/LAYOUTS/SP.core.debug.js" />

/// <reference path="file://C:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/14/TEMPLATE/LAYOUTS/SP.debug.js" />


function HelloWorld() {

    this.statusID = SP.UI.Status.addStatus("Hello World",

"A message from Mano <a href='#' onclick='javascript:closeStatus();return false;'>Close</a>.", true);

    SP.UI.Status.setStatusPriColor(this.statusID, "green");

}


function closeStatus() {

    SP.UI.Status.removeStatus(this.statusID);

}


Using Client Object Model to display current selected listItems and the list id
Now that we are able to access the SP namespace, we should be able to access the SharePoint entities like the site and the web for our use. In the code snippet we will be looking at how to get the selected items and the list Id from where these items are displayed.



function ShowListInformation() {

    // get all selected items

    var items = SP.ListOperation.Selection.getSelectedItems();

    var itemCount = CountDictionary(items);

    

    // get the current list

    var listID = SP.ListOperation.Selection.getSelectedList();


    // Remove all previous status

    SP.UI.Status.removeAllStatus(false);


    this.statusID = SP.UI.Status.addStatus("Selection Information", "Item Count : "

+ itemCount.toString() + " List ID : " + listID.toString(), true);

    SP.UI.Status.setStatusPriColor(this.statusID, "blue");

}





Note: Make sure that you change the CommandAction attribute in the elements.xml with the new function
Why is the above code important ?
This code opens a whole new arena for us to play with , including to enable the button based on a condition, which we will see as we dwell deeper.

Tip: Make sure that the latest code is used to render the button
1. Make sure the app pool is recycled
2. Make sure that the browser cache is cleared

Code to Hide the Ribbon and Site Actions Menu for Anonymous Users

In SharePoint 2010 sites that use the publishing infrastructure have an option on the Navigation Settings page to hide the ribbon by default.



Other sites lack this functionality as does SharePoint Foundation. However, the code to do the hiding is simple:
public void HideRibbonForAnon() { SPRibbon current = SPRibbon.GetCurrent(this.Page); if (current != null && !this.Page.Request.IsAuthenticated) { current.CommandUIVisible = false; SiteActions actions = SiteActions.GetCurrent(this.Page); if (actions != null) { actions.Visible = false; } HideStatusBar(); } } 

internal void HideStatusBar() { string script = "document.onreadystatechange=fnRemoveAllStatus; function fnRemoveAllStatus(){removeAllStatus(true)};"; this.Page.ClientScript.RegisterClientScriptBlock(typeof(HideTheRibbon), "statusBarRemover", script, true); } 

InfoPath Forms Server, Data Sources and Authentication



OK, So I put together a nice little InfoPath form, nothing too flash – it collects some data about a site and sub sites and then goes ahead and calls a web service to create the site, sub sites and sets permissions.

Problem is that while the form works fine in the InfoPath client if I try to use it as a browser enabled form in SharePoint (which I need to do) it fails to make the data connection calls.

It’s a permission thing, basically SharePoint doesn’t pass the user credentials to the web service so the web service denies the connection.

Trying to work around it, I first thought it was to do with form trust so I fully trusted the form which meant that when I deployed it it forced me to deploy it as an administrator approved form. In simple terms it saves the form on the file system, the administrator uploads it to the central form template library (Central Administration > Application Management > Manage Form Templates) and deploys it to a site collection. This puts a feature wrapper around the form and deploys it as a content type. Apply the content type to a library and hey presto…

So I did that and it still didn’t work, that’s when I figured it was authentication and not trust that was causing the issue.

Basically to use data connections in InfoPath Forms Server (IFS from now on) you will need to create a Universal Data Connection (UDC) and store it in a Data Connection Library (DCL)… ’nuff acronyms ;-)

  • UDC = a file that stores (in plain text!) authentication details and the details of the web service (or whatever) you need to connect with.

  • DCL = just like it sounds this is where you put the UDC


So how do you write a UDC?


There’s a decent overview here: http://blogs.msdn.com/infopath/archive/2006/10/02/Data-Connections-in-Browser-Forms.aspx and if you’re anything like me you’ll want to see an example so here we go:
<?xml version="1.0" encoding="UTF-8"?>
<?MicrosoftWindowsSharePointServices ContentTypeID="0×010100B4CBD48E029A4ad8B62CB0E41868F2B0"?>
<udc:DataSource MajorVersion="2" MinorVersion="0" xmlns:udc="
http://schemas.microsoft.com/office/infopath/2006/udc">
<udc:Name>CreateSite</udc:Name>
<udc:Description>CreateSite</udc:Description>
<udc:Type MajorVersion="2" MinorVersion="0" Type="WebService">
<udc:SubType MajorVersion="0" MinorVersion="0" Type=""/>
</udc:Type>
<udc:ConnectionInfo Purpose="ReadWrite">
<udc:WsdlUrl>
http://hp-vs-moss2007:555/HP.WebServices.CreateWorkspace.asmx?wsdl</udc:WsdlUrl>
<udc:SelectCommand>
<udc:ServiceUrl>
http://hp-vs-moss2007:555/HP.WebServices.CreateWorkspace.asmx</udc:ServiceUrl>
<udc:SoapAction>HP.WebServices.CreateWorkspace/Create</udc:SoapAction>
</udc:SelectCommand>
</udc:ConnectionInfo>
</udc:DataSource>

You’ll notice that in my example above there are no authentication details. Well…that’s because I forgot to put them in! And what I actually found was that simply by using the UDC method authentication started working, I haven’t had time to look into this but I assume this is because by the very virtue of using a UDC connection held in a SharePoint library PassThrough authentication is being used. I then started adding some cod ethat runs under elevated privileges and ran into some problems, so put the authentication details back in again ala:

How do you ‘do’ one of these DCL things?


That’s easy ;-) It’s just like a document library in SharePoint. Go the the root of your site collection (that usually a site like http://server/sites/xxxx) and click Site Actions then Data Connection Library, give it a name and hey presto.

Now upload your UDC to your DCL and remember to approve the UDC.

Getting it to work with Infopath


This bit is the simple bit

  1. You create a new data connection (Tools -> Data Connections -> New -> Search for Connections on MOSS -> Add your site -> Select the UDC)

  2. And then use it as you would any other data connection


So what have you achieved?


Well you’ve kind of abstracted web service and InfoPath form so you now need to go through the UDC to get to the web service calls, of course you can go direct to the web service for normal InfoPath forms but not for web based forms. Is it good thing? Not sure, I’ve read posts saying that it makes things better because your connections are in a central library and can be shared between forms and I guess that’s something but then I can secure my form library, web service, web application etc anyway so do I really need another layer of security?

Anyway, it’s the only way it works so you’re stuck with it for now.

 

Ribbon customization : Hide Ribbon Programatically

Ribbon customization : how to hide Ribbon programatically


programatically hide a Ribbon



public void HideRibbon()

{

SPRibbon current = SPRibbon.GetCurrent(this.Page);


if (current != null && !this.Page.Request.IsAuthenticated)

{

current.CommandUIVisible = false;

}

}


programatically hide a single ribbon button



public void HideRibbonItem()

{

//if this is a System.Web.UI.Page

SPRibbon ribbon = SPRibbon.GetCurrent(this);

ribbon.TrimById("Ribbon.ListItem.New.NewFolder");

}


programatically hide the status bar




public void HideStatusBar()

{

string script = "document.onreadystatechange=fnRemoveAllStatus; function fnRemoveAllStatus(){removeAllStatus(true)};";

this.Page.ClientScript.RegisterClientScriptBlock(typeof(HideTheRibbon), "statusBarRemover", script, true);

}





programatically hide the SiteActions Menu





public void HideSiteActionsMenu()

{

SiteActions actions = SiteActions.GetCurrent(this.Page);


if (actions != null && !this.Page.Request.IsAuthenticated)

{

actions.Visible = false;

}

}



Tuesday 17 April 2012

Display SharePoint User Profile Picture - C#

SPWeb oWeb = currSite.OpenWeb();
SPList oList = oWeb.SiteUserInfoList;
SPListItem userInfo = oList.Items.GetItemById(SPContext.Current.Web.CurrentUser.ID);
imgPic.ImageUrl = userInfo["Picture"].ToString();

 

 

or

SPServiceContext context = SPServiceContext.GetContext(SPContext.Current.Site);
UserProfileManager profileManager = new UserProfileManager(context);
UserProfile theProfile = profileManager.GetUserProfile(SPContext.Current.Web.CurrentUser.LoginName);
//theProfile["PictureUrl"].Value = "<img url>";
litPic.Text = Convert.ToString(theProfile["Picture"]);
theProfile.Commit();
litPic.Text = "<img src=" + userLI["Picture"].ToString() + " />".ToString();

//userInfo.Update();

Get User Profile Details Programmatically - SharePoint

In WSS, there is a basic list called the ‘User Information List’ which holds some profile details about the users themselves. These details can be viewed/edited from the ‘My Settings’ screen.

ms

WSS holds the following user details:

  • Account (Login Name)

  • Name (Display Name)

  • E-Mail

  • About Me

  • Picture

  • Department

  • Job Title

  • SIP Address


You can get a reference to any of these properties in code simply by querying the list with the ID of the required SPUser:

e.g.

using (SPSite Site = new SPSite(“Site URL”))

{
using (SPWeb Web = Site.OpenWeb())
{


SPList UserInfoList = Web.Lists[“User Information List”];


SPUser User = Web.Users.GetByID(1); – Put the User ID Here


SPListItem UserItem = UserInfoList.GetItemById(User.ID);


UserItem[“Department”] = “Department Name”;


}


}

Using this list you can set any of the values as required or simply retrieve the stored values. I used the above to get a reference to the ‘Picture’ which is stored as a URL.

Monday 16 April 2012

upload a file to a Web server in ASP.NET by using Visual C# .NET

Complete code listing


WebForm1.aspx




<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="CSharpUpload.WebForm1" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>WebForm1</title>
<meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">
<meta name="CODE_LANGUAGE" Content="C#">
<meta name=vs_defaultClientScript content="JavaScript">
<meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" enctype="multipart/form-data" runat="server">
<INPUT type=file id=File1 name=File1 runat="server" >
<br>
<input type="submit" id="Submit1" value="Upload" runat="server" NAME="Submit1">
</form>

</body>
</HTML>



 

WebForm1.aspx.cs




using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace CSharpUpload
{
/// <summary>
/// Summary description for WebForm1.
/// </summary>
public class WebForm1 : System.Web.UI.Page
{
protected System.Web.UI.HtmlControls.HtmlInputFile File1;
protected System.Web.UI.HtmlControls.HtmlInputButton Submit1;

private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here
}

#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Submit1.ServerClick += new System.EventHandler(this.Submit1_ServerClick);
this.Load += new System.EventHandler(this.Page_Load);

}
#endregion

private void Submit1_ServerClick(object sender, System.EventArgs e)
{
if( ( File1.PostedFile != null ) && ( File1.PostedFile.ContentLength > 0 ) )
{
string fn = System.IO.Path.GetFileName(File1.PostedFile.FileName);
string SaveLocation = Server.MapPath("Data") + "\\" + fn;
try
{
File1.PostedFile.SaveAs(SaveLocation);
Response.Write("The file has been uploaded.");
}
catch ( Exception ex )
{
Response.Write("Error: " + ex.Message);
//Note: Exception.Message returns a detailed message that describes the current exception.
//For security reasons, we do not recommend that you return Exception.Message to end users in
//production environments. It would be better to return a generic error message.
}
}
else
{
Response.Write("Please select a file to upload.");
}
}
}
}


Uploading images into picture library in sharepoint using c#

spSite objSite = new SPSite(SPContext.Current.Web.Url);


try
{
byte[] imageData = null;
if (flUpload != null)
{
// This condition checks whether the user has uploaded a file or not
if ((flUpload.PostedFile != null) && (flUpload.PostedFile.ContentLength > 0))
{
Stream MyStream = flUpload.PostedFile.InputStream;
long iLength = MyStream.Length;
imageData = new byte[(int)MyStream.Length];
MyStream.Read(imageData, 0, (int)MyStream.Length);
MyStream.Close();
string filename = System.IO.Path.GetFileName(flUpload.PostedFile.FileName);
using (SPWeb myWeb = objSite.OpenWeb())
{
SPPictureLibrary pic = (SPPictureLibrary)myWeb.Lists["Images"];//Images is the picture library name
SPFileCollection filecol = ((SPPictureLibrary)myWeb.Lists["Images"]).RootFolder.Files;//getting all the files which is in pictire library
filecol.Add(filename , imageData);//uploading the files to picturte library
}
}
}
lblMessage.Text = "Uploaded successfully";
}
catch (Exception ex)
{
Response.Write(ex.Message);
}















Listing C

private void cmdUpload_Click(object sender, System.EventArgs e)

{


       if (( File1.PostedFile != null) && (File1.PostedFile.ContentLength > 0))

       {

              //determine file name

              string sFileName = System.IO.Path.GetFileName(File1.PostedFile.FileName);

              try

              {

                     if (File1.PostedFile.ContentLength <= lMaxFileSize)

                     {

                           //Save File on disk

                           File1.PostedFile.SaveAs(sFileDir + sFileName);

                           lblMessage.Visible=true;

                           lblMessage.Text="File: " + sFileDir + sFileName + " Uploaded Successfully";

                     }

                     else //reject file

                     {

                           lblMessage.Visible=true;

                           lblMessage.Text="File Size if Over the Limit of " + lMaxFileSize ;

                     }

              }

              catch(Exception)//in case of an error

              {

                     lblMessage.Visible = true;

                     lblMessage.Text="An Error Occured. Please Try Again!";

                     DeleteFile(sFileDir + sFileName);

              }

       }

}


!= null) && (File1.PostedFile.ContentLength > 0))
       {

              //determine file name

              string sFileName = System.IO.Path.GetFileName(File1.PostedFile.FileName);

              try

              {

                     if (File1.PostedFile.ContentLength <= lMaxFileSize)

                     {

                           //Save File on disk

                           File1.PostedFile.SaveAs(sFileDir + sFileName);

                           lblMessage.Visible=true;

                           lblMessage.Text="File: " + sFileDir + sFileName + " Uploaded Successfully";

                     }

                     else //reject file

                     {

                           lblMessage.Visible=true;

                           lblMessage.Text="File Size if Over the Limit of " + lMaxFileSize ;

                     }

              }

              catch(Exception)//in case of an error

              {

                     lblMessage.Visible = true;

                     lblMessage.Text="An Error Occured. Please Try Again!";

                     DeleteFile(sFileDir + sFileName);

              }

       }

}

Friday 13 April 2012

Update email address at SQL server Database in FBA (SharePoint C#)

try
{
MembershipUser usr = System.Web.Security.Membership.Providers["FBAUser"].GetUser(SPContext.Current.Web.CurrentUser.LoginName, true);
usr.Email = "emailaddress@email.com";
System.Web.Security.Membership.UpdateUser(usr);
Msg.Text += "Email is Changed at FBA <br/>";
}
catch (Exception ex)
{
Msg.Text += " *Email is not updated at FBA <br/>" + ex.Message;
}

Get the current username from windows authentication or form base authentication

string userName = " ";
SPContext currentContext;
try
{
currentContext = SPContext.Current;
}
catch (InvalidOperationException)
{
currentContext = null;
}
if (currentContext != null && currentContext.Web.CurrentUser != null)
{
//userName = SPContext.Current.Web.CurrentUser.LoginName;
userName = HttpContext.Current.User.Identity.Name;
}
else
{
WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent();
if (windowsIdentity != null)
{
userName = windowsIdentity.Name;
}
}
return userName;

Update the user information list in SharePoint at User Profile C#

SPSite spsite = SPContext.Current.Site;
SPWeb spweb = spsite.OpenWeb();
SPList splist = spweb.SiteUserInfoList;
SPListItem userInfo = splist.Items.GetItemById(SPContext.Current.Web.CurrentUser.ID);
try{
Msg.Text = " ";
if ((txtFirstName.Text != "") || (txtLastName.Text != ""))
{
userInfo["Title"] = txtFirstName.Text + " " + txtLastName.Text;
}
if (txtEmail.Text != "")
{
userInfo["Work e-mail"] = txtEmail.Text;
}
if (txtFirstName.Text != "")
{
userInfo["First name"] = txtFirstName.Text;
}
if (txtLastName.Text != "")
{
userInfo["Last name"] = txtLastName.Text;
}
if (txtMobilePhone.Text != "")
{
userInfo["Mobile phone"] = txtMobilePhone.Text;
}
if (txtWorkPhone.Text != "")
{
userInfo["Work phone"] = txtWorkPhone.Text;
}
if (txtUsername.Text != "")
{
userInfo["User name"] = txtUsername.Text;
}
Msg.Text += "Profile Details are updated";
userInfo.Update();
}
catch{
Msg.Text = "Profile Details are not updated";
}

Update the user profile picture in SharePoint

SPServiceContext context = SPServiceContext.GetContext(SPContext.Current.Site);
UserProfileManager profileManager = new UserProfileManager(context);
UserProfile theProfile = profileManager.GetUserProfile(SPContext.Current.Web.CurrentUser.LoginName);
theProfile["PictureUrl"].Value = "<img url>";
theProfile.Commit();

Get User profile details on current user in SharePoint

SPWeb web = SPControl.GetContextWeb(Context);
SPUser currentUser = web.CurrentUser;

SPSecurity.RunWithElevatedPrivileges(delegate
{
web.AllowUnsafeUpdates = true;
web.Update();
UserProfileManager upm = new UserProfileManager();
UserProfile uProfile = upm.GetUserProfile(currentUser.LoginName);
Msg.Text = Convert.ToString(uProfile[PropertyConstants.AccountName].Value);
//uProfile[PropertyConstants.Department].Value = "Department";
web.AllowUnsafeUpdates = false;
web.Update();
});

Read the user profile properties in SharePoint C#

SPSecurity.RunWithElevatedPrivileges(delegate()
{
SPSite site = SPContext.Current.Site;
using (SPWeb web = site.OpenWeb("site"))
{
SPList userList = web.Lists["list"];
SPUser user = web.EnsureUser(SPContext.Current.Web.CurrentUser.LoginName);
SPListItem item = web.SiteUserInfoList.Items.GetItemById(user.ID);
SPFieldCollection fieldColl = userList.Fields;
foreach (SPField field in item.Fields)
{
Msg.Text += "<br/>" + field.Title + "--" + field.StaticName;
}
}
});

Submitting to 'this' document library

Have you ever needed to develop an InfoPath form template that submits back to a SharePoint document library but you did not initially know the server or library name when developing the form? Or have a scenario where your InfoPath form template could be published (or added as a content type) to multiple SharePoint document libraries and you need the submit location to be dynamic? Well read on to find out how you can do this!

When you create an InfoPath form template that needs to be able to submit to a SharePoint document library, you need to specify that connection in the initial design of the form template. However, at run time you can use managed code to determine the server and library name where the form was launched and then modify the “FolderUrl” property of the submit data connection so the form is submitted to the appropriate library.

So let’s get started setting up this sample. The C# walkthrough below uses the new InfoPath 2007 managed object model; below, you will find attached the same logic implemented in InfoPath 2003 managed object model and in InfoPath 2003 JScript.

Step 1: Create a sample InfoPath Form Template

Create a browser-compatible form template as following:

  1. Add 3 text box controls, all with a data type of text, named as follows: strFormURL, strLocation and strFolderName

  2. Add a “Submit” data connection named “Mainsubmit”:

    • Set the document library name to a dummy SharePoint document library (i.e. http://server/dummyLib)

    • Use the concat function to concatenate the strFolderName field and _Test for the File Name property: concat(my:strFolderName, "_Test")

    • Enable the Allow overwrite if file exists property



  3. Set the Security Level of the form to Full Trust and sign the form template with a digital certificate

  4. Enable the Submit functionality (Tools | Submit Options) and choose the “Perform custom action using code” option


Now that we have the form, controls and submit functionality, let’s add the code to make this process work:

 

Step 2: Add the code

  • Click the Edit Code button on the Submit Options dialog

  • Create the following FormState Dictionary object – this will be used to store the form’s location when the form is initially opened:


private object _strUri
{
get { return FormState["_strUri"];
set { FormState["_strUri"] = value; }
}

 

  • Add the following code to the Forms Loading event:


// Get the Uri (or SaveLocation in a browser form) of where
// the form was opened.
// See if the form was opened in the browser

Boolean OpenedInBrowser = Application.Environment.IsBrowser;

// If so, we will get the "SaveLocation" from the InputParameters

if (OpenedInBrowser)
_strUri = e.InputParameters["SaveLocation"].ToString();
else

//If it was opened in the client, we will get the Uri
_strUri = this.Template.Uri.ToString();

 

// Populate the fields on the form - keep in mind, this

// not necessary - this is simply to see the results

PopulateLibInfo(OpenedInBrowser);

 

  • Add the following procedure to the Forms class:


private void PopulateLibInfo(Boolean OpenedInBrowser)

{

// Create a Navigator object for the main DOM
XPathNavigator xnDoc = this.MainDataSource.CreateNavigator();

 

 

// Create Navigator objects for each field

XPathNavigator xnFormURL = xnDoc.SelectSingleNode("my:myFields/my:strFormURL", this.NamespaceManager);
XPathNavigator xnLocation = xnDoc.SelectSingleNode("my:myFields/my:strLocation", this.NamespaceManager);

XPathNavigator xnFolderName = xnDoc.SelectSingleNode("my:myFields/my:strFolderName", this.NamespaceManager);

 

// Get the Uri stored in the FormState Dictionary variable

string strUri = _strUri.ToString();

 

// Create a variable to store the path (URL) to the document library

string strPath = "";

if (OpenedInBrowser == true) {

//If we are open in the browser, the strUri value is just

//the server name and library - so we just need to get

//the URL without the last "/"

strPath = strUri.Substring(0, strUri.LastIndexOf("/"));

} else {

// Parse just the path to the document library -

// this would return something like this:

//  http://server/library

strPath = strUri.Substring(0, strUri.IndexOf("Forms") - 1);
}
// Now, parse the URL to where the document library resides;
// this would return something like:

//    http://server or http://server/site
string strLoc = strPath.Substring(0, strPath.LastIndexOf("/"));

 
// Lastly, parse the URL to return just the document library name -

// in this case,we are looking for the last "/" character

// knowing that what comes after this is the document library name

string strFolder = strPath.Substring(strPath.LastIndexOf("/") + 1);

 

// Populate the fields on the form – we will use these

// values in the Submit process

xnFormURL.SetValue(strUri);

xnLocation.SetValue(strLoc);

xnFolderName.SetValue(strFolder);
}

 

  • Add the following code to the form’s Submit event:


// Create a Navigator object for the main DOM
XPathNavigator xnDoc = this.MainDataSource.CreateNavigator();
// Create Navigator objects for the fields we will

// use to modify the FolderUrl
XPathNavigator xnLocation = xnDoc.SelectSingleNode("my:myFields/my:strLocation", this.NamespaceManager);
XPathNavigator xnFolderName = xnDoc.SelectSingleNode("my:myFields/my:strFolderName", this.NamespaceManager);

 

// Get a reference to the submit data connection

FileSubmitConnection fc = (FileSubmitConnection)this.DataConnections["Main submit"];

 

// Modify the URL we want to submit to by concatenating the

// xnLocation and xnFolderName values

fc.FolderUrl = xnLocation.Value + "/" + xnFolderName.Value;

 

// Execute the submit connection

try

{

fc.Execute();

e.CancelableArgs.Cancel = false;

}

catch (Exception ex)

{

e.CancelableArgs.Cancel = true;
}

 

  • Build and save the project

  • Publish and test


And that is it! You now have an InfoPath form template that will submit to whatever document library the form was opened from so you do not need to know this information when designing the template.

The xsi:nil attribute in InfoPath

Have you ever tried to programmatically set a value on a field only to get a “schema validation” error? Many times, this error is caused by the “nillable” attribute being present on the node. The nillable attribute is a special attribute that can appear on an xsd:element within an XML schema. If an element has the xsi:nil attribute specified, it indicates that the element is present but has no value, and therefore no content is associated with it.

However, if you attempt to programmatically set a value on this node and the nillable attribute is present, you will get an error similar to: “Schema validation found non-data type errors.” You will find the nillable attribute is typically present on the following data types:

  • Whole Number (integer)

  • Decimal (double)

  • Date (date)

  • Time (time)

  • Date and Time (dateTime)


To resolve this error, your code will simply need to test if the nil attribute is present and if so, remove that attribute before setting the value on the node. The following sample procedure takes an XpathNavigator object, checks that node for the nil attribute and if it exists deletes the attribute:
public void DeleteNil(XPathNavigator node)

{

if (node.MoveToAttribute("nil", "http://www.w3.org/2001/XMLSchema-instance"))

node.DeleteSelf();

}

The above procedure is generic - you can easily call this procedure as needed before programmatically trying to set the value of a field. As an example, this code is called from the click event of a button:
//Create a Navigator object for the main data source

XPathNavigator xn = this.MainDataSource.CreateNavigator();

 

//Create a navigator object for the field (node)

//where we want to set the current date value

XPathNavigator xnfield1 = xn.SelectSingleNode("/my:myFields/my:field1", this.NamespaceManager);

 

//Check if the "nil" attribute exists on this node

DeleteNil(xnfield1);

 

//Create a new dateTime object for the current date

DateTime curDate = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day);

 

//Set the value of field1 to the current date in the

//correct format: yyyy-mm-dd

xnfield1.SetValue(curDate.GetDateTimeFormats().GetValue(5).ToString());

Using SPQuery to filter lists by Domain User Account and SPUser ID

If you want to filter a list based on the value in the look up field that is of type ‘Person or Group’, We have to consider the following options:

  • Filter by the User Name.

  • Filter by SPUser ID Property

  • Filter by Domain User account


Filter by the User Name:

By default the settings for the ‘Person or Group’ column will have the following settings.

assignedto11

The Show Field will have the “Name with Presence” selected.

When we run a SPQuery search on the list using the following code we will be able to filter the list based on the fullname of the user.

   using (SPSite oSite = new SPSite("http://vslearnwss:801"))

             {

                using (SPWeb oWeb = oSite.OpenWeb())

               {

                  oList = oWeb.Lists["Project Tasks"];

                  SPQuery query = new SPQuery();

                    query.Query = "<Where><Eq><FieldRef Name='AssignedTo' /><Value Type='User'>Karthikeyan K</Value></Eq></Where>";

                    SPListItemCollection items = oList.GetItems(query);


              }

          }


Filtering by SPUser ID :

If you want to filter the list based on the SPUser ID then follow the steps below.

  • Add an additional attribute ‘LookupId’ for the queried field in your CAML query




<FieldRef Name='AssignedTo' LookupId='TRUE'/>




The updated code is as follows.


   using (SPSite oSite = new SPSite("http://vslearnwss:801"))

              {

                using (SPWeb oWeb = oSite.OpenWeb())

           {

                oList = oWeb.Lists["Project Tasks"];

               SPQuery query = new SPQuery();

                 query.Query = "<Where><Eq><FieldRef Name='AssignedTo' LookupId='TRUE'/><Value Type='User'>7</Value></Eq></Where>";

                  SPListItemCollection items = oList.GetItems(query);

              }

           }



Filtering by Domain User Account :

If you want to filter the list based on the Domain User Account then follow the steps below.

  • Change the ‘Show Field’ Settings of the Person or Group lookup column to ‘Account’


assignedto21

 

  • Modify your code to include the domain account in the filter value.




using (SPSite oSite = new SPSite("http://vslearnwss:801"))

            {

                using (SPWeb oWeb = oSite.OpenWeb())

                {

                    oList = oWeb.Lists["Project Tasks"];

                    SPQuery query = new SPQuery();

                    query.Query = "<Where><Eq><FieldRef Name='AssignedTo' /><Value Type='User'>learnmoss\vinod</Value></Eq></Where>";

                    SPListItemCollection items = oList.GetItems(query);

                }

            }





Trying to use an SPWeb object that has been closed or disposed and is no longer valid.



 "Trying to use an SPWeb object that has been closed or disposed and is no longer valid" error message is very common amongst developers dealing with the SharePoint object model. Here is how the error looks like:

The reason behind this is a silly mistake that developers do, when trying to use the SPSite/SPWeb objects. Here is the bad code that resulted in the error:



I used the using clause alongwith the SPContext.Current.Site which resulted in this error, it implicilty disposes the SPSite object which should not be done when using the SPContext object. Lets refactor the code a little bit and have a look at the good code snippet which resolved this issue:

Thats about it, my code started working when I removed the using clause from the SPContext.Current.Site. The same thing is true when you try to either explicitly/implicitly Dispose the SPContext.Current.Web object. So moral of the story never dispose SPContext objects either implicitly leveraging the using clause or explicitly by using Dispose method from in your finally block.

Read / Write User Profiles in Sharepoint

C#
//Include a reference to the Microsoft.Office.Server assembly, and add the following using statement to your class
//using Microsoft.Office.Server.UserProfiles;

//Get the current user
SPWeb litwareWeb = SPControl.GetContextWeb(Context);
SPUser currentUser = litwareWeb.CurrentUser;
//Create a Link Button
LinkButton mySiteButton = new LinkButton();
//Create a new UserProfileManager
UserProfileManager pManager = new UserProfileManager();
//Get the User Profile for the current user
UserProfile uProfile = pManager.GetUserProfile(currentUser.LoginName);
mySiteButton.Text = "Go to My Site";
//Retrieve User Profile Information
mySiteButton.PostBackUrl = uProfile.PersonalSite.Url;

VB
//Include a reference to the Microsoft.Office.Server assembly, and add the following Imports statement to your class
//Imports Microsoft.Office.Server.UserProfiles

'Get the current user
Dim litwareWeb As SPWeb = SPControl.GetContextWeb(Context)
Dim currentUser As SPUser = litwareWeb.CurrentUser
'Create a Link Button
Dim mySiteButton as LinkButton = new LinkButton()
'Create a new UserProfileManager
Dim pManager As UserProfileManager = new UserProfileManager()
'Get the User Profile for the current user
Dim uProfile As UserProfile = pManager.GetUserProfile(currentUser.LoginName)
mySiteButton.Text = "Go to My Site"
'Retrieve User Profile Information
mySiteButton.PostBackUrl = uProfile.PersonalSite.Url

The User Profile store also maintains a change log that records the changes to the user profiles in the database. The GetRecentChanges method in the User Profile object model enables you to access the change log programmatically.

Create function in infopath form from sharepoint list value

First, you need to set an onChange event on your 2 dropdown boxes. To do so, right click your dropdown boxes --> programming --> change event. This will create a visual studio project with an empty function for your dropdown box. In this function, write this code (or something similar) :

XPathNavigator root = MainDataSource.CreateNavigator();
string FirstName = root.SelectSingleNode("<XPath of your FirstName dropdown box>", NamespaceManager).Value;
string LastName = root.SelectSingleNode("<XPath of your LastName drop down box>", NamespaceManager).Value;


SPSite oSiteCollection = newSPSite(<URL of your server, eg http://portal/>);
SPWeb oWebsiteSrc = oSiteCollection.AllWebs["<URL of the site containing the sharepoint list, eg /sites/finance/expenseaccount>"];
SPList oList = oWebsiteSrc.Lists["<Name of your list>"];

string camlQuery = "<Where><And><Contains><FieldRef Name='Name of the FirstName column'/><Value Type='Text'>" + FirstName + "</Value></Contains><Eq><FieldRef Name='Name of the LastName column' /><Value Type='Text'>" + LastName + "</Value></Eq></And></Where>";
SPQuery query = newSPQuery();
query.Query = camlQuery;


SPListItemCollection collListItemsSrc = oList.GetItems(query);

root.SelectSingleNode("<XPath of your Age Field>", NamespaceManager).SetValue(collListItemsSrc[0].GetFormattedValue("<Name of the Age column>"));

 

CAML Query to retrieve data for current user in Sharepoint

While working with SharePoint CAML queries, you will need to get current user data. (Retrieve data from a list, that filtered by current logged in user).

There are couple of ways to achieve this requirement.

1) Filter by current user “Display Name”
<Where>
<Eq>
<FieldRef Name='Person'/>
<Value Type='Text'>Lastname, Firstname</Value>
</Eq>
</Where>

Simply pass the display name of the current user to filter the data. But what if there are multiple users with same display name.

So the above method is not a ideal solution.

2) Filter by current user “User ID” – By Passing the User ID
<Where>
<Eq>
<FieldRef Name='Person' />
<Value Type='Integer'>45</Value>
</Eq>
</Where>

In this method, we pass the current users user id as the parameter and filter the data (45 is the user id of the current user). For this you will need to know the current user id. Retrieving the user id is very simple. But there is another CAML variable that can be used to get current user id.

3) Filter by current user “User ID – User id retrieved from CAML Query it self
<Where>
<Eq>
<FieldRef Name='Person' />
<Value Type='Integer'><UserID/></Value>
</Eq>
</Where>

In this scenario just pass the <UserID/> to the value field in CAML. This will always retrieve the current users user id internally.

An error occurred accessing a data source : Browser enabled infopath Error in MOSS 2007

“An error occurred accessing a data source.”
Generally it is due to database or webservice connection. If you are getting this error
Then
1. First make sure the user has sufficient permission to access the database/web service.
2. In infopath ->Tools ->Form Options ->Security and trust ->Uncheck “Automatically determine security level” (If database/webservice is on same domain then select domain else select proper option)
3. Convert your data connection in udcx file.
For this, create a data connection library in MOSS.
Now open infopath form -> tools->Data connections
Select data connection and click on “Convert… “ button.
Give data connection library url with file name.
4. Now open Data Connection Library and Right click on udcx file -> “Approve/Reject” -> Select Approve and click OK.
5. Goto Central Administration ->Application Management->configure infopath form services->
Allow user form templates to use authentication information contained in data connection files” option must be checked.

 An error occurred accessing a data source : Browser enabled infopath Error in MOSS 2007

If your database/web service is placed on another domain then you need to check next option “Allow cross-domain data access for user form templates that use connection settings in a data connection file”.

Hope, It helps!!!

Add a Custom Style Sheet to Infopath

InfoPath view .xsl files contain three or four standard internal style sheets, depending on whether you have specified a color scheme. These can be identified by the attributes controlStyle='controlStyle', tableEditor="TableStyleRulesID", languageStyle='languageStyle', and themeStyle='urn:office.microsoft.com:themeBlue'. Never modify any of these standard internal style sheets. InfoPath often regenerates these, which will cause you to lose any changes you make to them.

You can add your own custom internal or external style sheet to any or all of the view .xsl files in your form template. The best place to add it is after the InfoPath standard style sheets because styles have reverse order precedence, meaning the last value for an identical selector property wins. If both you and InfoPath have specified a value for the border property of the table selector, whichever one appears last will override the value for the same selector property of any preceding style sheet.

You might use HTML and class selectors when writing your own styles. ID selectors will not be useful because InfoPath will not allow you to place an ID attribute on an element in the XSL. This is because InfoPath autogenerates ID attributes when it creates the view.

 






div {...} <!-- HTML Selector: This will work fine. -->
.myClass {...} <!-- Class Selector: This will work fine. -->
#myId {...} <!-- ID Selector: Not useful. You cannot use custom IDs on elements -->

 


INTERNAL STYLE SHEETS


Internal style sheets are stored directly in the view .xsl file, just as the InfoPath standard style sheets are. If you want to use the same styles across multiple views you will need to copy the styles from one view .xsl file to another. Let's review the steps to add an internal style sheet.


Add a custom internal style sheet:

  1. Choose Extract Form Files from the File menu.

  2. Select a location to save your extracted form files to, and then click OK.

  3. Close InfoPath to release the lock it places on your form files.

  4. Using a text editor, open your view .xsl file.

  5. Add the following code just below the last style element:


 






<style title="myCustomStyleSheet" type="text/css">
table { FONT-FAMILY: Courier New; BORDER: solid 1px black; }
</style>

 

  1. Save your view .xsl file, and then close the text editor.

  2. Reopen your form template by right-clicking the manifest.xsf file and choosing Design.


Your custom styles should now be visible in the designer. Internal styles must be updated per view .xsl file, which can create inconsistencies if you forget to update one of the .xsl files. If you want to use the same styles across multiple views, you should consider using external style sheets instead. You can always override external styles for a particular view by using a combination of external and internal style sheets.


EXTERNAL STYLE SHEETS


External style sheets exist in separate .css files. They must be added to the form template as resource files as well as referenced in any view .xsl file that will use them. By using external style sheets you maintain a consistent set of styles across all of the views that reference them. Let's review the steps to add a custom external style sheet named myCustomStyleSheet.css.

Add a custom external style sheet as a resource file:

  1. Choose Resource Files from the Tools menu.

  2. In the Resource Files dialog box, click Add.

  3. In the Add File dialog box, navigate to and select the myCustomStyleSheet.css file, and then click OK. Figure 1 shows the file added as a resource.

  4. Click OK to close the Resource Files dialog box.


 

Figure 1. The myCustomStyle.css file has been added as a resource file.

Link to a custom external style sheet from your view .xsl file:

  1. Choose Extract Form Files from the File menu.

  2. Select a location to save your extracted form files to, and then click OK.

  3. Close InfoPath to release the lock it places on your form files.

  4. Using a text editor, open your view .xsl file.

  5. Add the following code just below the last style element:


 

 






<link href="mySstyle.css" rel="stylesheet" type="text/css"/>

 

 

  1. Save your view .xsl file, and then close the text editor.

  2. Reopen your form template by right-clicking the manifest.xsf file and choosing Design.


Your custom styles should now be visible in the designer. If you added the link element to the view .xsl file before you added the .css file as a resource, or if you later update the resource file, your updates will not be visible in the designer until you save and reopen your form template. They will, however, be visible in the form preview before you save and reopen your form template.

As long as your internal and external style sheets appear last you should not have any trouble with InfoPath overriding any of your values. However, if a scenario is encountered where a value in one of the InfoPath standard style sheets is still causing you trouble by overriding your value, add the !important declaration to yours. This will force your value to always be chosen.

 






table { FONT-FAMILY: Wingdings !important; }

 

Finally, it should be noted that inline styles are normally chosen over internal or external styles because they appear last. The !important declaration on an internal or external style will override a value on an inline style unless the inline style also uses the declaration. In other words, the !important declaration also follows the reverse order precedence.

User Id from User Information List (Hidden Web Site List in SharPoint)

This list can be accessed by the link " /_catalogs/users/simple.aspx" from the every SharePoint web site.

To get the data from this list use the following code :
SPList spList = SPContext.Current.Web.SiteUserInfoList;

Using this the basic information about the user can be accessed.
SPSite spsite = new SPSite("http://MyWebApplication");

SPWeb spweb = spsite.OpenWeb();

SPList splist=spweb.SiteUserInfoList;

SPListItem userInfo = splist.Items.GetItemById(SPContext.Current.Web.CurrentUser.ID);

string pictureURL = Convert.ToString(userItem["Picture"]);

Monday 2 April 2012

Sharepoint Server error: This item cannot be deleted because it is still referenced by other pages

We might get this error when you try to delete from the _catalogsmasterpage directory.

Microsoft has provided a solution which doesn't look convincing at all : http://support.microsoft.com/kb/926812

We can use a different method:

  • Open the Master gallery in Explorer view

  • Create a Directory named "Delete"

  • Cut all the un-wanted Master Pages and paste it inside the "Delete" directoty

  • Delete the "Delete" Directory


And you got rid of all the unwanted pages .