SharePoint 2013 Custom AJAX filters on List View Web Parts

Requirement:
Implement ‘exact match’ filter against the list view web part on text values and drop down values using AJAX for great user performance. An alternative to filtering in a fly out menu of the list view web part’s column values.ajaxfilter1
Filter by ‘Title’
ajaxfilter2

Filter by ‘Task Status’
ajaxfilter3

Technique:

I am essentially emulating the column based filters that are out-of-the-box functionality of the SharePoint 2013 List view web parts. I do this by tracking down how the filtering is executed in the SharePoint inplview.js code. Then wrap the filtering JavaScript logic through custom text boxes.

ajaxfilter4

You can see the URL query string parameters reflect the filtering
/SitePages/Tickets.aspx#InplviewHashdba27ef6-7bff-4c0f-8ec1-b3e3e18fb0b8=FilterField1=LinkTitle-FilterValue1=Printer broken

For large lists (i.e. > 5,000 items), keep in mind to index the columns you want to filter by. You can find the setting in the List Settings page and find a link ‘Indexed Columns’

<table style="" border="0">
    <tr>
        <td>Title:</td>
        <td><input type="text" id="title" onblur="TitleFilter(); return false;" /></td>
        <td>
            <button onclick="TitleFilter(); return false;">Filter by Title</button>
        </td>
    </tr>
    <tr>
        <td>
            Task Status:
        </td>
        <td>
            <input type="text" id="taskStatus" onblur="TaskStatusFilter(); return false;" />
        </td>
        <td>
            <button onclick="TaskStatusFilter(); return false;">Filter by Task Status</button>
        </td>
    </tr>
    <tr>
        <td></td>
        <td></td>
        <td>
            <button onclick="TitleAndTaskStatusFilter(); return false;">Filter by Title AND Task Status</button>
        </td>
    </tr>
</table>
 

<script language='javascript'>
       function MyRefreshPageToEx(lvTableID, url, bForceSubmit) {

        // Hardcode reference to list view <table> Id attribute
        var tblv = document.getElementById("{BE9A90D1-BF5D-401B-8A9B-C44CCCD14241}-{DBA27EF6-7BFF-4C0F-8EC1-B3E3E18FB0B8}");
        var clvp = CLVPFromCtx(tblv);

        if (clvp != null && clvp.ctx.IsClientRendering) {
            clvp.RefreshPaging(url);
            clvp.ctx.queryString = url;
            if ((typeof clvp.ctx.operationType == "undefined" || clvp.ctx.operationType == SPListOperationType.Default) && Boolean(clvp.ctx.ListData)) {
                var fromPage = clvp.ctx.ListData.FirstRow - 1;
                var toPage = Number(GetUrlKeyValue("PageFirstRow", false, url));

                if (!isNaN(fromPage) && !isNaN(toPage) && fromPage != toPage)
                    fromPage < toPage ? (clvp.ctx.operationType = SPListOperationType.PagingRight) : (clvp.ctx.operationType = SPListOperationType.PagingLeft);
            }
        }
        else {
            SubmitFormPost(url, bForceSubmit);
        }
    }

    function TitleFilter() {
        var title = $('#title').val()
        var url;
        if (title) {
            url = "?List={BE9A90D1-BF5D-401B-8A9B-C44CCCD14241}&View={DBA27EF6-7BFF-4C0F-8EC1-B3E3E18FB0B8}&FilterField1=LinkTitle&FilterValue1=" + title
        }
        inplview.MyRefreshPage = MyRefreshPageToEx;
        inplview.MyRefreshPage(null, url, null);
    }

    function TaskStatusFilter() {
        var taskStatus = $('#taskStatus').val()
        var url;
        if (taskStatus) {
            url = "?List={BE9A90D1-BF5D-401B-8A9B-C44CCCD14241}&View={1F1B1E55-992B-4A03-98B2-9E5D34916611}&FilterField1=TaskStatus&FilterValue1=" + taskStatus
        }
        inplview.MyRefreshPage = MyRefreshPageToEx;
        inplview.MyRefreshPage(null, url, null);
    }

    function TitleAndTaskStatusFilter() {
        var title = $('#title').val()
        var taskStatus = $('#taskStatus').val()

        // HARD Code: query string to reference List GUID and View ID
        var url = "?List={BE9A90D1-BF5D-401B-8A9B-C44CCCD14241}&View={DBA27EF6-7BFF-4C0F-8EC1-B3E3E18FB0B8}&ViewCount=1&IsXslView=TRUE&IsCSR=TRUE&";
        if (title && taskStatus) {
          url = url + "FilterField1=LinkTitle&FilterValue1=" + title + "&FilterField2=TaskStatus&FilterValue2=" + taskStatus
        } else if (title && !taskStatus) {
          url = url + "FilterField1=LinkTitle&FilterValue1=" + title
        } else if (!title && taskStatus) {
          url = url + "FilterField1=TaskStatus&FilterValue1=" + taskStatus
        }
        inplview.MyRefreshPage = MyRefreshPageToEx;
        inplview.MyRefreshPage(null, url, null);
    }
