New version of SPClientSideDeployment adds support for folder-based file deployment and automatic folder creation

I have just released version 2.0 of SPClientSideDeployment with two major enhancements:

  • Folder-based file deployment – this allows you to define a local folder in the DeploymentSettings.xml file. All files under this folder (and its sub-folders) will be processed by the tool.
  • Automatic folder creation – all folders on the target path will now be automatically created by the Visual Studio command.

Download it now!

You can download the latest version of SPClientSideDeployment from the Visual Studio Gallery.

Folder-based file deployment

In previous versions, each file to be deployed needed to be declared individually in the DeploymentSettings.xml file. This can be cumbersome for large projects. In this release you can now use the Folder element to define a local folder to be deployed to SharePoint. All files under this folder (and all of its sub-folders) will be processed by the tool. The schema for this new element is very similar to the File element. Review the inline comment below for more details.

<?xml version="1.0" encoding="utf-8" ?>
<DeploymentSettings>
	<Files>
		<!-- Define local items to be deployed by using a combination of File and Folder elements. -->
		
		
		<File localPath="Script1.js">
			...
		</File>
		<File localPath="Script2.js">
			...
		</File>

		<!-- localPath: Required. Local path of the folder to deploy. Relative to the current project. Value should not start with '/'. Files within this folder and all of its sub-folders will be processed. -->
		<Folder localPath="Scripts">
			<Destinations>
				<!-- Same usage as Destination element for File. targetFileName is not supported when this element is being used for Folder. All files in the local folder will be deployed to the target location using the local file name. The local sub-folder structure will be automatically re-created at the target location. -->
				<Destination targetWeb="" targetFolder="Style Library"/>
			</Destinations>
			
			<!-- Same usage as Metadata element for File. The same metadata will be applied to all files within this folder. -->
			<Metadata>
				<Field name="ContentTypeId" value="0x01010007FF3057"/>
			</Metadata>
		</Folder>
	</Files>
</DeploymentSettings>

The sub-folder structure of the defined local folder will be automatically re-created at the target location. For example, given the Scripts folder and its content below:

      Scripts\utility.js

      Scripts\Search\search.js

and the definition in the DeploymentSettings.xml file:

		<Folder localPath="Scripts">
			<Destinations>
				<Destination targetFolder="Style Library/Intranet"/>
			</Destinations>
		</Folder>

The file utility.js will be deployed to the Style Library, under the Intranet folder. The file search.js will be deployed to the Style Library, under the Intranet/Search folder. The Intranet folder under the Style Library and its Search sub-folder will be created automatically.

Remember to republish your deployment package if you are planning to update your existing DeploymentSettings.xml to use the new Folder element. This is because the DeployFiles.ps1 has been updated to support the new element.

Automatic folder creation

In previous versions, all folders on the target deployment path (specified via the targetFolder attribute) must exist at the target location when using the Visual Studio command. This however was not a requirement when using the PowerShell deployment script generated by the tool (as the script automatically creates any non-existing folder). This release brings the same capability to the Visual Studio command. Any non-existing folder at the target location will now be created automatically by the Visual Studio command, in the same manner as the PowerShell deployment script.

Conclusion

This release brings two major enhancements that aim to simplify your deployment configuration. I hope you find them useful – and as always, would love to hear from you with feedback and suggestion.

 

Advertisements
Posted in SharePoint, SPClientSideDeployment | 1 Comment

CRMQuickDeploy 2.6 adds RibbonDiff deployment from Visual Studio

Rather than storing the ZIP solution in source control, some project teams choose to store the source code of each individual component instead, for example by using the SolutionPackager tool. This allow team members to easily track changes to components at check-in, or to understand how a component was changed over time.

One type of component that may be stored in source control in this way is the RibbonDiff XML for entities. The process of modifying and deploying RibbonDiff is pretty cumbersome though. Natively it involves exporting a solution, modifying the XML and reimporting the solution. The popular Ribbon Workbench automates this process and provides a great UI for editing the XML, but it is rather slow for making small changes – and it also does not help in storing the source code for the RibbonDiff.

