Thursday, July 22, 2010

OData, REST and this cool program call LINQPad

I was watching this video http://azgroups.nextslide.com/odata-begins with Scott Hanselman about OData. OData is cool in itself, but what exited me most was then Scott showed this program call LINQPad http://www.LINQpad.net. LINQPad is not only a tool to build your LINQ statement in but also to execute against a data source. In Scott example, he use the http://odata.netflix.com/ as the data source and create a LINQ query that LINQPad then translator in to a REST statement, sooo cool :D

A simple walk through to query netflix.com

1) Open LINQPad and click on “Add connection”
clip_image002

2) Choose WCF Data Services as the data content and click next.
clip_image003

3) Insert the url to Netflix.com (http://odata.netflix.com/Catalog/) and click OK
clip_image004

4) Set the database to Netflix.com
clip_image006

5) Type a LINQ query like this
clip_image008

6) Select the SQL view instead of Results and wola your REST statement.
clip_image010

Saturday, July 17, 2010

PowerShell, events and file watcher

A simple script that create a file watcher on a specific folder and collect the events in a global variable.

 

function watch-folder {
    param([string]$path)
    $fileSystemWatcher = new-object System.IO.FileSystemWatcher
    $fileSystemWatcher.Path = $path
    $global:events = new-object system.data.datatable
    [void] $events.Columns.Add("Time", [datetime])
    [void] $events.Columns.Add("Full path", [string])
    [void] $events.Columns.Add("Change type", [string])
    $event = {
        [void] $events.Rows.Add([datetime]::Now, $eventArgs.FullPath, $eventArgs.ChangeType)
    }
    [void](Register-ObjectEvent -InputObject $fileSystemWatcher -EventName Created -Action $event)
    [void](Register-ObjectEvent -InputObject $fileSystemWatcher -EventName Changed -Action $event)
    [void](Register-ObjectEvent -InputObject $fileSystemWatcher -EventName Deleted -Action $event)
}
cls
watch-folder "c:\Temp"
"foobar" > c:\temp\test.txt
del c:\temp\test.txt
$global:events
get-eventsubscriber -force | unregister-event -force

Monday, July 12, 2010

patterns & practices SharePoint Guidance - SharePoint 2010 Release now Live on MSDN!!

Copy/paste from MSDN:

The following releases are designed to help solution developers and architects make the right decisions and follow proven practices when building applications for SharePoint

MSDN link : http://msdn.microsoft.com/en-us/library/ff770300.aspx

Codeplex link: http://spg.codeplex.com/

Friday, July 9, 2010

Wednesday, July 7, 2010

Show list items through ECMAScript and jQuery

1) Create an announcement list named "Announcements"


clip_image002


2) Create some items in the list and set some of the items Expires date to today and some to a nother date.


clip_image004


2) Through SharePoint deisnger create a new page layout.


3) Add this code to the page



<%@ Page language="C#" Inherits="Microsoft.SharePoint.Publishing.PublishingLayoutPage,Microsoft.SharePoint.Publishing,Version=14.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" meta:progid="SharePoint.WebPartPage.Document" meta:webpartpageexpansion="full" %>
<%@ Register Tagprefix="SharePointWebControls" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="PublishingWebControls" Namespace="Microsoft.SharePoint.Publishing.WebControls" Assembly="Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="PublishingNavigation" Namespace="Microsoft.SharePoint.Publishing.Navigation" Assembly="Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>


<asp:Content ContentPlaceholderID="PlaceHolderPageTitle" runat="server">
<SharePointWebControls:FieldValue id="PageTitle" FieldName="Title" runat="server"/>
</asp:Content>
<asp:Content ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
<SharePointWebControls:ScriptLink Name="SP.debug.js" runat="server" OnDemand="true" Localizable="false"/>
<script src="http://ajax.Microsoft.com/ajax/jQuery/jquery-1.4.2.min.js%22 type="text/javascript"></script>
<script type="text/javascript">


