Monday, 1 September 2014

Generating CAML at Run Time.

For that we need List<> of String type i.e List<string> strArr = new List<string>(); and one string
string entireCAMLQuery = string.Empty; .

In strArr we can Add the CAML query like

strArr.Add("<BeginsWith><FieldRef Name='CandidateName' /><Value Type='Text'>" + filter.Value + "</Value></BeginsWith>");

Then check strArr is not equal to 0.

if (strArr.Count != 0)
 {
entireCAMLQuery = BuildingCAMLUsingStringArr(strArr);
query.Query = entireCAMLQuery.ToString();
query.ViewAttributes = "Scope=\"Recursive\"";  // for fetch data from folder of  SP list.
GetItemThroughtLoop(webSite, strList, query);

}

private string BuildingCAMLUsingStringArr(List<string> strArr)
        {
            string caml = string.Empty;
            try
            {
                if (strArr.Count == 1)
                {
                    caml = strArr[0] ;
                }
                else if (strArr.Count > 1)
                {
                    int count = strArr.Count - 1;
                    caml = CAMLRecursiveCall(strArr, count) ;
                }

            }
            catch { throw; }
            finally { }
            return @"<View><Query><Where>" + caml + "</Where></Query></View>";
        }
        private string CAMLRecursiveCall(List<string> strArr,int count)
        {
            StringBuilder strBuild= new StringBuilder();
            if(count>0)
            {
                strBuild.Append("<And>");
                strBuild.Append(CAMLRecursiveCall(strArr, count-1));
                strBuild.Append(strArr[count]);
                strBuild.Append("</And>");
            }
            else
                strBuild.Append(strArr[count]);
            return strBuild.ToString();
        }

public void GetItemThroughtLoop(SPWeb webSite, string strList, SPQuery serachQuery)
{
string site = webSite.Url;
SPList List = webSite.Lists(strList);
SPListItemCollection collListItems = List.GetItems(serachQuery);
 
//TO DO :  Do anything with list item collection
 

}

Tuesday, 8 July 2014

Get TaskId In Visual Studio Workflow Without Using OnTaskCreated Activity

Most of SharePoint IT devs who are working on implementing the Visual Studio Workflows are looking for the solution of the problem “How to get the current created task id in the workflow to send email once task assigned/created to a user/group.” 

Scenario:
We need to send an email to the assigned person/group with the custom mail body with the task link.
Solutions Tried:
Many solutions proposed on the net/MSDN that we cannot get the TaskId of the item without using the OnTaskCreated activity as this is the activity will trigger once the task is created in the database. So, we have added the OnTaskCreated activity in the workflow. But, it never hit when we debug the workflow. This is because OnTaskCreated is handled by the timer job and there is a delay in loading the TaskId into the workflow. Most of the cases we observed its end up of delaying the workflow to 15-20 minutes. (This is also not sure, sometimes it may return TaskId or sometimes may not.) So, this is not the ideal solution we should use in the workflow.
Next, for immediate resolution we have tried of using the Item Created event receiver on the Task list. So, whenever a task is created the event triggers and we are sending email. But, this needs additional coding/package/maintenance.
Later, we have got a solution recommended from Microsoft employee and it solved the problem without writing extra line of code. This is the best and recommended solution.
Final Solution:
In Visual Studio Workflow, we have used the activities in the sequence:
Ø  First, disable or delete the OnTaskCreated activity from the workflow.
Ø  Right click on the CreateTask activity -> Properties window. You will see a property field “ListItemId”. Click on the field to open properties window. 



Ø  From the properties window, click on the second tab “Bind to a new member”.
Ø  Enter the name of the member/field and then select the option “Create a Field” and save your changes.

Task_Create_Field

Ø  Drag and Drop a Code Activity next to the CreateTask activity. And in the activity access the created member from above step which has the newly created taskid. And you can access the TaskID in your logic.

Code_Activity1

Finally, the complete solution including the steps shown below: 

Workflow_Task


Note: From above diagram, the step “ReviewerTaskCreated (OnTaskCreated)” activity is disabled in the workflow.



Friday, 6 June 2014

Incompatible Webpart Markup - .dwp vs .webpart

SharePoint 2010 allows us to extend out of the box web parts. When I try to inherit search box webpart (one of the out of the box webparts), and try to add new web part to a SharePoint page, I got this error:

“Incompatible Web Part markup detected. Use *.dwp Web Part XML instead of *.webpart Web Part XML.”

Problem:

Both .dwp and .webpart file types are used to describe where the code is for a web part. They are XML web part descriptors deployed with the web part. The difference is .dwp was the file extension used in version 2 of SharePoint and .webpart is a new extension used in version 3.  Inside the files, the schemas are different. Microsoft.SharePoint.Portal.WebControls.SearchBoxEx is one of the older ones and therefore requires a .dwp descriptor.

Solution:

We have to create a .dwp descriptor for the webpart.

1. Add a new XML file to the web part and give it the same name but with a .dwp extension

2. Add this content to the .dwp file

<?xml version="1.0" encoding="utf-8"?>
<WebPart xmlns="http://schemas.microsoft.com/WebPart/v2">
      <Assembly>$SharePoint.Project.AssemblyFullName$,Version=1.0.0.0,Culture=Neutral,PublicToken=d15bb591c34f9efb</Assembly>
      <TypeName>"EmesnCombi_SQL.EmesnCombi_SQL, $SharePoint.Project.AssemblyFullName$"</TypeName>
      <Title>EmesnCombi_SQL</Title>
      <Description>EmesnCombi_SQLt</Description>
</WebPart>

It is important to note that there are two main differences in the schema compared to the .webpart file;
Ø  The xmlns is http://schemas.microsoft.com/WebPart/v2 instead of http://schemas.microsoft.com/WebPart/v3
Ø  We need the assembly's public token.

3. Set the Assembly version to your assembly's version. This is usually  1.0.0.0, but you can find it in AssemblyInfo.cs in your project.

4. Replace the PublicKeyToken.

5. Replace the TypeName with the type name in the .webpart file.


6. Select the .dwp file in Solution Explorer and change its Deployment Type property from NoDeployment to ElementFile. This will ensure .dwp file is deployed with the web part.


7. Verify that Step 6 adds an entry to the .spdata file.

8. Delete the .webpart file. So the final view will be like this.


9.Edit Elements.xml file and replace both instances of .webpart with .dwp.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/" >
      <Module Name="EmesnCombi_SQL" List="113" Url="_catalogs/wp">
            <File Path="EmesnCombi_SQL\EmesnCombi_SQL.dwp" Url="EmesnCombi_SQL_EmesnCombi_SQL.dwp" Type="GhostableInLibrary">
                  <Property Name="Group" Value="EmrsnCombi_SQL" />
            </File>
      </Module>
</Elements>

10. Build and deploy the project

This is how I extended Microsoft.SharePoint.Portal.WebControls.SearchBoxEx. For the purpose I had to reference two assemblies Microsoft.Office.Server.Search.dll, microsoft.sharepoint.portal.dll from ISAPI folder (Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI).


Tuesday, 20 May 2014

Client-Side Object Model in SharePoint 2013

The manage and javascript client object model are maintained in seprate libraries , which are located under a sharepoint system directory. The managed client object model is contained in the assemblies Microsoft.Sharepoint.ClientRuntime.dll, which we can found in the ISAPI folder.

The havascript client object model is contained in the library sp.js, which is located in the LAYOUTS folder.

Initializing the Client-side object model:  

Much like the Server -side object model, which is the other framework for development in SharePoint, CSOM also needs a starting point in the form of a central object which will instantiate and provide access to the client object model.  This central object is called the Client Context. The Client Context object orchestrates requests and initiates actions within a site collection. Once the Client Context Object is initialized, it provides information to the site collection or website through which we can access other SharePoint client object remotely as depicted in the below code.