</script>
 

There is some hard coding in the custom JavaScript code making references to the list view web part such as the table Id, list GUID and view GUID.

Find the table element Id as follows.
ajaxfilter5

Limitations

  • Inplview.js filtering only supports exact match of values and not partial match
  • OR operand is not supported in the inpview.js from what I can see.
  • This custom approach is a bit of “hack”. Since it is client side, there is no impact to the SharePoint farm on the server side. Nevertheless, follow any development guidelines in your team. At the least, regression testing is recommended on SharePoint product patching and upgrades for any breaking changes.

The solution fit

I think the better solution fit is where the user already knows exactly what to filter on, but doesn’t want to scroll a largest list of values through the OOTB column filters every single time. For example, filtering by exact name or a small number.

SharePoint 2013 Custom List View Web Part Refresh

In the SharePoint 2013 list view web part, the paging, filtering and sorting functionality is driven by the inplview.js file. This is supported by AJAX calls against a RESTful service inplview.aspx. I am able to extend the JavaScript inplview object to implement client side refresh as data is updated on the server.
refresh1

To configure the automatic refresh by OOTB (out-of-the-box) configuration, go to the Web Part Properties: 

refresh2

 

What I find unattractive of this approach is that it is using the older AJAX UpdatePanel introduced in ASP .NET 2.0.

  • There is at least 23kb transferred for each refresh which is a relatively heavier in bandwidth.
    refresh3
  • The http response time is longer.
  • Using IE 8 browser, there is a memory leak such that memory utilization by the browser maxes out.
  • The out of the paging, filtering and sorting with the AJAX options do not work well together. For example, the AJAX refresh option sometimes shows no rows even after repeated combination of filtering and manual OOTB AJAX refresh. To resolve, refresh the page without any query string parameters.

The applicable business scenario or requirement is when frequently added and updated list items by multiple users are to be seen updated in the browser without user requiring to manually refresh the page. 

In SharePoint 2013, when the user interacts with the list view web part for activities such as paging, column filtering and sorting, there is an AJAX request making a RESTful call to inplview.aspx.
refresh4 Compared to the OOTB refresh, the inplview.aspx REST calls are significantly lighter in bandwidth and has faster response time.

How inplview.js Works

The javascript code that supports the list view web part paging, sorting and filtering is in the inplview.js file

The sequence of calls are made as follows:

  1. Browser
    1. User clicks on list view web part to page, sort and filter
    2. invoke objects in various SharePoint .js files
    3. invoke objects inplview.js
  2. Server
    1. inplview.aspx that is a RESTful http service
    2. HTTP response back to browser with only JSON formatted row data.

Using the chrome JavaScript debugger against inplview.js, I have identified the following sequence of function calls. To support the refresh, I have “forked” the code with my own custom functions.

Original OOTB sequence Customized “forked” sequence
RestoreAllClvpsNavigation Refresh_RestoreAllClvpsNavigation
EnumCLVPs(RestoreClvpNavigation) EnumCLVPs(Refresh_RestoreClvpNavigation)
RestoreClvpNavigation(clvp) <skip>
clvp.RestoreNavigation(); <skip>
CLVPRestoreNavigation() Refresh_RestoreClvpNavigation(clvp)

