New Demo Project Released: SharePoint Web Change Log – An Alternate Notification Feature


I created an alternated notification feature for SharePoint 2010. It’s a demo project for SharePoint 2010. I’ve done it for some practice in SharePoint development and just for fun 🙂

It’s intended to replace the default notification feature of SharePoint 2010 where you can subscribe to notifications list based. – With my feature a user can subscribe to all changes of a SharePoint Web by using a menu entry in the Personal Actions menu.

The notification mail is send to any subscribing user once a day. (Please notice that at the moment there is no security trimming for the notification mail!)

Project site: http://spwebchangelog.codeplex.com

 

How it works:

1. There is a web scoped feature and a farm scoped feature.

2. The web scoped feature is responsible for the Personal Actions menu entry and the change log at web scope.

image

3. The farm scoped feature deploys a timer job that scans each web every day and sends the notification mail if there are any changes in the web.

image

4. The job can be scheduled as you like.

5. On each web where the web scoped feature is active, there are two hidden lists:

image

This list contains an list item for each user that has subscribed for notifications. If a users unsubscribes the list item is removed.

image

6. If the web feature is active the “Change Log” list will contain a list item for each change in other lists of the web.

A list event receiver recognizes each list level change: Created lists, deleted lists.  It adds list item event receivers to each list in the web.

A list item event receiver creates items in the “Change Log” list for each list item action: add, update, delete.

7. If the web scoped feature is deactivated the list event receiver and all list item event receivers are removed. If the feature gets activated the list event receiver and a list item event receiver for each existing list are registered.

8. The farm scoped feature deploys a timer job that scans each web of a specific web application. If the web feature is active in a web the timer job looks for the change log list and for subscribers. If there are at least one subscriber and at least one one change since the last job run the notification mail is send.

image

9. It’s localized for german and english. The notification mail text is part of a resource file. But the resource file value for the mail text can be replaced by using a Web Property.

image

10. The notification mail is not security trimmed! That’s important for use in a production environment!

11. It’s tested in both a german and an english SharePoint system with both language packs, with multiple site collections and multiple webs and sub webs. I’d like to hear your experiences. Please report any bug. Feel free to modify it but please send me your improvements!

BTW: A little trick for development in Visual Studio 2010 – Start PowerShell scripts that need to run in an x64 context by double click from Solution Explorer


For development and some related tasks I use PowerShell, of course. – I store the PowerShell scripts in my projects as part of them. They are part of the source code and they are saved in the source control.

If I need to run such a script I start it directly from Solution Explorer in VS2010.

Therefore I’ve set the default “open with…” to “powershell.exe”

image

image

image

If you have done this you can run every “.ps1” script file by double click in Solution Explorer!!

BUT… VS2010 itself is 32bit! – If you start an architecture independend process like “poweshell.exe” from within VS2010 it runs in 32bit environment! But sometimes you need to run a 64 version of PowerShell, e.g. for some SharePoint tasks that need an 64 bit environment.

Therefore I’ve created a little App “StartPS64”:

1. In VS2010 create a new Project of type “Console Application”

2. Open the project’s properties, select the “Build” tab and change “Platform target” to x64.

SNAGHTML57d9e4d

3. Edit “program.cs” and insert this code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace StartPS64
{
    class Program
    {
        static void Main(string[] args)
        {
            string fullname = System.IO.Path.GetFullPath(args[0]);
            if( !System.IO.File.Exists(fullname) )
            {
                Console.WriteLine("Script does not exist!");
                Console.ReadKey();
                return;
            }

            Process.Start(@"c:\windows\system32\windowspowershell\v1.0\powershell.exe", fullname);
        }
    }
}

4. Compile it.

5. Specify the build “startps64.exe” as new “default application” for “.ps1” files in VS2010 as described above.

6. Now every “.ps1” file started from the Solution Explorer will run in an 64 bit environment and can execute SharePoint cmdlets!

Walkthrough: Create simple WCF Web Service for SharePoint 2010 with Visual Studio 2010


In this “Walkthrough” I’d like to show you how to create a simple WCF Web Service for SharePoint 2010.

