 |
|
| Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XsnLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | FileType | xsn | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.2 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.3 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.4 | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsx | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsb | 255 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsx | 256 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsb | 256 |
|
|
| Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XsnLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | FileType | xsn | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.2 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.3 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.4 | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsx | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsb | 255 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsx | 256 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsb | 256 |
|
|
| Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XsnLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | FileType | xsn | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.2 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.3 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.4 | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsx | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsb | 255 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsx | 256 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsb | 256 |
|
|
|
| Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XsnLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | FileType | xsn | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.2 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.3 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.4 | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsx | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsb | 255 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsx | 256 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsb | 256 |
|
|
|
 |
|
|
|
|
|
|
| The Silverlightness of SharePoint |
3/11/2008In previous posts I explained how you can host a Silverlight application from within a SharePoint web part and how you have to configure SharePoint before you are able to do so: - hosting a Silverlight application from within a web part. If you want to host a Silverlight application from within a SharePoint application page, you have to perform a few additional steps. In your web.config you have to add an extra tag for the silverlight control in the <system.web><pages><controls> section. This section must at least contain the following: | <controls> <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> <add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> <add tagPrefix="asp" namespace="System.Web.UI.SilverlightControls" assembly="System.Web.Silverlight, Version=2.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> </controls> | The following code snippet is a very basic application page that hosts a Silverlight control. The page does not contain any code behind. You page has to reference the Microsoft.SharePoint.dll and the System.Web.Silverlight.dll. Import the according namespaces. Within the Main content control first place a script manager because this is required by the Silverlight control. Then add the Silverlight control using the <asp:Silverlight> tag. The Silverlight control renders the Hello Silverlight application from the Silverlight BluePrint for SharePoint. Pay attention to the Source property. If you deploy your Silverlight application in the same sub directory as your as your application page (12\TEMPLATE\LAYOUTS\…) you can set the Source property as in the sample code below. But if your Silverlight application is deployed in the ClientBin directory within your SharePoint web application or within a SharePoint document library, your Source property will look a bit different. | <%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Assembly Name="System.Web.Silverlight, Version=2.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %> <%@ Page Language="C#" MasterPageFile="~/_layouts/application.master" Inherits="Microsoft.SharePoint.WebControls.LayoutsPageBase" %> <%@ Import Namespace="Microsoft.SharePoint" %> <%@ Import Namespace="System.Web.UI.SilverlightControls" %> <asp:Content ID="Main" contentplaceholderid="PlaceHolderMain" runat="server"> <asp:ScriptManager runat="server" ID="ScriptManager1" /> <asp:Silverlight ID="HelloSL" runat="server" MinimumVersion="2.0.31005.0" Source="SL.XAML.HelloSilverlight20.xap" Width="400" Height="300" /> </asp:Content> <asp:Content ID="PageTitle" contentplaceholderid="PlaceHolderPageTitle" runat="server"> Hello Silverlight </asp:Content> <asp:Content ID="PageTitleInTitleArea" runat="server" contentplaceholderid="PlaceHolderPageTitleInTitleArea" > The Hello Silverlight Application Page </asp:Content> | This is the sample application page: You can download the source code here. 23/10/2008Recently I wrote an article for an online SharePoint magazine. It’s about hosting a Silverlight 2 application in a a SharePoint web part. You can also read the article on the U2U web site. I upgraded the sample to Silverlight 2 final release. You can download the upgraded code and the list templates here. It is a tutorial in which I explain how you can host a Silverlight 2 application from within a SharePoint Web Part. The Web Part will pass the URL of the SharePoint site together with the name of the list for which the Silverlight application will show the data. The retrieval of the data will be done by the Silverlight application using the HttpWebRequest technique for calling the SharePoint web services. As the SharePoint web services return a chunk of XML the XML will be handled by using LINQ for XML. The data will be bound to the Silverlight controls. There are a few changes to take into account when working with Silverlight 2 final release. The only thing to change in the SharePoint web part is in the CreateChildControl method: you have to set the MinimumVersion property of the Silverlight control to 2.0.30923.0. | protected override void CreateChildControls() { base.CreateChildControls(); // instantiation of the silverlight control silverlightControl = new System.Web.UI.SilverlightControls.Silverlight(); silverlightControl.ID = "SLAdventureWorks"; silverlightControl.MinimumVersion = "2.0.30923.0"; silverlightControl.Width = new Unit(750); silverlightControl.Height = new Unit(600); silverlightControl.Source = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "SL.AdventureWorksProducts.Resources.SL.XAML.AdventureWorksProducts.xap"); // parameters passed are the URL of the SharePoint site and //the name of the list containing the AdventureWorks Products silverlightControl.InitParameters = "siteurl=" + SPContext.Current.Web.Url + ",listname=AdventureWorks Products"; this.Controls.Add(silverlightControl); } | The major change lies in the silverlight application, specifically in the functioning of the HttpWebRequest object. 1. The HttpWebRequest object works completely asynchronous and on different threads as the main thread. This means that the Silverlight application continues processing while the request to the Web Service is executed. Before you start a request to a Web Service, in this case a SharePoint web service, you have to grab the context of the UI thread. | syncContext = SynchronizationContext.Current; | The syncContext variable is a class-level variable: | SynchronizationContext syncContext; | 2. Create the HttpWebRequest object passing it the URL of the SharePoint web service and specify a callback method on which the HttpWebRequest can come back after processing the request. The request will come back on a background thread. | HttpWebRequest request = (HttpWebRequest)WebRequest.Create( new Uri(siteUrl + "/_vti_bin/Lists.asmx", UriKind.Absolute)); request.Method = "POST"; request.BeginGetRequestStream(new AsyncCallback(RequestCallback), request); | 3. The RequestCallback method contains the code for the soap envelope. The body is retrieved from the request stream by calling the EndGetRequestStream method of the HttpWebRequest and completed with the soap envelope. Then a callback method is defined for the response to come back on. Also the response will come back on a different background thread. The request stream must be closed before the BeginGetResponse method of the HttpWebRequest object is called. | private void RequestCallback(IAsyncResult asyncResult) { try { string envelope = @"<?xml version=""1.0"" encoding=""utf-8""?> <soap12:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap12=""http://www.w3.org/2003/05/soap-envelope""> <soap12:Body> <GetListItems xmlns=""http://schemas.microsoft.com/sharepoint/soap/""> <listName>{0}</listName> <query><Query xmlns="""">{1}<OrderBy><FieldRef Name=""Title"" /></OrderBy></Query></query> <viewFields><ViewFields xmlns=""""> <FieldRef Name=""ID"" /> <FieldRef Name=""Title"" /> <FieldRef Name=""ProductName"" /> <FieldRef Name=""ListPrice"" /> <FieldRef Name=""Thumbnail"" /> <FieldRef Name=""Color"" /> <FieldRef Name=""Weight"" /> <FieldRef Name=""Size"" /> <FieldRef Name=""Description"" /> </ViewFields> </viewFields> <queryOptions><QueryOptions xmlns=""""><IncludeMandatoryColumns>False</IncludeMandatoryColumns></QueryOptions></queryOptions> </GetListItems> </soap12:Body> </soap12:Envelope>"; string query = string.Empty; if (!string.IsNullOrEmpty(searchstring) && searchstring != "Topic...") { query = "<Where><Contains><FieldRef Name=\"Title\" />" + ";<Value Type=\"Text\">{0}</Value></Contains></Where>"; query = string.Format(query, searchstring); } envelope = string.Format(envelope, listName, query); HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState; request.ContentType = "application/soap+xml; charset=utf-8"; request.Headers["ClientType"] = "Silverlight"; Stream requestStream = request.EndGetRequestStream(asyncResult); StreamWriter body = new StreamWriter(requestStream); body.Write(envelope); body.Close(); request.BeginGetResponse(new AsyncCallback(ResponseCallback), request); } catch (WebException ex) { responsestring = ex.Message; } } | 3. When the response comes back on a background thread, the response is retrieved. If an error occurred along the way, it is captured in a class-level string variable. The UI thread is invoked by calling the Post method on the context variable, passing the address of the ExtractResponse method to it. | private void ResponseCallback(IAsyncResult asyncResult) { HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState; WebResponse response = null; try { response = request.EndGetResponse(asyncResult); } catch (WebException we) { responsestring = we.Status.ToString(); } catch (System.Security.SecurityException se) { responsestring = se.Message; if (responsestring == "") responsestring = se.InnerException.Message; } syncContext.Post(ExtractResponse, response); } | 4. The ExtractResponse method executes the GetResponseStream method on the response and retrieves the resulting xml from the stream. | private void ExtractResponse(object state) { HttpWebResponse response = state as HttpWebResponse; if (response != null && response.StatusCode == HttpStatusCode.OK) { using (StreamReader reader = new StreamReader(response.GetResponseStream())) { responsestring = reader.ReadToEnd(); ProcessResponse(); } } else ProcessMessage(); } | 5. The rest of the code remains the same. The ProcessResponse method parses the resulting XML with LINQ to XML into objects and the object collection is bound to the ListBox. The update of the list price in the product detail box works in a similar way, except that it executes the UpdateListItems method of the Lists.asmx web service. If you are configuring the web.config of your SharePoint web applications the “lazy” way please verify the HttpHandlers section. It should look like the following: | <httpHandlers> <remove verb="GET,HEAD,POST" path="*" /> <add verb="GET,HEAD,POST" path="*" type="Microsoft.SharePoint.ApplicationRuntime.SPHttpHandler, Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" /> <add verb="OPTIONS,PROPFIND,PUT,LOCK,UNLOCK,MOVE,COPY,GETLIB,PROPPATCH,MKCOL,DELETE,(GETSOURCE),(HEADSOURCE),(POSTSOURCE)" path="*" type="Microsoft.SharePoint.ApplicationRuntime.SPHttpHandler, Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" /> <add verb="*" path="Reserved.ReportViewerWebControl.axd" type="Microsoft.Reporting.WebForms.HttpHandler, Microsoft.ReportViewer.WebForms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false" /> <remove verb="*" path="*.asmx" /> <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false" /> </httpHandlers> | Otherwise SharePoint web services and the Silverlight HttpWebRequest object will NOT work. 18/10/2008
Silverlight 2 RTM is out and ready to download. If you want to integrate Silverlight 2 with SharePoint you have to install the following:
- SP1 for WSS if you have a WSS installation
- SP1 for MOSS if you have a MOSS installation
- SP1 for Visual Studio 2008
- If you are a SharePoint developer you can also install the Visual Studio 2008 extensions for WSS 3.0 (VseWSS 1.2)
- The Silverlight 2 run-time
- The Silverlight 2 SDK
- The Visual Studio 2008 Tools for Silverlight 2
My colleague Jan Tielens wrote a great post on how to upgrade the web.config of your SharePoint site(s) the “lazy way”. It is a great way to quickly upgrade the web.config files of your SharePoint sites without any chances on typos. I tested it out: it still works with Silverlight 2 RTM.
The only thing that need to be added manually to each web.config is the reference to the Silverlight assembly in the <system.web><compilation><assemblies> section:
<add assembly="System.Web.Silverlight, Version=2.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
Two other things need to be done to get Silverlight working with SharePoint:
- drop the System.Web.Silveright.dll into the Global Assembly Cache. After the installation of the Silverlight SDK, this assembly can be found in the C:\Program Files\Microsoft SDKs\Silverlight\v2.0\Libraries\Server directory.
- If you already worked with the betas of Silverlight 2, you had to define a MIME type on each IIS SharePoint Web Application (or on the root if IIS). You have to change this MIME type to application/x-silverlight-app.
If you are using the System.Web.UI.SilverlightControls.Silverlight control in your SharePoint web parts and application pages, you have to set the MinimumVersion property to “2.0.30923.0”
I will soon post my updated data binding sample. 11/10/2008
Recently I wrote an article for an online SharePoint magazine. It’s about hosting a Silverlight 2 beta 2 application in a a SharePoint web part. You can also read the article on the U2U web site.
It is a tutorial in which I explain how you can host a Silverlight 2 beta 2 application from within a SharePoint Web Part. The Web Part will pass the URL of the SharePoint site together with the name of the list for which the Silverlight application will show the data. The retrieval of the data will be done by the Silverlight application using the HttpWebRequest technique for calling the SharePoint web services. As the SharePoint web services return a chunk of XML the XML will be handled by using LINQ for XML. The data will be bound to the Silverlight controls.
By clicking one of the products you can view its details and update the list price. The modified price is stored in the SharePoint list using the HttpWebRequest technique that calls the UpdateListItems method of the Lists.asmx.
You can download the source code and the sample list templates here.
As we will soon start upgrading the Silverlight Blueprint for SharePoint to Silverlight RTM, this sample will also be upgraded in the coming weeks. 8/10/2008
Developing a list definition for a custom list using the Visual Studio 2008 extensions for WSS is not that hard because there is an existing project template for it. But having the custom fields displayed in the several forms (edit form, new form, display form, etc) can be a challenge. This post offers you a walkthrough on how you can proceed.
Lets say you want to develop a list definition for a custom list having fields like CustomerCode, Name, City, Country and StartDate. The custom list must also contain a customer ID but as the list item will inherit from the standard list item, the ID column will automatically be created. The Name column will be the standard Title column. When a new customer is entered, you also want to check if the customer code is not already used for another customer, so you will need to add an event receiver to the custom list.
Open Visual Studio 2008 and choose to create an empty SharePoint project. Add a new list item of type SharePoint List Definition. In the dialog that appears, select Custom List and check both the check boxes.
This is the structure that is created by the Visual Studio extensions for WSS. Notice that the necessary forms like the AllItems.aspx, DispForm.aspx, etc are all there. They will need no modification. The schema.xml file contains the definition of the list template and it is in here that you will have to do the work. The instance.xml file will create a list instance based on this custom list definition upon activation of the feature. The ItemEventReceiver.cs file will contain the necessary code for checking the existence of the customer code. The ItemEventReceiver.xml file on its turn will install the event receiver upon activation of the feature.
As we want to develop an item event receiver, we can remove the ListEventReceiver.cs and the ListEventReceiver.xml file from the project.
First we are going to define the schema of the Customer list. Open the schema.xml file and locate the <Fields> node.
Enter a field element for each column in the custom list. If you copy/paste, don't forget to change the GUID of the field ID because the ID must be unique.
<Field ID="{7809EF2B-C225-4459-BC81-50F9CBF1A244}" DisplayName="Code" Type="Text" Required="TRUE" MaxLength="15" StaticName="Code" Name="Code" RowOrdinal="0" SourceID="http://schemas.microsoft.com/sharepoint/v3" />
This Field element should be added for each column needed in the custom list. Also pay attention to attributes like
- Name: this is the internal name of the field. This field doesn't allow spaces. In the case of Company Name you can use CompanyName or Company_x0020_Name.
- DisplayName: this is the user friendly name of the field and allows spaces.
- StaticName: give it the same value as the Name attribute.
- Type: this indicates the data type of the field. Possible values are the SharePoint data types like Text, Note, DateTime, Currency, Number,...
- Required: indicates wether a value is required or not.
At the top of the schema definition you find a ContentTypes element containing one or more ContentTypeRef elements. Remove these elements and add a new ContentType element. This is the definition of the Customer content type.
The ID attribute shows the inheritance: this content type inherits from the Item content type which has ID 0x01. The ID should then be followed by 00 and a new GUID.
It is necessary to define a content type to make the fields appear in the New, Edit and Display form.
|
<ContentTypes> <ContentType ID="0x0100247971ABF81E4ac9B96C7C6287D18772" Name="Customer Item" Group="U2U Content Types" Description="Customer item content type." Version="0">
<FieldRefs>
<!-- Here comes the reference to the fields --> </FieldRefs>
</ContentType>
</ContentTypes> |
The FieldRefs element of the content type contains the field references to the fields you defined in the Fields element. The first field is the reference to the Title field which is part of the Item content type.
|
<FieldRefs> <FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" Required="TRUE" DisplayName="Company Name" />
<FieldRef ID="{7809EF2B-C225-4459-BC81-50F9CBF1A244}" Name="Code" Required="TRUE" ShowInNewForm="TRUE" ShowInEditForm="TRUE"/>
<FieldRef ID="{F5BC3F73-88E0-436e-8C2C-C9819FFE2FE3}" Name="City" Required="FALSE" ShowInNewForm="TRUE" ShowInEditForm="TRUE"/>
<FieldRef ID="{D5877137-AB9C-4474-93BD-F99B734436D8}" Name="Country" Required="FALSE" ShowInNewForm="TRUE" ShowInEditForm="TRUE"/>
<FieldRef ID="{242BF2C4-6459-45f2-B61C-EF7280A701C6}" Name="StartDate" Required="FALSE" ShowInNewForm="TRUE" ShowInEditForm="TRUE"/> </FieldRefs> |
The content type also contains a XmlDocuments element which is a collection of XmlDocument elements. An XmlDocument element can contain custom information. In this case it defines the form templates to use when displaying the content type.
Then you have a number of View definitions. To have your fields displayed in the different views, for example the All Items view when viewing the list content, you have to add your custom fields to the ViewFields element of each view.
|
<ViewFields> <FieldRef Name="LinkTitleNoMenu"> </FieldRef> <FieldRef Name="Code" /> <FieldRef Name="City" /> <FieldRef Name="Country" /> <FieldRef Name="StartDate" /> </ViewFields> |
Now that the list definition is set and done, we can start with the code for the event receiver. When a new customer is entered, you want to check whether the customer code is already used for another customer or not. Open the ItemEventReceiver.cs file and uncomment the ItemAdding event handler:
|
public override void ItemAdding(SPItemEventProperties properties) { // Check here if the code already exists DisableEventFiring();
string code = null; if (properties.AfterProperties["Code"] != null) { code = properties.AfterProperties["Code"].ToString(); }
SPList list = properties.OpenWeb().Lists[properties.ListId];
if (!ValidateData(list, code)) { properties.Cancel = true; properties.ErrorMessage = "This customer code is already in use."; }
EnableEventFiring(); } |
The ValidateData method is a private method that executes a CAML Query to check whether the customer code already exists or not.
|
private bool ValidateData(SPList list, string email) { if (email != null) { SPQuery qry = new SPQuery(); qry.Query = "<Where><Eq><FieldRef Name='Code' /><Value Type='Text'>" + email + "</Value></Eq></Where>"; SPListItemCollection results = list.GetItems(qry); if (results.Count > 0) return false; } return true; } |
Time to deploy the list definition. The ListDefinition.xml file contains the definition of the list template. Open the file to modify some metadata. You can change the display name of the list template and set the type to a custom number.
|
<ListTemplate Name="CustomerListTemplate" DisplayName="Customer List Template" Description="" BaseType="0" Type="700" OnQuickLaunch="TRUE" SecurityBits="11" Sequence="410" Image="/_layouts/images/itgen.gif" /> |
The instance.xml file defines the list instance that will be created based on your custom list template. Also here you can change f.e. the Title attribute.
|
<ListInstance FeatureId="bc53ee2c-46b3-41ea-8deb-e75013c92eee" Title="Customer List Template instance" Url="Lists/CustomerListTemplate"> </ListInstance> |
Open the project Properties and set the Start browser with URL on the Debug tab to your SharePoint site where you want to deploy your custom list template. Press F5 to start the deploy.
Open an internet browser and navigate to your SharePoint site. The list instance is already created for you. Add a new customer and fill out some data.
Add another customer with the same code and you will get an error message indicating that this customer code is already used.
You can download the code here. 13/09/2008
While my world stopped turning 10 days ago, technology has not. The coming weeks I will post things I stopped working on because my work for Patrick took too much of my (free) time. By keeping up the work I hope to honor him. Thanks for the many words of support and the condolences.
When integrating Silverlight applications with SharePoint custom development, you have different possibilities where to deploy your silverlight application:
- To the ClientBin folder of your IIS web application: If you deploy in this location, it means that the Silverlight application can be picked up by any SharePoint code that runs in the site collections and sites hosted on the IIS Web Application.
- To the 12\Template\Layouts or in the 12\Template\ControlTemplates folder: deploying here means that you can include all of the deployment steps in your SharePoint Solution.
- To a document library: you can create one central document library within your site collection (or if you want a more narrow scope, for your site) where to drop the XAP files.
I refer to the post of Patrick Tisseghem for more details, advantages and disadvantages of each possibility.
In this post I will show you how you can deploy your Silverlight application as an embedded resource of your web part. In that case the Silverlight application will only be available to that web part.
The first step is to build your silverlight application. I used the Hello Silverlight 2.0 application from the Silverlight BluePrint for SharePoint.
Create your web part
Then create your web part. I used the SharePoint WebPart template for Visual Studio 2008.
Add a reference to the following DLLs:
- System.Web.Silverlight.dll (version 2.0.5.0)
- System.Web.Extensions.dll (version 3.5.0.0)
Add your silverlight application (.xap) to your Visual Studio project. I created a Resources directory for it. Set the properties of the xap to Embedded Resource. Don't forget this because otherwise the Silverlight application will not be compiled as embedded resource.
Open the Web Part class. Before the namespace declaration add the metadata attribute that enables an embedded resource in an assembly:
[assembly: WebResource("EmbeddedSilverlightWebPart.Resources.SL.XAML.HelloSilverlight20.xap", "application/x-silverlight-app")]
Check the correct namespace with Reflector.
Add a class level variable for the Silverlight control. This control resides in the System.Web.Silverlight namespace.
Silverlight silverlightControl;
Override the OnLoad event to check whether a Script Manager already lives on the Web Part page.
protected override void OnLoad(EventArgs e) { base.OnLoad(e);
// Script manager instance may appear only once on a page ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page); if (scriptManager == null) { scriptManager = new ScriptManager(); this.Controls.AddAt(0, scriptManager); } }
Instantiate the Silverlight control in the CreateChildControls method and add it to the Controls collection. The Source property of the silverlight control need to be set to the location of the embedded resource. This location can be detected by using the this.Page.ClientScript.GetWebResourceUrl method:
protected override void CreateChildControls() { base.CreateChildControls();
this.Width = new Unit("400"); this.Height = new Unit("200");
string xapUrl = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "EmbeddedSilverlightWebPart.Resources.SL.XAML.HelloSilverlight20.xap"); silverlightControl = new System.Web.UI.SilverlightControls.Silverlight() { ID = "EmbeddedSlCtl", MinimumVersion = "2.0.30523", Source = xapUrl, Width = new System.Web.UI.WebControls.Unit(400), Height = new System.Web.UI.WebControls.Unit(200) }; this.Controls.Add(silverlightControl); }
Override the RenderContents method:
protected override void RenderContents(HtmlTextWriter writer) { EnsureChildControls(); if (silverlightControl != null) silverlightControl.RenderControl(writer); }
That's it. Build your code.
Deploy the web part
Make the necessary changes to the .webpart file and the .xml file if you want to. Patrick learned me to always add the web part to a significant group in the Web Part Gallery:
<Elements Id="1eba021c-8a0f-4bf2-8f2e-1c9d8f36bf7f" xmlns="http://schemas.microsoft.com/sharepoint/" > <Module Name="WebParts" List="113" Url="_catalogs/wp"> <File Path="EmbeddedSilverlight.webpart" Url="EmbeddedSilverlight.webpart" Type="GhostableInLibrary"> <Property Name="Group" Value="Silverlight" /> </File> </Module> </Elements>
Deploy the web part to your SharePoint site. If you use the Visual Studio 2008 extensions for SharePoint, you only have to enter the URL of your SharePoint site in the project properties and press F5.
Don't forget to configure your SharePoint sites for enabling Silverlight if not yet done.
Add the Web Part to a Web Part page
You can download the sample web part here.
Thanks to Stefaan Rillaert for pointing me in the right direction. 11/09/2008
Yesterday I was learning how to work with LINQ. I tried to use LINQ to XML to parse the XML that results from calling methods on the Lists.asmx.
I made a small windows application with Visual Studio 2008 to fill a combo box with lists. When you select a list, a grid view is populated with the some information of the fields of the selected list.
The combo box is populated as follows:
|
XmlNode listsResult = listService.GetListCollection();
// Get the Title and the ID from the xml XDocument results = XDocument.Parse(listsResult.OuterXml);
var lists = from item in results.Descendants(XName.Get("List", "http://schemas.microsoft.com/sharepoint/soap/")) select new { Title = item.Attribute("Title").Value, Id = item.Attribute("ID").Value };
ListsComboBox.DataSource = lists.ToList(); ListsComboBox.DisplayMember = "Title"; ListsComboBox.ValueMember = "Id"; |
The grid is populated as follows:
|
XmlNode result = listService.GetList(ListsComboBox.Text); XDocument results = XDocument.Parse(result.OuterXml);
var fields = from item in results.Descendants(XName.Get("Field", "http://schemas.microsoft.com/sharepoint/soap/")) where item.Attribute("ID") != null select new { DisplayName = item.Attribute("DisplayName").Value, InternalName = item.Attribute("Name").Value, TypeAsString = item.Attribute("Type").Value, Id = item.Attribute("ID").Value ?? "empty" };
FieldsDataGridView.DataSource = fields.ToList(); |
What a delight not to have to parse all that XML again! 5/09/2008
On Wednesday evening my best friend Patrick Tisseghem passed away, 1 year and one month after his friend David Boschmans. At this very moment I still cannot believe it. He still had so many plans.
Patrick, I’m so glad I had the chance to know you. Ten years ago you were only a hero speaking at small conferences but since the day we met in person, we became friends, good friends and it felt like we knew each other for ever. We could share everything: good feelings, bad feelings. Whenever I had a problem or a dip, I always turned to you and you were always there to help me out. I consider myself lucky that I was able to return you the favor on many occasions. Even when you were abroad we talked every single day. Thanks to you I achieved things that I never dared dream of.
Dearest friend, since the day we met I've always followed your trail. You were my guide I trusted unconditionally. But your trail doesn’t stop here. You will always be my guiding light. You will always be on my mind.
You will last forever. 27/08/2008
The Silverlight BluePrint for SharePoint on Silverlight Beta 2 is finally available for download here.
“The updated release of the Silverlight Blueprint for SharePoint is a little different from the original blueprints as with this release we've created a set of self-contained samples that using the blueprint methodology you can deploy to your SharePoint site to test out the Silverlight applications. The goal of the blueprints is to give you some guidance on how to integrate Silverlight applications with SharePoint. There are many possibilities here, and we've put together just a few to get you started.”
We have built in the latest new features of Silverlight, like Visual State Manager, HTTPWebRequest, data binding,
Hello World sample
This is a simple web part sample that shows how you can host a silverlight application from within a SharePoint web part.
In the Silverlight 2 beta 1 BluePrint for SharePoint we always deployed to a sub folder of the ClientBin that resides in the SharePoint web application but in this version of the Blueprint we also deployed to other locations. This sample contains a SharePoint web part that deploys to a document library and a web part that deploys to the LAYOUTS folder.
Slider custom field sample
This is a SharePoint custom field type containing a Silverlight slider. No major changes are made to this sample. As for the Silverlight 2 beta 1 BluePrint for SharePoint, the technique for using the InitParams property for the Silverlight control is explained here.
Media Viewer web part sample
This web part illustrates the use of a Picture Library containing pictures or movies. Information like the URL of the SharePoint site, the name of the Picture Library and the type of media is passed in the InitParams property of the Silverlight control. The data for the pictures is downloaded from within the Silverlight application using the HttpWebRequest object. This technique works completely asynchronous know. Changes to the Silverlight code itself include the use of the built-in ListBox control customized with styles and data binding.
The SharePoint web part is deployed to a document library.
Colleague Viewer web part sample
This sample illustrates the use of a WCF service for displaying colleague information out of the UserProfileManager. The WCF service runs in the SharePoint context. This WCF service is called from within the Silverlight application. Silverlight techniques used are styles and data binding.
The SharePoint web part is deployed to a SharePoint document library.
Navigation Control sample
This controls shows how you can develop a custom navigation control hosting a silverlight control. The data for the silverlight application is retrieved from within SharePoint and passed in an XML Data Island that can be accessed by the Silverlight application. Silverlight techniques used here are data binding and Visual State Manager to build the navigation scroll viewer. The silverlight application comes with a SharePoint master page feature.
Have fun with it! Hope you like it. 30/07/2008
Some months ago I needed to develop a custom timer job for a customer. That time I learned a lot from this post of Andrew Connell.
When the timer job ran in test, we used an SPMinutesSchedule. But after some time, the job needed to be deployed in production. So I had to change the code in the FeatureReceiver event to have a weekly schedule. So I came to the idea of developing an application page in which you can configure and reschedule job definitions.
You can download the feature here. (A small remark: when deploying the solution using the delivered setup, be sure to only leave the Central Administration web application checked).
You can access the application page from a custom section in the Operations page of the SharePoint 3.0 Central Administration.
The page looks like the following:
In the first section you can choose the web application for which you want to configure a timer job. The dropdown list in the Job Definitions section is populated with the job definitions running on the selected web application.
The third section is an idea I got from Andrews article. In general jobs run for a complete web application. But this feature makes use of the SharePoint object property bag so that you can configure a custom timer job to run for one or more site collections of the selected web application.
If you schedule a job for a specific site collection, you have to add some extra code within your custom timer job, otherwise it will continue running for the whole application:
Before you can use the U2U.SharePoint.Administration.JobConfigurationSettings class, you have to add a reference to the U2U.SharePoint.JobDefinitionConfigurator.dll, which is deployed in the 12\TEMPLATE\ADMIN\U2U.SharePoint.JobDefinitionConfigurator\bin folder:
Remark: This means that the option of running a job for a specific site collection doesn't apply to standard SharePoint jobs!!
In the 4th section you can choose a schedule. If the selected job is already scheduled, the next occurrence date and the current schedule is displayed:
You can also enable/disable a timer job.
If you want to learn more about developing custom timer jobs:
- read the MSDN article: Creating Custom Timer Jobs in Windows SharePoint Services 3.0
- look at the Visual How-To: Creating, Deploying, and Debugging Custom Timer Jobs in Windows SharePoint Services 3.0
both from andrew connell. Andrew, thanks for sharing your knowledge!
This feature contains resources: all strings can be translated into your language. The resource files are deployed to the 12\Resources directory and are retrieved using the SPUtility.GetLocalizedString. Thanks to Renaud Comté for helping me out with the resources.
You can read more about localization of strings here:
- Localisation des développements avec SharePoint
- Expression Builder et localisation
| Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XsnLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | FileType | xsn | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.2 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.3 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.4 | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsx | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsb | 255 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsx | 256 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsb | 256 |
|
|
|
|
|
| Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XsnLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | FileType | xsn | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.2 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.3 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/karine/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.4 | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsx | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsb | 255 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsx | 256 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /Blogs/karine/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsb | 256 |
|
|
| | | | |