function GetAnnoucmentItems()
{
var clientContext = new SP.ClientContext.get_current();
var web = clientContext.get_web();
var annoucmentlist = web.get_lists().getByTitle("Announcements");
var camlQuery = new SP.CamlQuery();
var camlString = '<View><Query><Where><Eq><FieldRef Name="Expires" /><Value Type="DateTime"><Today /></Value></Eq></Where></Query><RowLimit>100</RowLimit></View>'
camlQuery.set_viewXml(camlString);


this.listItems = annoucmentlist.getItems(camlQuery);


clientContext.load(this.listItems,'Include(Title, Body)');
clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed));
}
function onQuerySucceeded()
{
var listItemEnumerator = this.listItems.getEnumerator();
this.listCount = this.listItems.get_count()-1;
if(this.listItems.get_count() != 0)
{
ShowAnnouncement(0);
}


}
function onQueryFailed(sender, args)
{
alert('faild');
}
function ShowAnnouncement(index)
{
if(index != 0)
{
$("#text").hide();
}
$("#text").fadeIn("slow");
var htmlString = this.listItems.get_item(index).get_item("Title") + "<br />" + this.listItems.get_item(index).get_item("Body")
$("#text").html(htmlString);
if(index < this.listCount)
{
++index
setTimeout("ShowAnnouncement(" + index + ")",3000);
}
else
{
setTimeout("ShowAnnouncement(0)",3000);
}
}
</script>
</asp:Content>
<asp:Content ContentPlaceholderID="PlaceHolderMain" runat="server">
<script type="text/javascript">
ExecuteOrDelayUntilScriptLoaded(GetAnnoucmentItems, "sp.js");
</script>
<div id="text" />
</asp:Content>


4) Create a new page based on the page layout.


clip_image006


5) And wola.


clip_image008

Monday, July 5, 2010

SharePoint Solution Package, JobExitsts and PowerShell

One of the issues we have when we are using the SharePoint Solution Package (wsp) framework for SharePoint is, we don’t know when all the files is copied out to the SharePoint system root (14-hive), because the deployment process is asynchronous. So if we call active-feature right after we deployed and the deployment process is not done yet, we can experience some error because the files is not deployed.

The solution for this is to make the deployment process synchronous or at least wait for it for finish. The easiest way is just to wait for the deployment process to finish and the obvious way to do this is through PowerShell.

On the Microsoft.SharePoint.Administration.SPSolution is there a property call JobExitsts (http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.administration.spsolution.jobexists.aspx). This property tells if there is a deployment process in progress (deploying or retracing) for the solution. So all the PowerShell has to do is to get the solution from the solution store and wait for the JobExitsts property to return false. But we have to build in a fail save so we don’t end up in an endless loop.

I created a function (cmdlet) to do this:

function IsDeploying {
    [CmdletBinding()]
    param
    (
        [Parameter(
                Mandatory=$true, 
                ValueFromPipeline=$true,
                ValueFromPipelineByPropertyName=$true)]
        [ValidateNotNullOrEmpty()]
        [Microsoft.SharePoint.Administration.SPSolution] $Identity
    )
    begin
    {
        $packagename = $Identity.Name
        Write-Progress -Activity "Deployment job:" -Status "Waiting for deployment job for $packagename" -Id 0
    }
    process
    {
        $index = 0
        [DateTime] $startingTime = [DateTime]::Now
        while($Identity.JobExists)
        {
            $index++
            Write-Progress -Activity "Deployment job:" -Status "Job still running" -Id $index
            Start-Sleep -s 5
            if($startingTime -gt [DateTime]::Now.AddMinutes(2))
            {
                #Throw error
                break
            }
        }
        return $Identity
    }
    end
    {
        $index++
        Write-Progress -Activity "Deployment job:" -Status "Deployment job done for $packagename" -Id $index -Completed
    }
}

And the function can be used like this:

$solution = ls -Filter *.wsp -Recurse | % { Add-SPSolution -LiteralPath $_.FullName }´
Install-SPSolution -Identity $solution –GACDeployment
IsDeploying -Identity $solution