CRMQuickDeploy 2.6 adds a feature that allows you to quickly deploy RibbonDiff XML from Visual Studio to CRM for an entity.

1 Deploy Ribbon (1)

Download it now!

You can download the latest version of CRMQuickDeploy from the Visual Studio Gallery.

Accessing the command

This command is accessible by right-clicking on the code editor of the RibbonDiff.xml file, or by the Alt+Q, F shortcut key.

2 Context Menu

Note that this is the same command for deploying web resource. The command determines the current file in the code editor to be a RibbonDiff if its file name is RibbonDiff.xml, and if it is not located under the WebResources folder of the project.

Therefore, to use this command for RibbonDiff deployment, ensure that:

  • The file is named RibbonDiff.xml
  • The file is not located under the WebResources folder of the project, or one of its sub-folders
  • The file is contained in an immediate folder with the name of the target entity (see below)

Specifying target entity for RibbonDiff

The RibbonDiff schema does not contain information about the target entity. The command therefore uses the name of the immediate parent folder of the RibbonDiff file to determine the target entity. If the target entity is new_staff for example, place the RibbonDiff file for this entity directly under a folder named new_staff.

Posted in CRM, CRMQuickDeploy | Leave a comment

New deployment context menu in SPClientSideDeployment 1.2

I have just released version 1.2 of SPClientSideDeployment. This version adds a “Deploy to SharePoint” context menu to files and folders in the Solution Explorer.

1 Context Menu

With this addition, you can now selectively deploy files that you typically don’t open in the code editor, such as images. For folders, this command deploys all files within the selected folder(s) and their sub-folders. Multiple selection of files and folders is supported.

Note that the command is not available for code files (i.e. .CS or .VB files). Selecting files and folders across multiple projects is not supported.

Download it now!

You can download the latest version of SPClientSideDeployment from the Visual Studio Gallery.

Posted in SharePoint, SPClientSideDeployment | Leave a comment

Getting entity type code from CRM UI for an entity

Entity type code for custom entities may be different across environments. Sometime you may need to work out the entity name from an entity type code, for example when CRM throws an error message at you.

Here is a quick way to confirm the entity type code for an entity using the CRM UI:

  1. Open a record of the entity type you’d like to check
  2. Go to the Customize tab and click on Form to launch the form editor
    1 Customise Menu_2
  3. Notice the URL of the form editor. This URL has an etc query string parameter. This is the entity type code for the entity.
    2 Url

The above steps are for CRM 2011 but should also work for later versions of CRM.

This method works best when you have some gut feels of which entity a given code may be for, and of course if you can access a record of the suspecting entity. There are other methods of retrieving entity type codes, such as querying the CRM database, or invoking the RetrieveAllEntitiesRequest against the web service. These other methods however may not be available to you, particularly in environments that are higher than DEV.

Posted in CRM | Leave a comment

New version of CRMQuickDeploy adds tighter integration with CRM Developer Toolkit and productivity shortcut

I have released version 2.5 of CRMQuickDeploy (previously known as BNH.CRM.Debugging). This version adds tighter integration with CRM Developer Toolkit projects and a new productivity shortcut.

Download it now!

You can download the latest version of CRMQuickDeploy from the Visual Studio Gallery.

Tighter integration with CRM Developer Toolkit

For web resources, the extension now checks if the project is the CRM Developer Toolkit package project; and if so will use the Description, Display Name and Unique Name properties of the file to deploy the web resource.

1 File Properties

If the project is not a CRM Developer Toolkit package project, then the extension falls back to using the location of the file within the project to determine its unique name in CRM.

New productivity shortcut

A new keyboard shortcut (Alt + Q, F) and context menu has been added to the code editor for web resources.

2 Editor Context Menu

This command deploys the file that is currently opened in the editor to CRM.