//Managed  Client Object  Model
using (ClientContext ctx = new ClientContext(“http://MyServer/sites/MySiteCollection”))
{
Site siteCollection =ctx.site;
ctx.Load(siteCollection);
ctx.ExecuteQuery();
string url=siteCollection.Url;
}

//Javascript Client Object Model
var siteCollection;
var ctx= new SP.ClientContext.get_current();
siteCollection=ctx.get_site();
ctx.load(siteCollection);
ctx.executeQueryAsync(success,failuer);

function success()
{
var url= siteCollection.get_url();
}

function failure()
{
alert(“Failuer!”);
}

The Client Context class in managed object model inherits from the ClientContextRuntime class.
The SP.ClientContext object in JavaScript client object model inherits from the  SP.ClientContextRuntime object and provides equivalent functionality to the ClientContext  class found in the managed client object model.

Working with the Managed Client Object Model:

To start the development in the managed client object model, you will need to add references of Microsoft.SharePoint.Client.dll ,Microsoft.SharePoint.ClientRuntime.dll into the assemblies and add the using statement for Microsoft.SharePoint.Client  namespace and start writing code.

Basic operations using Managed Client Object Model:

With managed client object,  you can perform all SharePoint website related tasks, ie- Read and write all website related properties, create new SharePoint web site, SharePoint List operations(create new SharePoint lists, Retrieve all SharePoint lists in a SharePoint website, insert, update and delete in  SharePoint lists),SharePoint document library operations (same as SharePoint List operations).

Create a new SharePoint website:

Using System.Text;
Using System.Collection.Generic;
// Starting with ClientContext, the constructor requires a URL to the
// server running SharePoint.
ClientContext context = new ClientContext(“http://SiteUrl”);
WebCreationInformation creation = new WebCreationInformation();
creation.Url = “web1″;
creation.Title = “Hello web1″;
Web newWeb = context.Web.Webs.Add(creation);
// Retrieve the new web information.
context.Load(newWeb, w => w.Title);
context.ExecuteQuery();
label1.Text = newWeb.Title
New web site is created in sharepoint as a sub site.
WebCreationInformation class is used for to create a new website.

Create new SharePoint list:

// Starting with ClientContext, the constructor requires a URL to the
// server running SharePoint.
ClientContext context = new ClientContext(“http://SiteUrl”);
// The SharePoint web at the URL.
Web web = context.Web;
ListCreationInformation creationInfo = new ListCreationInformation();
creationInfo.Title = “My List”;
creationInfo.TemplateType = (int)ListTemplateType.Announcements;
List list = web.Lists.Add(creationInfo);
list.Description = “New Description”;
list.Update();
context.ExecuteQuery();

ListCreationInformation class is used for to create new SharePoint List.
After new list is creating it update SharePoint list collection by using update method.


Working with the JavaScript Client Object Model:

The primary purpose of JavaScript client side object model is to talk with SharePoint without requiring a full-page postback. To access the JS CSOM the calling page must reference the following two files:
SP.Runtime.js
SP.js
Each of these are located in the _layouts/15/ directory under each SharePoint site; for example, http://myserver/sitename/_layouts/15/SP.js.

Whether you want to perform web site related tasks (read or write web site properties etc.), list related tasks (retrieve list properties, create and update list etc.) below are some general steps to follow for every kind of operation.

Use the ClientContext object to connect and work with the SharePoint server.
Use the clientContext.get_web() method to access specific web site object.
Use ClientContext.Load() to load the objects you need to work with.
Use the ClientContext.ExecuteQuery() to execute the query and fetch the objects

Sample method to create lists using Java Script

function createList(siteUrl) {
    var clientContext = new SP.ClientContext(siteUrl);
    var oWebsite = clientContext.get_web();
    var listCreationInfo = new SP.ListCreationInformation();
    listCreationInfo.set_title('My Announcements List');
    listCreationInfo.set_templateType(SP.ListTemplateType.announcements);
    this.oList = oWebsite.get_lists().add(listCreationInfo);
    clientContext.load(oList);
    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onSuccess),
        Function.createDelegate(this, this.onFailuer)
    );
}
function onSuccess() {
    var result = oList.get_title() + ' created.';
    alert(result);
}
function onFailuer(sender, args) {
    alert('Request failed. ' + args.get_message() +
        '\n' + args.get_stackTrace());
}

SP.ListCreationInformation is used to create a new list in a SharePoint website.
Use get_lists().add(Parameter) to add newly created lists into web site list collection.

Refer Link

Friday, 2 May 2014

Things to remember while working with sharepoint timer job .

Important Note

Note that, whenever you change the logic or code inside Execute() method, you must restart the Timer service from Services.msc. If you just deploy without restarting service, it will not take your latest updates. So always have practice to restarting the "SharePoint Timer Service" from Services.msc.

If you still face any problem registering or deploying timer job, try uninstalling your assembly and restart the IIS and then deploy again.

To uninstall assembly, in "Run" type "assembly" and press enter. In list of assemblies, you will see the assembly of your project name. Select that and uninstall by right click.

To restart IIS, in "Run" type iisreset and press Enter.

Tuesday, 29 April 2014

How to send alert (Reminder Email) in SharePoint Workflow - Visual Studio.

Blog approach - In many projects  it's a requirement to send an email on daily basis or hourly.
Using Delay Activity  we can send an alert.

To achieve above requirement we need to use listen Activity , delay Activity and code activity.

Listen Activity : The listen activity will wait for any of the branch to wake up and whichever wakes up first - completes the activity. The Listen Activity activity cannot be used in state machine workflows.

Delay Activity : Here we have to set time span / Initialize time out duration .

Code Activity : Once in time of delay activity is up , code activity will be execute where we will write send mail code.


Put listen activity with two branches under while loop .

One branch will be use for execute the code on  "OnTaskChanges"  and another branch will be use for execute thye code on Dealy Activity ( which will use for send an email ) .

Here is a code activity (codeActivitySendReminder)  which will execute the code for send an alert if the time in dealy activity is up.

Here is a delay Activity handler code :

private void delayActivity_InitializeTimeoutDuration(object sender, EventArgs e)
{
   DelayActivity dlyAct = sender as DelayActivity;
   dlyAct.TimeoutDuration = new TimeSpan(<Number Of Days Here>, 0, 0, 0);
}

Now let's say we want to send a reminder every 2 days  if the task has not completed,  then the above line would look like

dlyAct.TimeoutDuration = new TimeSpan(2, 0, 0, 0);


Some explanation:

If you set <Number Of Days> as 1 (i.e. 1 Day),So It will consider as 24 Hr means time out duration will up after 24 Hr and then fire the code within Code Activity i.e. CodeActivitySendReminder.

Consider an example- If Time out duration of delay activity is initialized at 3:00 PM on dated 1/1/2014. So Time of delay activity will up at 3:00 PM of 2/1/2014 and hence code activity (CodeActivitySendReminder)  fires up.

If You want to send Reminder mail at particular time , suppose at 3:00 AM.

Calculate the value for 3:00 AM as per 24 Hr. Time and it will be 27.

private void delayActivity_InitializeTimeoutDuration(object sender, EventArgs e)        {
   int TaskGenerateTime = DateTime.Now.TimeOfDay.Hours;
   int AlertFiredTime = 27 - TaskGenerateTime;
   DelayActivity dAct = sender as DelayActivity;
   dAct.TimeoutDuration = new TimeSpan(AlertFiredTime, 0, 0);
}

private void CodeActivitySendReminder(object sender, EventArgs e)
{
    //TODO: code for send mail.

}

Going further more: 

The above code can be replaced with the days based on actual Due date of the task in CreateTask activity.
 Example:  
TimeSpan ts = TaskObject.DueDate -  DateTime.Today ; // (Calculate ts before the While loop above)
and hence use 

ts.Days above i.e.
dlyAct.TimeoutDuration = new TimeSpan(ts.Days, 0, 0, 0); 

Sunday, 27 April 2014

How to add user control to Sharepoint master page.

How to add user control to Sharepoint master page.

we can add user control using two ways
a] Register user control into master page
b] using module