Sunday, July 4, 2010

List all runnig deployment jobs

The first way to list all running deployment jobs is by goning to the Central Administration > Job Definitions, Under CA > Monitoring > Review job definitions and see after jobs that start with “Microsoft SharePoint Foundation Solution Deployment”

Untitled

The second way is to use PowerShell.

Get-SPTimerJob -Type Microsoft.SharePoint.Administration.SPSolutionDeploymentJobDefinition

The output of the Get-SPTimerJob cmdlet is not very useful.

Name                 Schedule             Last Run
----                 --------             --------
solution-deployme...                      04-07-2010 11:56:31

But pipe the Get-SPTimerJob to Format-List (fl) and select the “SolutionName” property.

Get-SPTimerJob -Type Microsoft.SharePoint.Administration.SPSolutionDeploymentJobDefinition | ft "SolutionName"

The output is more useful.

SolutionName
------------
sharepointprojectwsp.wsp

Saturday, July 3, 2010

Playing with PowerShell and timerjobs

The goal for this blog post is to display how easy it is to manage and update SharePoint timerjob through PowerShell.

For this demo I created a Timerjobtest class that inherits from SPJobDefinition with an empty and an overloaded constructor that takes a SPWebApplication as argument and custom property call Message.

clip_image002

The first thing I do is restart the timer service (SPTimerV4) to ensure I’m working with the same version of my DLL as the timer service has loaded.

Then I delete all old versions of my Timerjobtest timerjob, load my custom DLL so I can work with it in my PowerShell script, after that I create a SPSchedule object used later.

Documentation on a valid schedule object:
The type must be a valid SharePoint Timer service (SPTimer) schedule in the form of any one of the following schedules:
- Every 5 minutes between 0 and 59
- Hourly between 0 and 59
- Daily at 15:00:00
- Weekly between Fri 22:00:00 and Sun 06:00:00
- Monthly at 15 15:00:00
- Yearly at Jan 1 15:00:00

Now for some of the core functionality of this script where I’m create an object of my custom SPJobDefinition. The syntax is like this [Fully-Qualified Class Name] $myvarb = New-Object "Fully-Qualified Class Name" -ArgumentList argArry. A nice blog post on creating PowerShell object from .net class is this one http://www.lcbridge.nl/vision/2010/powershell.htm. Then I update the newly created timerjob object, with the schedule object and set a custom property and then I call the update method on the timer job object. At last a get the timer job back from SharePoint and select the custom property Message and then get the timer job again, to run the timerjob ones.

The scripts look like this:

#clear the console, for debug purposes
cls

#Restart the timer service
Restart-Service SPTimerV4

#Delete the old timerjob
Get-SPTimerJob | where { $_.TypeName -eq "Timerjobtest.Timerjobtest" } | % { $_.Delete() }

#Load my custom assembly, so it can be used in my script
[System.Reflection.Assembly]::Load("Timerjobtest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5bfcf02a97af8d35")

#Creating a SPSchedule object from a string
[Microsoft.SharePoint.SPSchedule] $schedule = [Microsoft.SharePoint.SPSchedule]::FromString("Every 10 minutes between 0 and 59")

#Crating an object of my custom SPJobDefinition
[Timerjobtest.Timerjobtest] $timerjobtest = New-Object "Timerjobtest.Timerjobtest" -ArgumentList (Get-SPWebApplication "http://win-ugka6ujlm21/")

#Sets the base properties of SPJobDefinition
$timerjobtest.Schedule = $schedule;
$timerjobtest.Name = "Timerjob test"
$timerjobtest.Title = "Timerjob test"

#Sets my custom property
$timerjobtest.Message = "powershell rocks!!!"

#Updates the timerjob
$timerjobtest.Update($true)

#Gets the Message property value from my timerjob
Get-SPTimerJob -Identity "Timerjob test" | Select "Message"

#Find my timerjob and run it ones
Get-SPTimerJob -Identity "Timerjob test" | Start-SPTimerJob

Happy PowerShelling