The Implementation

There is no explicit data refresh support in the inplview javascript code so I have injected custom code that extends the inplview javascript object to have supporting functions to implement refresh.

// automatic refresh based on interval
function autoRefresh()
{
 window.setInterval(listViewRefresh, 2000); // 20 seconds
}

// refresh all list view web parts on the page
function listViewRefresh() {
 $('#lblMessage').text('refreshed ').fadeIn("slow").fadeOut("slow"); // debugging
 inplview.MyRestoreAllClvpsNavigation = MyRestoreAllClvpsNavigation;
 inplview.MyRestoreAllClvpsNavigation();
}

// Enumerate list view web parts
function MyRestoreAllClvpsNavigation()
{
 EnumCLVPs(MyCLVPRestoreNavigation);
}

// refresh referencing list view web part
function MyCLVPRestoreNavigation(clvp) {
 var strHash = ajaxNavigate.getParam("InplviewHash" + clvp.WebPartId());
 if (strHash == null)
 strHash = '';

 var strInpl = '?' + DecodeHashAsQueryString(strHash);
 var strShowInGrid = GetUrlKeyValue("ShowInGrid", true, strInpl);

 if (strShowInGrid == "True") {
 InitGridFromView(clvp.ctx.view, true);
 }
 else if (clvp.ctx.inGridMode) {
 ExitGrid(clvp.ctx.view, true);
 }
 clvp.strHash = strHash;
 clvp.fRestore = true;
 var curRootFolder = GetRootFolder2(this);

 if (curRootFolder != null)
 strInpl = SetUrlKeyValue("RootFolder", unescapeProperly(curRootFolder), true, strInpl);
 clvp.RefreshPagingEx(strInpl, true, null);

 }

$(document).ready(function() {
 autoRefresh();
});

refresh5

Benefits

  1. Overcome IE8 browser memory leak issue
  2. Noticeable performance improvement over OOTB Ajax option
  3. The ability to extend and customize the client side rendering of the list view web part functionality

Caveats

  1. Upgrades and patches:
    Since this is extending from product JavaScript code, in the event of upgrades or patching, there could breaking changes.
    To mitigate this risk, remember to regression test after a product upgrade and patch.

Supportability

  1. Still supports general list view paging, column filtering and sorting.
  2. Exception: column filtering and sorting is not supported on lookup columns as it is already with OOTB.
  3. Ability to refresh all list view web parts that exist on the same page.

I’ll have a another blog post to add filtering based on user input by customizing the inpvliew.js

SharePoint 2013 Workflow Integration with the WaitForCustomEvent Activity

Implementing an integration scenario with SharePoint 2013 Workflows using WaitForCustomEvent Activity in Visual Studio 2012 Technical Requirement: Integrate a SharePoint workflow with another application to call into the application and wait for a response with data.

Applicable business scenarios

  • A document management approval workflow notifies a CRM system of a customer engagement and provides a reference number back to the workflow.
  • A SharePoint workflow assigns and emails an end user to do some work in another application. The end user goes to the other application to do this work and it notifies the workflow of completion and other application data. The SharePoint workflow continues.

The following is an implementation flow that is applied to the above business scenario.

  1. The workflow instance calls an external application through a RESTful service passing correlating information and the custom wait event name.
  2. Workflow is in a wait state by the WaitForCustomEvent.
  3. The external application executes its relevant business logic and is then ready to notify the workflow through the SharePoint API by passing correlating information, event name and any event args (e.g. data).
  4. The workflow custom wait event handles the call and continues execution with the given event args. At this point, the workflow status can be set.
WaitForCustomEvent 2

High level development

  1. In Visual Studio 2013
    • Create a Workflow Custom Activity project item.
    • Deploy solution to a site.
  2. In SharePoint Designer 2013
    • Create a SharePoint 2013 workflow. The deployed activity will apear in the Actions menu
    • Add the custom action to the workflow design surface.
    • Publish workflow