This Web Service will provide two methods:

  • Ping => Just as test.
  • GetUsedEmailAliasses => This method reports all aliasses used for “E-Mail enabled lists” in SharePoint.

Here is the code: http://spwcfwebservicedemo.codeplex.com/

Let’s start.

1. Create a new SharePoint 2010 project in Visual Studio 2010. Use the “Empty Project” template. Name the project “ik.SharePoint2010.SPWCFWebServiceDemo”.

image

2. In the project creation wizard specify the Central Administration address as deployment location. You need to deploy as “Farm Solution”:

image

3. Now add this Assembly References:

  • Microsoft.SharePoint.Client
  • Microsoft.SharePoint.Client.Runtime
  • Microsoft.SharePoint.Client.ServerRuntime
    (You may need to locate this assembly in the file system: “C:\Windows\assembly\GAC_MSIL\Microsoft.SharePoint.Client.ServerRuntime\14.0.0.0__71e9bce111e9429c\Microsoft.SharePoint.Client.ServerRuntime.dll”)
  • System.Configuration
  • System.ServiceModel
  • System.ServiceModel.Web

Now my Assembly Reference tree looks like this:

4. Now map the SharePoint hive folder “Layouts” to your project:

a) Right click your project in the Solution Explorer Pane

b) In the context menu open sub menu “Add” and click “SharePoint Mapped Folder”

c) Select this:

image

d) Click “OK”

5. Create a sub folder named “ik.SharePoint2010.SPWCFWebServiceDemo” in folder “Layouts”

6. Add a new project item of type “Interface” to your project. Name it “ISPWCFSvc.cs”.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.InteropServices;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace ik.SharePoint2010.SPWCFWebServiceDemo
{
    [ServiceContract(Namespace="http://schemas.microsoft.com/sharepoint/soap/"),      Guid("f01e2ff6-c291-4b8b-a154-cd7059ed4900")]
    public interface ISPWCFSvc  {
        [OperationContract, WebInvoke(Method = "GET")]
        List<string> GetUsedEmailAliasses();

        [OperationContract, WebInvoke(Method = "GET")]
        string Ping();
    }
}
7. Add a new project item of type “Class” and name it “SPWCFSvc.cs”
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Web;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Security;