Note that this command will only be enabled and appear in the editor context menu for files that are recognised as deployable web resources. This means the file must be located under the WebResources folder of the project, and must be one of the web resource types (e.g. JavaScript, CSS, HTML, XML, etc).

Changes to shortcut keys in previous versions

Previous versions of the extension uses shortcut keys beginning with Alt + D by default. In this version all shortcut keys have been changed to begin with Alt + Q to avoid conflict with Visual Studio’s OOTB commands.

Note that you can edit the shortcut key for all commands in Visual Studio by going to: Tools \ Customize \ Keyboard (on the Toolbars tab).

The complete list of shortcut keys in this version is as follow:

  • Alt + Q, B: Deploy assemblies to Bin Folder
  • Alt + Q, D: Deploy assembly to CRM Database
  • Alt + Q, G: Deploy assemblies to GAC
  • Alt + Q, W: Deploy web resources
  • Alt + Q, F: Deploy web resource in current editor to CRM
  • Alt + Q, A: Attach to Async Service
  • Alt + Q, I: Attach to IIS
  • Alt + Q, S: Attach to Sandbox Worker
Posted in CRM, CRMQuickDeploy | Leave a comment

Correcting available lookup views when restricting lookup types via JavaScript in CRM

Although unsupported, in CRM you can use JavaScript to restrict the available lookup types for a lookup field on the form. For example, on the Email form I’d like to restrict the Regarding field to be able to lookup Client and Incident records only. Below is the code that’d (partially) achieve this. Again, please note that this is unsupported.

//The code below is for CRM 2011. In CRM 2013 (and possibly 2015), 
//the ID for DOM elements that represent fields are suffixed with '_i'.
//Therefore, the ID below in CRM 2013 would be 'regardingobjectid_i'.

var regardingField = document.getElementById("regardingobjectid");
regardingField.setAttribute("lookuptypes", "2,112");

2 and 112 are the object type codes for Client and Incident. Below is the result of the above code.

1 Lookup Types

While this looks like it does the trick, something is wrong if you look closely. The list of available lookup views is not correct. It is still listing the available lookup views for the Account entity, not the Client entity. Note that this would only occur if you launch the lookup dialog, and the lookup field on the form does not currently have a value, e.g. when creating a brand new Email.

The lookup element has a number of attributes that control its behaviour. One of these is the defaulttype attribute, and it seems that the dialog is listing the available lookup views for the defaulttype by default. So to fix this, we need to set defaulttype to one of our allowable lookup types. This can be achieved with the additional line of code below.

regardingObject.setAttribute("defaulttype", "2");

Below is the result of this additional line.

2 Lookup Types

OK this looks better, but there is however another issue. In the dialog, if you change the lookup entity to something else (e.g. Incident), and then switch back to the default type (i.e. Client in this example), you will find that a lookup view is not selected by default. Furthermore, if you go ahead and pick a lookup view and select a record and click OK, then you will receive a JavaScript error from CRM.

To correct this issue, we need to set another attribute for the the lookup DOM element, namely defaultviewid. Below is the additional line of code.

regardingObject.setAttribute("defaultviewid", "");

So in conclusion, to avoid issues when restricting lookup types, the complete code you should use is as below.

var regardingObject = document.getElementById("regardingobjectid");
regardingObject.setAttribute("defaulttype", "2");
regardingObject.setAttribute("defaultviewid", "");
regardingObject.setAttribute("lookuptypes", "2,112");

This was observed on CRM 2011 with UR 18.

Posted in CRM | Leave a comment

Programmatically setting toolbar type for list view web part [SharePoint]

If you ever tried to programmatically set the toolbar type for a list view web part then you will find that this is not at all straightforward. There are actually quite a lot of posts about this on the net, and they all involve using reflection to invoke various private methods. The simplest way I have found is to invoke the SetToolbarType private method of the SPView class. Using ILSpy you can see that there are two overloads for this method, one takes a uint and the other takes a string for the toolbar type. The first overload translates the uint to a string value and invokes the second overload.