Updating workflow custom activity and redeploy steps

  1. Create Workflow in SharePoint Designer 2013
    • Clear SP Designer website cache
  2. Create Workflow Activity in Visual Studio 2012
  3. Create external application to receive and publish the even back to the running workflow instance.

The WaitForCustomEvent Activity

This activity is part of the toolbox when you want to create a Custom Workflow Activity in Visual Studio 2012.

WaitForCustomEvent 3

When deployed to the SharePoint server, it will show up as a custom action in SharePoint Designer 2013. This activity has an input of EventName and an output of Result.

WaitForCustomEvent 12

SharePoint Client Side Object Model: WorkflowInstanceService.PublishCustomEvent

In the external application, leveraging the SharePoint Client Side Object Model, use the WorkflowInstanceService.PublishCustomEvent method to call to the waiting workflow instance to continue. This activity would handle the event is by a CSOM API call using the PublishCustomEvent method.

Parameter Description Type
instance The instance of a workflow that is running. WorkflowInstance
eventName The event name that would be declared in the WaitForCustomEvent activity String
payload Data that would be passed to the workflow. String

As you can see, the EventName input is associated to the eventName parameter and the Result output to the payload parameter. http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.workflowservices.workflowinstanceservice.publishcustomevent.aspx

WorkflowServicesManager workflowServiceManager = new WorkflowServicesManager(web);
var workflowInstanceService = workflowServiceManager.GetWorkflowInstanceService();
workflowInstanceService.PublishCustomEvent(workflowInstance, "CustomEventName", "Eventpayload:value;key:value");

Sample code on the use of this method is in  Sohel Blog post

Creating the Workflow Custom Activity in Visual Studio 2012

    1. Create new project SharePoint 2013 – Empty Project
    2. Right click on the project > Add new item > Select Workflow Custom ActivityWaitForCustomEvent 5
    3. Click on the xaml file and see the designer surface.
    4. Open the Toolbox pane
    5. Drag and drop the WaitForCustomEvent activity on to the designer surface. I have also added WriteToHistory activity for debugging/tracing purposes. WaitForCustomEvent 6
    6. Create arguments to make the design of this custom workflow activity dynamic and reusable in Sharepoint Designer workflows. At the bottom of the designer surface, click on the Arguments tab.WaitForCustomEvent 7

      Set “EventName” as an input argument and the “EventOuput” as the output argument. To give you an idea of what we are trying to achieve by “dynamic” here is a peak of how it will be used in SharePoint Designer workflow. The following blue text are placeholders for literal values or variables.

      WaitForCustomEvent 11 WaitForCustomEvent 9

    7. So now let’s get back to setting up these arguments in Visual Studio 2012. Click on the WaitForCustomEvent activity properties pane. Enter “EventName” argument for the EventName input Enter “EventOuput” argument for the Result ouput.WaitForCustomEvent 10
    8. Let’s surface these arguments to SharePoint Designer to look likeWaitForCustomEvent 8 Click on the .actions4 file. Setup as follows:
      <Action Name="WaitEventActivity" ClassName="WaitEvent.WaitEventActivity" Category="Custom" AppliesTo="all">
        <RuleDesigner Sentence="Wait Event Name %1 ( Event Args %2 )">
          <FieldBind Field="EventName" Text="Event Name" Id="1"
          DesignerType="TextBox"
          DisplayName="Event Name triggered from an external system" />
          <FieldBind Field="EventOutput" Text="Event Output" Id="2"
          DesignerType="TextBox" DisplayName="Event ouput from an external system"   />
        </RuleDesigner>
        <Parameters>
          <Parameter Name="EventName" Type="System.String, mscorlib" Direction="Optional"
          DesignerType="TextBox"
          Description="Event Name" />
          <Parameter Name="EventOuput" Type="System.String, mscorlib" Direction="Out"
          DesignerType="TextBox"
          Description="Event Output" />
        </Parameters>
      </Action>
      