namespace ik.SharePoint2010.SPWCFWebServiceDemo
{
    [Guid("ae428eb5-02d1-4e50-8cee-eb3806f16ffd"),
    ServiceBehavior(Namespace = "http://schemas.microsoft.com/sharepoint/soap/"),
    AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required),
    ClientRequestServiceBehavior,
    SharePointPermission(SecurityAction.Demand, ObjectModel = true),
    AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
    public class SPWCFSvc : ISPWCFSvc  {
        [SharePointPermission(SecurityAction.Demand, ObjectModel = true)]
        public List<string> GetUsedEmailAliasses()
        {
            List<string> l = new List<string>();

            SPProcessIdentity pi = SPContext.Current.Site.WebApplication.Farm.TimerService.ProcessIdentity;
            string userName = pi.Username;
            object configDB = pi.GetType().GetProperty("ConfigurationDatabase", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(pi, null);
            SPServer server = (SPServer)configDB.GetType().GetProperty("Server").GetValue(configDB, null);
            string dbName = (string)configDB.GetType().GetProperty("Name").GetValue(configDB, null);
            string serverName = server.Name;

            SPSecurity.RunWithElevatedPrivileges(() =>
            {
                System.Data.SqlClient.SqlConnection s = new System.Data.SqlClient.SqlConnection(new System.Data.SqlClient.SqlConnectionStringBuilder {
                    DataSource = serverName,
                    InitialCatalog = dbName,
                    IntegratedSecurity = true }.ConnectionString);

                SPConfigDBDataContext dc = new SPConfigDBDataContext(s);

                foreach( var item in dc.EmailEnabledLists )
                {
                    l.Add(item.Alias);
                }
            });

            return l;
        }

        [SharePointPermission(SecurityAction.Demand, ObjectModel = true)]
        public string Ping()
        {
            return "Pong";
        }
    }
}
8. Now add a new “Text File” project item and name it “spwcfsvc.svc”
<% @ServiceHost Service="$SharePoint.Type.ae428eb5-02d1-4e50-8cee-eb3806f16ffd.AssemblyQualifiedName$" Factory="Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory, Microsoft.SharePoint.Client.ServerRuntime, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"%>

Here we use an existing service factory of SharePoint that will handle the service instanciation for us.

In this file we use the token replacement functionality of Visual Studio 2010 for SharePoint 2010 development. We like to replace the token “$SharePoint.Type.ae428eb5-02d1-4e50-8cee-eb3806f16ffd.AssemblyQualifiedName$” through the “real” full qualified name during package creation.

By default *.svc files will not be processed by the token replacement engine. We need to specify *.svc files for that build step. Therefore we edit the C# project file in notepad.  Insert this line as shown in the screenshot:

<TokenReplacementFileExtensions>svc</TokenReplacementFileExtensions>

image

After deploying the solution you may have a look into the SharePoint hive and look into “spwcfsvc.svc”

9. Now Copy & Paste this file into the you folder in the mapped Layouts folder:

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI\web.config

10. You need to edit this file. Remove the complete “<system.web>” tag and the (four) “location” tags at the beginning of the copied file! – The configuration settings in the copied & modified web.config file will manage the diffrent authentication methods for us. This works by using the class attribute “ClientRequestServiceBehavior” in the code above.

11. Now we add a “Linq to SQL” connection to the SharePoint Configuration database. Be sure only to read this DB!!!

12. Add a new project item of type “Linq to SQL Classes” to the project. Name it “SPConfigDB.dbml”

image

13. In the Server Explorer of Visual Studio 2010 create a connection to the SharePoint Configuration DB of your development environment. – After that, open the connection, open the “Table” node and select “EmailEnabledLists”.

image

14. Drag the “EmailEnabledLists” node to the “SPConfigDB.dbml” canvas. – It looks like this:

image

15. In the Properties Pane set the “Context Namespace” property to “ik.SharePoint2010.SPWCFWebServiceDemo”. (If you do not see this properties like in the screenshot below you need to right click the “SPConfigDB.dbml” project item node in the Solution explorer and click “Properties” in the context menu.

image

16. Now you should be able to compile and deploy your project.

17. Edit the startup settings. In the “Debug” select “Start browser with URL” and enter there the URL to your webservice: “http://<central-administration-url-and-port>/_layouts/ik.sharepoint2010.spwcfwebservicedemo/spwcf.svc/GetUsedEmailAliasses”

SNAGHTML4b070d4

18. Now start the project. You get something like this:

SNAGHTML4acbe57

I’ve only one e-mail enabled list or library in my current dev system.

Walkthrough: Deploy ClickOnce Application as SharePoint 2010 Solution Package


In some projects there was a need to run code on the client machine for interaction with SharePoint. If’ve realized this kind of applications as “ClickOnce” apps. It’s possible to deploy them as “SharePoint Solution Package”. If you do so the ClickOnce files can be deployed to every WFE. Updating the ClickOnce is easy.

Here I want to show you how to deploy a ClickOnce app als SharePoint Solution.

Let’s start.

1. Create your ClickOnce app. – If you have an existing one skip to step 5. – Otherwise continue reading. I’ll show you how to create a very simply ClickOnce.

Open  Visual Studio 2010. Create a new project of type “Windows Forms Application” or “WPF Application”. I’ll use the first one and name the project “MyClickOnce”.

image

Design you app. – I drag 2 Label controls, 2 Checkbox controls and 2 Textbox controls to the surface. I do not change their names but their fonts Smile

image

In my app I’d like to show the “running context”: locally started EXE or online started ClickOnce. Furthermore I’d like to show the URL if started online.

2. Open the Code view of the form.

First of all you need to add a assembly reference for “System.Web”!

Then insert this code. Maybe you need to correct the name of the controls.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections.Specialized;
using System.Deployment.Application;
using System.Web;

namespace MyClickonce
{
    public partial class Form1 : Form {
        public Form1()
        {
            InitializeComponent();

            ParseParams();

            checkBox1.Checked = !IsOnline;
            checkBox2.Checked = IsOnline;
            textBox1.Text = Url;
            textBox2.Text = Parameters["Param1"];
        }

        private bool _isOnline = false;
        private NameValueCollection parameters = null;
        private string _url = "";

        public bool IsOnline
        {
            get {
                return _isOnline;
            }
        }

        public string Url
        {
            get {
                return _url;
            }
        }

        public NameValueCollection Parameters
        {
            get {
                return parameters;
            }
        }

        private void ParseParams()
        {
            NameValueCollection nameValueTable = new NameValueCollection();

            if( ApplicationDeployment.IsNetworkDeployed )
            {
                _isOnline = true;
                _url = ApplicationDeployment.CurrentDeployment.ActivationUri.ToString();

                string queryString = ApplicationDeployment.CurrentDeployment.ActivationUri.Query;
                parameters = HttpUtility.ParseQueryString(queryString);
            }
            else {
                _isOnline = false;
                parameters = HttpUtility.ParseQueryString(string.Join("&", Environment.GetCommandLineArgs()));
            }
        }
    }
}

The method “ParseParams” will be useful while developing the app and later running the app: This method is able to parse both “command line parameter” sources: URL and native (EXE). During development you maybe need to pass parameters to the app for testing purpose. Than you define this parameters in the “Debug” tab of the project properties.

Here is a screenshot of the app’s debug settings:

image

You see there is a parameter “Param1” follwed by “=” and it’s value. This is similar to URL style query string parameters. But you do not separate them with “&”! Instead use a single whitespace. – Later in the URL you will use “&” as normal!

Now just run the app!

image

Nice, isn’t it?

3. Now you need to configure the application to become a ClickOnce.

Open the Project Properties of your Windows Form App project.

Select the “Signing” tab and create a self signed certificate. Or use a valid Code Signature certificate.

image

Now switch to the “Publish” tab of the project settings.

Here you can change the settings as you need it. – I’ll leave it as is EXCEPT one setting: Click the “Options…” button and select “Manifests”. Check “Allow URL parameters to be passed to application”:

image

[If you do not set this the app will fail in the following line because “ActivationUri” will be null: “_url = ApplicationDeployment.CurrentDeployment.ActivationUri.ToString(); “]

The other settings:

image

Click “Publish Now”.

Than the project will be build and stored to the sub folder “Publish” of your project folder in the file system.

image

4. If you now try to run the app locally you may get this error:

image

This is caused by your ClickOnce publishing in the step before.

The resolve this open the project settings, select the “Security” tab and clear the checkbox “Enable Clickonce security settings”:

image

This you need to do after each ClickOnce publishing!

5. Now we create the SharePoint Solution Package.

In the Solution Explorer click on the solution item, click “Add” and click “New project”.

image

Now chooce “Empty SharePoint Project” and name it “MyClickonceDeployment”.

As local site I use “http://sharepoint.local/sites/clickonce”. It has to be a “Farm Solution”!!

image

Now create a “Module” project item. Name it “MyClickonce”.

SNAGHTMLacb2fc

Remove the file “Sample.txt”

image

6. Now open the solutions path in Windows Explorer.

Go into the folder of the Windows Forms Application. There go into the “Publish” folder.

Select the “.application” file of your ClickOnce app and select the “Application Files” folder. This items you need to copy. Just select “Copy” from the context menu or press Ctrl+C.

No open the folder of “MyClickonceDeployment” and go into the folder “MyClickonce”. There insert (paste) the selected items.

Now you folder should look like this:

image

In the “Application Files” folder you’ll see another folder “1_0_0_0” or with another version number. This version number will be increased by every ClickOnce publishing if you did not disable this function.

7. Back in the Visual Studio go into the Solution Explorer and click this icon:

image

This will show you all files in the project folder, not even project items.

Select the “MyClickonce” module project item. Maybe you need to click the icon:

image

You should see this:

image

Right click on “MyClickonce.application” and select “Include in project”. Right click on “MyClickonce_1_0_0_0” and select “Include in project”.

Now you need to edit the “Elements.xml” file of you module project item.

First of all add an attribute named “Path” to the “Module” tag. This will define the URL of your ClickOnce app. Select a unique name so that the solution won’t get in conflict with other solutions. You could choose a GUID here or use date and time:

image

Now you can remove the string “MyClickonce/” of the beginning of every “Path” attribute of the child nodes of the “Module” tag.

image

After removing the string the file should have this content:

<?xml version="1.0" encoding="utf-8"?> <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> <Module Name="MyClickonce" Url="MyClickonce20110815152200"> <File Path="MyClickonce\MyClickonce.application" Url="MyClickonce.application" /> <File Path="MyClickonce\Application Files\MyClickonce_1_0_0_0\MyClickonce.application" Url="Application Files/MyClickonce_1_0_0_0/MyClickonce.application" /> <File Path="MyClickonce\Application Files\MyClickonce_1_0_0_0\MyClickonce.exe.deploy" Url="Application Files/MyClickonce_1_0_0_0/MyClickonce.exe.deploy" /> <File Path="MyClickonce\Application Files\MyClickonce_1_0_0_0\MyClickonce.exe.manifest" Url="Application Files/MyClickonce_1_0_0_0/MyClickonce.exe.manifest" /> </Module> </Elements> 

8. Now deploy your SharePoint Solution Package!

9. To verify the ClickOnce was deployed correctly just open the site with SharePoint Designer 2010.

Open SPD.

Click “All Files”.

Now you should find your folder “MyClickonce20110815152200”.

image

9. Open the SharePoint site you deployed to.

Enter the complete URL of the ClickOnce app in the address bar of the browser. In my case the URL is:

http://sharepoint.local/sites/Clickonce/MyClickonce20110815152200/MyClickonce.application

image

Open the URL.

The ClickOnce should start after some seconds. During installation or update you’ll see these windows:

image

image

It will look like this:

image

10. Now lets add a Quicklaunch entry for this:

image

In the link I’ve used “Param1”: http://sharepoint.local/sites/Clickonce/MyClickonce20110815152200/MyClickonce.application?Param1=Hey, Ingo!

image

Just click the Quicklaunch entry.

You’ll get:

image

That’s it. – Please let me know if it worked for you!

Of course you could build query strings in JavaScript to pass dynamically generated parameters to the ClickOnce!! This is charming and makes ClickOnce apps to become usefull in SharePoint development. You could create custom Ribbon menu items and call a ClickOnce app on click. As parameters you could pass ListID, Web URL, ItemID, … to the app! Very cool!

Have fun! – Please post your comments on this!

Walkthrough/Solution for Workflow Error in SharePoint 2010 State Machine Workflow: Event "OnWorkflowActivated" on interface type "Microsoft.SharePoint.Workflow.ISharePointService" for instance id "<guid>" cannot be delivered.


Today I got the following error and did not find a clear description and solution for it:

image

Error message: “Event “OnWorkflowActivated” on interface type “Microsoft.SharePoint.Workflow.ISharePointService” for instance id “<guid>” cannot be delivered.”

 

The Solution: …in my case was a missing “EventDriven” activity.

My “Initialization” state looks like this:

image

I’ve added a “StateInitialization” Workflow Activity and added some code to it. But this is a SharePoint Workflow and it needs at least an “OnWorkflowActivated” event driven activity.

Let’s walk through the solution:

1. Drag a “EventDriven” activity to the “Init” state. Its name may defer in your project.

image

2. Name the EventDriven activity “onWorkflowActivatedHandler”. (You can use an other name too!)

3. Double click the EventDriven activity.

4. Drag a “OnWorkflowActivated” activity from the Toolbox pane into the “onWorkflowActivatedHandler” activity:

image

5. Add a correlation token to “onWorkflowActivated1”!!

6. Add a binding for “WorkflowProperties” !!!

image

7. That’s it. Now you can add activities behind “handleExternalEventActivity1”… As you like.

Walkthrough: Add List Event Receiver dynamically at runtime in SharePoint 2010


This time a tiny neat walkthrough of how to add an Event Receiver at runtime in SharePoint 2010.

Let’s say you have a SharePoint site that your colleagues already use. In this site you have an existing list. Now you want to add some automation to this existing list. – You cannot deploy the list as List Definition w/ List Instance again in a VS 2010 SharePoint project, because the list exists and the data must not be touched.

One solution is to add an List Event Receiver that is contained in a VS2010 solution package.

1. You create a Empty SharePoint 2010 project in Visual Studio 2010.

2. Now you add an “Event Receiver” project item

image

3. Now you add the events you want to handle. Select “List Item Events” and “Custom List”.

image

4. Implement some functionality in the newly created Event Receiver class.

5. Now create or open an Feature Event Receiver for the SharePoint feature that will configure the event receiver. – You have to create a new feature or use an existing feature… If you create a new feature event receiver you have to uncomment the methods “FeatureActivated” and “FeatureDeactivating”.

6. Add this code to the “FeatureActivated” method:

try {
    SPWeb web = (SPWeb)properties.Feature.Parent;
    SPList l = web.Lists["My SharePoint List"];
    if( l != null )
    {
        bool found = false;
        foreach( SPEventReceiverDefinition er in l.EventReceivers )
        {
             if( er.Class == "Full.Namespace.Qualified.Class.Name.Of.Your.Event.Receiver.Class")   {
                 found = true;
                 break;
             }
        }

        if( !found )
        {
            SPEventReceiverDefinition newERD = l.EventReceivers.Add();

//the next line is only valid if the event receiver class is in the same assembly as the feature event receiver!!!

            newERD.Assembly = System.Reflection.Assembly.GetExecutingAssembly().FullName;
            newERD.Class = "Full.Namespace.Qualified.Class.Name.Of.Your.Event.Receiver.Class";
            newERD.SequenceNumber = 1000;

//you may add more “received” events in the following line.

            newERD.Type = SPEventReceiverType.ItemUpdated | SPEventReceiverType.ItemAdded;
            newERD.HostId = l.ID;
            newERD.HostType = SPEventHostType.List;
            newERD.Update();
            l.Update();
        }
    }
}
catch {
}

This installs the event receiver when the feature gets activated.

7. Add this code to the “FeatureDeactivating” method:

try {
    SPWeb web = (SPWeb)properties.Feature.Parent;
    SPList l = web.Lists["My SharePoint List"];
    if( l != null )
    {
        SPEventReceiverDefinition d = null;
        foreach( SPEventReceiverDefinition er in l.EventReceivers )
        {
            if( er.Class == "Full.Namespace.Qualified.Class.Name.Of.Your.Event.Receiver.Class" )
            {
                d = er;
                break;
            }
        }

        if( d != null )
        {
            d.Delete();
            l.Update();
        }
    }
}
catch {
}

This will remove the event receiver when the feature gets deactivated.

8. Now remove the “Elements.xml” file in the Event Receiver project item in the Solutions Explorer:

image

9. For me this works very well.

How to deploy conditional formatting in a SharePoint 2010 list definition using Visual Studio 2010


This time it’s not a walkthrough. Only a description of what you have to do. – It’s “experimental”!!!

The need is to deploy a conditional formatting in a list definition that was created in a SharePoint 2010 Visual Studio (2010) project.

1. You need to design the list definition. Create a list instance for the list definition. This instance you can remove later if you want.

2. Deploy the project. It’s without conditional formatting at this point.

3. Create the conditional formatting in SharePoint Designer.

Open the list instance.

Open the list view you want to modify.

Select the cells that should have a conditional formatting.

Create the conditional formatting.

4. Open the “Code” view of the list view page.

5. Look for the “<xsl>” tag of the XsltListViewWebPart that renders the list data.

Copy the content of the <xsl> tag.

6. In Visual Studio open the “Schema.xml” file of the list definition.

7. In the <views> tag look for the view you want to modify. E.g. “AllItems.aspx”. Look for the “Url” attribute of the view tag that contains the Web Part Page name (e.g. “AllItems.aspx”).

8. Before the closing “view” tag add this:

        <Xsl>
              <![CDATA[
              ...
              ]]>
        </Xsl>

Replace the “…” through the copied content of the web part pages “xsl” tag content.

9. Deploy the project.

10. It’s done! – BUT: You may be unable to edit the conditional formatting in SharePoint Designer! As I said: It’s experimental.