For a recent project we used PowerShell to add the list view web part to a rich text field on a page and then turn off the toolbar. Below is the complete script to do this – please review the inline comments.

###Declare a custom enum. The names of the enum members match the string values that the SetToolbarType method expects.
Add-Type -TypeDefinition @"
    public enum ToolbarType
    {
        Standard,
        FreeForm,
        None,
        ShowToolbar
    }   
"@

###These functions are required as we are adding the web part to a rich text field, rather than to a web part zone.
Function RegisterWebPartForPageRendering([Microsoft.SharePoint.WebPartPages.SPLimitedWebPartManager] $webPartManager, [System.Web.UI.WebControls.WebParts.WebPart] $webPart)
{
    $WEB_PART_ZONE_ID = "wpz";

    $webPartStorageKey = [Guid]::NewGuid()
    $webPart.ID = GetWebPartIDFromStorageKey $webPartStorageKey

    $webPartManager.AddWebPart($webPart, $WEB_PART_ZONE_ID, 0);
    return GetHtmlForWebPart $webPartStorageKey
}

Function GetWebPartIDFromStorageKey([Guid] $storageKey)
{
    return "g_" + $storageKey.ToString().Replace('-', '_');
}

Function GetHtmlForWebPart([Guid] $webPartStorageKey)
{
    return [String]::Format(@"

<div class='ms-rtestate-read ms-rte-wpbox' contentEditable='false' unselectable='on'>

<div class='ms-rtestate-notify ms-rtestate-read {0}' id='div_{0}' unselectable='on'></div>


<div style='display:none' id='vid_{0}'unselectable='on'></div>

</div>

"@, $webPartStorageKey.ToString());
}

###This is the method that does the magic. It is invoked by the main script below.
Function SetViewToolbar([Microsoft.SharePoint.SPView] $view, [ToolbarType] $toolbarType)
{
    $setToolbarTypeParameterTypes = [uint32]
    $setToolbarTypeMethod = $view.GetType().GetMethod("SetToolbarType", [System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic, $null, $setToolbarTypeParameterTypes, $null)
    $setToolbarParameters = [uint32] 1
    
    $setToolbarTypeMethod.Invoke($view, $setToolbarParameters)
    $view.Update()
}


###Get the web's landing page. The web part will be added to this page.
$web = Get-SPWeb "http://myServer/myWeb"
$publishingWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($web)
$defaultPage = $publishingWeb.DefaultPage

###Check out the page so we can edit it
$defaultPage.CheckOut()

###Get the page's web part manager
$defaultPageItem = $defaultPage.Item
$webPartManager = $defaultPageItem.File.GetLimitedWebPartManager([System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared)

###Delete all the web parts currently on the page
$allWebParts = $webPartManager.WebParts | Select $_
ForEach ($webPart in $allWebParts)
{
    $webPartManager.DeleteWebPart($webPart);
}

###Instantiate a new list view web part
$targetList = $web.Lists.TryGetList("My List")
$listViewWebPart = New-Object Microsoft.SharePoint.WebPartPages.XsltListViewWebPart
$listViewWebPart.ListName = $targetList.ID.ToString("B")
$listViewWebPart.ViewGuid = $targetList.Views["My View"].ID.ToString("B")
$listViewWebPart.Title = "My List View Web Part"

###Add the web part to the rich text field
$content = RegisterWebPartForPageRendering $webPartManager $listViewWebPart
$defaultPageItem["PublishingPageContent"] = $content

###As we are adding a new web part to be page, be sure to call Update on the page before 
###accessing the View property of the web part, otherwise it will be null.
$defaultPageItem.Update()

###Access the View used by the list view web part and set the toolbar type
$view = $listViewWebPart.View
SetViewToolbar $view None

###All done, update the page and check in.
$defaultPageItem.Update()
$defaultPage.CheckIn([String]::Empty, [Microsoft.SharePoint.SPCheckinType]::MinorCheckIn)
Posted in SharePoint 2013 | 1 Comment