Note: you can find more examples in the workflow15.actions4 file. These are all the out of the box actions. They are located at C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\TEMPLATE\1033\Workflow

    1. Deploy the solution to your SharePoint site.
      This is deployed as a farm solution and activate the feature at the web scope.
    2.  Open SharePoint Designer 2013 and open the site where you had activated the feature with the WaitForCustomEvent activity.
    3. Create a new Workflow in 2013 workflow platform
    4. In the ribbon, click Action > Add the Call HTTP Web Service to make a call to the external application through a RESTful service such that the necessary business logic will be executed.
      Pass correlating information and custom event name as query. This will be used to by the external application to call back to the workflow.
    5. In the ribbon, click Action and you should see in the Custom group as defined in .actions4 file.
      WaitForCustomEvent 12
    6. Create the following workflow with using the actions Set Workflow Status, Log to History List WaitForCustomEvent 13 

Creating a Mock External Application

This application will serve as a mock external system or application noted as “3” in the diagram above. This application will serve two purposes:

  • Self-hosted RESTful services that wraps the business logic of which the workflow can call into. You may to choose to host in IIS web server.
  • This business logic will make a call to publish a custom event notification to the running workflow instance using the SharePoint .NET Client Side Object Model.

Reference:
How to create Self-Host a Web API
http://www.asp.net/web-api/overview/hosting-aspnet-web-api/self-host-a-web-api

  1. Add New Project
  2. Select Console Application
  3. Right-click the Project > Manage NuGet Packages
  4. Install Microsoft ASP.NET Web API Self Host
  5. Add assembly references > browse C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\
    • Microsoft.SharePoint.Client.WorkflowServices
    • Microsoft.SharePoint.Client.Workflow
    • Microsoft.SharePoint.Client.Runtime
    • Create a class and method
  6. Create a business class with the method
    PublishCustomWorkflowEvent(string url, string listTitle, string documentTitle, string eventName, string eventArgs)
    {
      using (ClientContext ctx = new ClientContext(url))
      {
        ctx.Credentials = new NetworkCredential("\\ ", "");
        // Best practice: retrive credentials in a secured credentials store.
    
        Microsoft.SharePoint.Client.WorkflowServices.WorkflowServicesManager workflowServiceManager = new Microsoft.SharePoint.Client.WorkflowServices.WorkflowServicesManager(ctx, ctx.Web);
        var workflowInstanceService = workflowServiceManager.GetWorkflowInstanceService();
    
        List list = ctx.Web.Lists.GetByTitle(listTitle);
        int itemId = 1;
    
        CamlQuery query = new CamlQuery();
        query.ViewXml =@""
        + documentTitle
        + "";
    
        ctx.Load(list);
        ctx.ExecuteQuery();
    
        ListItemCollection listItems = list.GetItems(query);
        ctx.Load(listItems);
        ctx.ExecuteQuery();
        if (listItems.Count > 0)
          itemId = listItems[0].Id;
    
        var workflowInstances = workflowInstanceService.EnumerateInstancesForListItem(list.Id, itemId);
    
        ctx.Load(workflowInstances);
        ctx.ExecuteQuery();
    
        // Once we get the workflow Instance, we can get the instance properties as shown below. Any properties in Workflow Initiation form will also be available:
        if (workflowInstances.Count > 0)
        {
        foreach (WorkflowInstance instance in workflowInstances)
        {
          WorkflowStatus status = instance.Status;
          if (instance.Properties.Count > 0)
          {
            var itemUrl = instance.Properties["Microsoft.SharePoint.ActivationProperties.CurrentItemUrl"];
    
            Console.WriteLine("Internal Status: " + instance.Status);
            Console.WriteLine(" Item Url: " + itemUrl);
            Console.WriteLine(" Workflow User Status: " + instance.UserStatus);
            string userStatus = instance.UserStatus;
            var propertyValue = instance.Properties["Microsoft.SharePoint.ActivationProperties.ItemId"];
    
            workflowInstanceService.PublishCustomEvent(instance, eventName, eventArgs);
            Console.ForegroundColor = ConsoleColor.Magenta;
            Console.WriteLine("Event Args: " + eventArgs);
         }
        } // end foreach workflowInstances
      }
    }
    
    
  7. Create a RESTful method in a controller class inherited from the APIController.
    [HttpGet]
    public string DoSomeWork(string url, string listTitle, string documentTitle, string eventName)
    {
      string output = string.Emptyy;
      // DO SOME WORK
    
      // publish custom event to running workflow instance
      PublishCustomWorkflowEvent(url, listTitle, documentTitle, eventName, eventArgs);
     return output;</pre>
    }
    

Workflow Manager 1.0 Setup and Validation on a Development Environment

Sharing my approach and knowledge of setting up a SharePoint 2013 development server with Workflow Manager 1.0. There are many step by step guides on installing and configuring Workflow Manager 1.0; however, this is from a topology point of view as well as areas of validating the setup.

SharePoint Designer 2013 | Publishing 2013 Workflow Error

Using SharePoint Designer 2013, I create and publish a simple custom workflow (2013 platform). I get the following within the error message:

“There was no endpoint listening at net.pipe://localhost/SecurityTokenServiceApplication/appsts.svc that could accept the message.”

Background:

  • I am able to browse to http://localhost:32843/SecurityTokenServiceApplication/securitytoken.svc with no issues or errors showing.
  • I have installed Worfklow Manager (and update) on a WFE server in a 3 tier setup.
  • I am trying to publish this through a domain account which was not used to install, but is still local administrator and Site Collection administrator.
  • The net.pipe binding exists in IIS web site for SharePoint Web Services
  • Windows Server 2012, installed all WF updates, SP server updates, SP Designer update

Solution:

Windows Services -> Start the Net.Pipe Listener Adapter service

Service Description: Receives activation requests over the net.pipe protocol and passes them to the Windows Process Activation Service.

I just stumbled upon this service by associating the name “Net.Pipe” and the error message containing “There was no endpoint listening at net.pipe://…”

What is “net.pipe”?

netNamedPipeBinding binding, which provides cross-process communication on the same machine. Named pipes do not work across machines.”

Visual Studio 2012 SharePoint 2013 List and Content Type Designer: Hands-on Observations

After spending some time on developing a SP Hosted App, I would like to share my insights and observations with the new Office Developer tools for SharePoint 2013

Prerequisite: Web Platform Installer > Microsoft Office Developer Tools for Visual Studio 2012

Let’s walk through my observations from site columns, to content types and to list definitions.

Site Columns

  • There is no visual designer. Content types reference site columns and so having a site column designer would make much sense. It is unfortunate that one is absent.
  • Therefore, creating site columns is manual through the elements.xml file

VSContentTypeDesigner-1

Field Element Schema
http://msdn.microsoft.com/en-us/library/ms437580.aspx

Content Type

  • There is a new visual designerVSContentTypeDesigner-2VSContentTypeDesigner-3
  • Add existing OOTB site columns
  • Add existing custom site columns that were manually created.VSContentTypeDesigner-4
  • Remember, you cannot create custom site columns in the content type designer.
  • Limitation: Column ordering is manual through the elements.xml definition files. In other words, you cannot reorder site columns in the conten type designer.
  • Gotcha: Change in custom site column definition does not automatically reflect changes in content type. For example, changing site column name will break the referring content type.
    Therefore, you must remove the custom site column and then add updated site column.

List Definition and Instance

  • There is new visual designer
    Able to set List (template) name, url and description.
  • Content Types. Add existing OOTB content type or custom content type created in the VS projectVSContentTypeDesigner-5
  • Columns
    Add existing OOTB site columns or
    existing custom site columns in the VS project
    VSContentTypeDesigner-6Add list level columns manually
    VSContentTypeDesigner-7
  • Limitation: When creating a new custom column that are more complex in nature such as choice or person, there is no ability to configure the selectable choices. I would think you would have to revert to the xml files and fill in the rest of the xml manually. Having such a site column designer would have been very convenient.
  • When creating a list column, it automatically creates a list content type called “ListFieldsContentType” if one does not exist. This becomes the default. Any further site columns (OOTB or custom) added will be automatically added to this ListFieldsContentType content type.
    VSContentTypeDesigner-8
  • Note: Changes in content types referenced by the list definition are not automatically reflected. This is the same scenario mentioned above with site columns referenced by content types. So after you change a referenced content type, you must remove and then add back the updated content types to the list definition.
  • Set default content type so that the list’s ‘new’ button refers to the content type desired.
  • Limitation: List column ordering is manual through the xml definition files.
  • Not able to add predefined data rows in List Instance
    In ListInstance elements.xml, I added
    <DataRows>
    <Row>
    ….
    </Row>
    </DataRows>
    This resulted in a deployment error. Maybe I am missing something, but I was unsuccessful.
  • Views
    Able to specify which columns appear in the view and their order, row limit, read only, but nothing more than that. For example, no sorting ability, grouping, filtering, etc.
    VSContentTypeDesigner-9

After deploying to site collection:

VSContentTypeDesigner-10

Deployment Error: Failed to install app

Possible causes:

  • The xml schema files are malformed or have a syntax issue. Visual Studio can detect and highlight some of these in the Error pane.
  • A custom element definition is in conflict with an element already existing in the SharePoint farm.
    For example, deploying a list, content type or site column that has the same internal name as an existing artefact. Duplication error.

Troubleshooting:

The way I troubleshoot, is to remove snippets of xml definition and re-deploy to isolate trouble area.

I have looked in the 15 ULS Logs to find any detailed error messages and did not recognize anything helpful.

Conclusion:

The designers are a welcomed feature in Visual Studio 2012 for SharePoint developers. However, more can be achieved with site columns and handling changes to referenced elements. This is probably a large effort, since there are so many types of site columns with varying complexities such as ‘People and Groups’ and ‘Managed Metadata”. Nevertheless, it is one step better in getting through the xml hell.

Appreciate any comments and feedback.

References:

Walkthrough: Create a Site Column, Content Type, and List for SharePoint
http://msdn.microsoft.com/en-us/library/ee231593.aspx

Common SharePoint Web Part Errors

The following are some of the common web part errors that I just wanted to summarize and provide the general solution.

Error Message:

A Web Part or Web Form Control on this Page cannot be displayed or imported. The type could not be found or it is not registered as safe.

Image

OR

A Web Part or Web Form Control on this Page cannot be displayed or imported. The type DateTimeWebPart.DateTimeWebPart.DateTimeWebPart, DateTimeWebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2bfd9e5fd3b67b15 could not be found or it is not registered as safe.

OR

An error occurred when previewing the Web Part.

Ways to reproduce error

  • Preview web part by Site Settings > Web parts (Galleries) > Click web part list item; OR
  • Insert web part to a page; OR
  • View a page that previously inserted the web part.

The files in question

Image

1) .cs