Consider-
Project Name: MasterPageControl
master page:  v4.master
User control: RestrictPasteUrlb.ascx

Firstly add user control in your project.
   right click on project -> Add new item->select User Control
    (write your code in that)

using a first way i.e. Register user control into master page

1] Register user control in master page.

<%@ Register  TagPrefix="myControl"  TagName="CurrentPageControl"
Src="~/_controltemplates/MasterPageControl/ RestrictPasteUrlb.ascx"  %>

Src : is a path where user control is placed. i.e  in Template folder -> controltemplates  -> Folder of project name in our case (MasterPageControl)

2] Then you can add control to master page.

<mycontrol:CurrentPageControl Id="myControl" runat="server"/>

3] Delopy

using second way i.e Using Module.

1] Add module into project
right click on project -> Add new item->select Module.

2]Open Element.xml
(Here we will register our user control using module)

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="Module">
    <File Path="Module\Sample.txt" Url="Module/Sample.txt" />
  </Module>
      <Control ControlSrc="~/_controltemplates/ MasterPageControl /RestrictPasteUrl.ascx" Id="AdditionalPageHead" />
</Elements>

ControlSrc : It's a path where user control is placed. i.e  in Template folder -> controltemplates  -> Folder of  project name in our case (MasterPageControl)
Id : It's a control id of sharepoint delegate control where we are going to add our user control  on master page (v4.master).

3] Delopy

I would preferred second way (using module ).