Image

2) .webpart

Image

3) .spdata
(hidden – must ‘show all files’ at the Visual Studio project level)

Image

OR

Right Click <WebPart> Project item > Properties > Click Safe Control Entries

Image

4) Web.config
(IIS virtual directory, e.g. C:\inetpub\wwwroot\wss\VirtualDirectories\80)

The safe control entry is automated in deployment declared in the .spdata file.

<SafeControls>
<SafeControl Assembly=”DateTimeWebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2bfd9e5fd3b67b15″ Namespace=”DateTimeWebPart.DateTimeWebPart” TypeName=”*” Safe=”True” />
</SafeControls>

5) Assembly / DLL file missing  in the Global Assembly Cache for GAC deployment (c:\windows\assembly) or virtual directory bin folder in web app deployment.

Resolution

Make sure the Namespace and Type Name are consistent across all files where indicated. Also with matching case sensitivity.

Verify web.config file and assembly in GAC or virtual directory bin folder in post deployment.

Background

What does it mean by ‘type could not be found’? What is the type?

The type in question is the class inheriting from WebPart class. In this case, it is DateTimeWebPart.DateTimeWebPart.DateTimeWebPart. Excuse my naming convention. When the .NET run time is creating an instance of the web part, the run time can not find the type; either because the assembly is missing, inaccurately referenced or misnamed.

What does it mean by ‘Is not registered as safe’?

Given that the type can be found and the type is registered in the web.config in the <SafeControls> xml node.

The safe control entries mark a web control (instantiated in the web part) such that an untrusted user has access to the web control. Or another way to look at it is that the web application trusts the web control.