Monday, December 30, 2013

_spBodyOnLoadFunctionNames.push and ExecuteOrDelayUntilScriptLoaded

SharePoint JavaScript Client Object Model: How to Use
 
_spBodyOnLoadFunctionNames.push
 
ExecuteOrDelayUntilScriptLoaded
 
SP.ClientRuntimeContext.executeQueryAsync
 


This is a blog that discusses when and how to use these important SharePoint Javascript calls.

1. _spBodyOnLoadFunctionNames.push() is SharePoint's version of jQuery's $(document).ready() or $(function(){});

It is better to use SharePoint's version than using jQuery's version.

2. _spBodyOnLoadFunctionNames.push() takes the function names as string,

For example, for self-defined function use

_spBodyOnLoadFunctionNames.push('Company.Utility.hideText');

Since the function name passed as string, it is not possible to pass parameters to the function directly. The parameters have to be passed inside the function itself.

3. If your Javascript use SharePoint Client Object Model, you need to use ExecuteOrDelayUntilScriptLoaded to delay your Client Object calls after SharePoint's core Javascript library is loaded. The function name is passed directly as parameter to the function.

ExecuteOrDelayUntilScriptLoaded(Company.Utility.showData"sp.js")

4. To pass parameters to the function calls deplayed by ExecuteOrDelayUntilScriptLoaded.

ExecuteOrDelayUntilScriptLoaded(function () { Company.ReportListView.initListView("<%=ReportName %>") }, "sp.js")

This code also shows the technique to pass server side variable value to the client script.

5. Usually you will need these two functions together to first delay the run of your script after the page is loaded and delay the run of your script after the core SharePoint JavaScript library is loaded.

<script type="text/javascript">
    if (ExecuteOrDelayUntilScriptLoaded && _spBodyOnLoadFunctionNames) {
        _spBodyOnLoadFunctionNames.push(ExecuteOrDelayUntilScriptLoaded(function () { Compnay.ReportListView.initListView("<%=ReportName %>") }, "sp.js"));
    }
</script>

6. To pass parameter to the success function of SP.ClientRuntimeContext.executeQueryAsync

    function initListView(reportName) {
        var context = SP.ClientContext.get_current();
        ... 
        context.load(items);
 
        var sender = { "items": items, "reportName": reportName };
 
        context.executeQueryAsync(function () { succeed(sender); }, failed);
    }
 
    function succeed(sender, args) {
 
         if (sender.items) {
 
            var htmlOutput = "";
            var count = sender.items.get_count();
 
            ...

 

Friday, December 13, 2013


An Easier Way to Provision Publishing Page in SharePoint Solution


When you use SharePoint as a full-fledged publishing portal to do content management, there are scenarios that requires custom page layout.
For example , every article page of your portal requires a sub-title area that end users need to add or edit when they provide the content. The manual steps to create a custom page layout is
1.       Create custom content type that inherits from a OOTB page layout content type. This custom content type will have a new field called “Sub Title”.

2.       Create a page layout that uses the custom content type and then using SharePoint Designer to design the UI. During this process, the “Sub Title” field is added to the UI.

3.       Create the content page in “pages” library that use the custom page layout created in step2.
When creating a SharePoint solution in Visual Studio 2012 to create publishing portal, we tends to follow the same steps to create a publishing page: Create a custom content type, bind the content type to pages library, create custom page layout, and create the page that uses the custom content type and page layout.
However if you think it twice, you will find these are not necessary steps to follow.

First, most pages provisioned though custom SharePoint solution will not have custom content from end users. The layout and contents of the pages are pre-defined in implementation. This means there is no need to create a custom field with a custom content type. The new page could just use any existing page layout template such as “Article Page”.
Second, since we developer have control over the design of the page layout using HTML and XML, we don’t even need to use any field from the layout content type. All the content and layout could be done with HTML, web part zone and web parts.
So the easy way to do this is just two steps
1.       Create the custom page layout (with web part zones).

2.       Create the content page that uses the custom page layout (with web part that use the web part zone).

The content page uses OOTB page layout content type "Article Page"
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="Pages_" List="101" Url="Pages" SetupPath="SiteTemplates\SPS\">
    <File Name="home.aspx" Url="home.aspx" Path="default.aspx" Type="GhostableInLibrary" IgnoreIfAlreadyExists="FALSE" >
      <Property Name="Title" Value="Home" />
      <Property Name="PublishingPageLayout" Value="~SiteCollection/_catalogs/masterpage/HomePageLayout.aspx, My Homepage Layout" />
      <Property Name="ContentType" Value="Article Page" />
      <Property Name="ContentTypeId" Value="0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF3900242457EFB8B24247815D688C526CD44D00034BC11D88051947AB4A4F809BB04726" />
      <AllUsersWebPart WebPartZoneID="TopLeft" WebPartOrder="0">
        <![CDATA[
    ......
 ]]>
      </AllUsersWebPart>
    </File>
  </Module>
</Elements>

Saturday, June 15, 2013

Create PerformancePoint Content List Programmatically

Create PerformancePoint Content List Programmatically


During one of PerformancePoint project, we need to create a custom PerformancePoint Content list to save our PerformancePoint reports.

First as usual I created the list using XML schema and everything works fine until I deployed it to staging environment.

In staging environment, if I try to create a report using Dashboard designer, I will get an error as

"You do not have permission to run a query using this report."

For saved report in the list, when try to display the report, there is an error

"The report no longer exists or you do not have permission to view it."

In the SharePoint event log, there is

06/14/2013 16:39:28.96  w3wp.exe (0x2468)                        0x182C SharePoint Foundation          Logging Correlation Data       xmnv Medium   Name=Request (GET:http://server1000:80/pps1/_layouts/ppswebparts/ReportViewPreview.aspx?SiteLocation=http%3a%2f%2fserver1000%2fpps1%2fxyz&ItemLocation=%2fpps1%2fxyz%2fLists%2fSavedReports%2f3_.000) edeeac52-ede6-4a34-b7d7-73ec6ac14012
06/14/2013 16:39:28.98  w3wp.exe (0x2468)                        0x182C SharePoint Foundation          Logging Correlation Data       xmnv Medium   Site=/pps1 edeeac52-ede6-4a34-b7d7-73ec6ac14012
06/14/2013 16:39:28.98  w3wp.exe (0x2468)                        0x182C SharePoint Foundation          Topology                       e5mc Medium   WcfSendRequest: RemoteAddress: 'http://ppsdev06:32843/3fc88cafe222497aa89ab77622ed491b/PerformancePointService.svc' Channel: 'Microsoft.PerformancePoint.Scorecards.IBIMonitoringServiceApplication' Action: 'http://www.microsoft.com/performancepoint/scorecards/IBIMonitoringServiceApplication/GetAnalyticReportView' MessageId: 'urn:uuid:6aa61912-71a0-4feb-895f-b34743b23cd4' edeeac52-ede6-4a34-b7d7-73ec6ac14012
06/14/2013 16:39:28.99  w3wp.exe (0x2468)                        0x182C PerformancePoint Service       PerformancePoint Services      ef8z Critical An exception occurred while rendering a Web control. The following diagnostic information might help to determine the cause of this problem:  Microsoft.PerformancePoint.Scorecards.BpmException: The report no longer exists or you do not have permission to view it.  PerformancePoint Services error code 20700. edeeac52-ede6-4a34-b7d7-73ec6ac14012
06/14/2013 16:39:29.02  w3wp.exe (0x2468)                        0x182C SharePoint Foundation          Topology                       e5mc Medium   WcfSendRequest: RemoteAddress: 'http://ppsdev06:32843/3fc88cafe222497aa89ab77622ed491b/PerformancePointService.svc' Channel: 'Microsoft.PerformancePoint.Scorecards.IBIMonitoringServiceApplication' Action: 'http://www.microsoft.com/performancepoint/scorecards/IBIMonitoringServiceApplication/GetSettingValue' MessageId: 'urn:uuid:a9e31515-75c1-4df5-9f43-a98aafb52ac0' edeeac52-ede6-4a34-b7d7-73ec6ac14012


In Windows Event Viewer, there  is error

"An exception occurred while rendering a Web control. The following diagnostic information might help to determine the cause of this problem: Microsoft.PerformancePoint.Scorecards.BpmException: The report no longer exists or you do not have permission to view it. PerformancePoint Services error code 20700."


The solution:

The solution is to use SharePoint object model to create the PerformancePoint Content List and don't use the XML schema.

I think the reason is that when PerformancePoint Content List is created there is some OOTB code runs and set the list to use unattended service account to call the web service. When everything runs on the same machine, it just works fine. When PerformancePoint service 'PerformancePointService.svc' runs on a different server, the list created from XML schema cannot use the proper account to call the service on a different machine.

Thursday, June 6, 2013

Master Page Url Tokens in SharePoint

Master Page Url Tokens in SharePoint
 

In SharePoint you reference master page in pages by url as


<%@ Page language="C#" MasterPageFile="...."

You can have as many master pages you want and reference them using static tokens "~site/.../master1.master" and "~sitecollection/.../master2.master"


SharePoint also supports two dynamic tokens to reference master pages.

~masterurl/default.master
~masterurl/custom.master

How to use these dynamic token can be confusing.

Basically when you start designing a portal site, you first make a decision if you want to use the static token or dynamic token. If you can use static token, you don't need worry about the dynamic tokens.

However in many situations this is not the case.

1. All OOTB application/setting pages use dynamic token. If you care about customizing the OOTB application pages, you need to use dynamic tokens.

2. All publishing portal pages which use page payout uses dynamic token. The only way to change them is to leverage dynamic tokens.

To leverage dynamic tokens, you can set SPWeb's property in code as




sysMasterUrl = SPUrlUtility.CombineUrl(siteCollection.ServerRelativeUrl, "_catalogs/masterpage/" + sysMasterUrl);
siteMasterUrl = SPUrlUtility.CombineUrl(siteCollection.ServerRelativeUrl, "_catalogs/masterpage/" + siteMasterUrl);
foreach (SPWeb site in siteCollection.AllWebs)
    {
            site.MasterUrl = sysMasterUrl;
            site.CustomMasterUrl = siteMasterUrl;
            site.Update();
    }

Dynamic tokens:
  • ~masterurl/default.master – The page references the master page file that is stored in the MasterUrl property.
  • ~masterurl/custom.master – The page references the master page file that is stored in the CustomMasterUrl property. 
 
The code will change the url of the dynmaic tokens.

The publishing portal site also provides UI to let user to change two master pages "Site Master Page" and "System Master Page". At first sight, you may think that "Site Master Page" is referring token "~masterurl/default.master " and "System Master Page" is referring token "~masterurl/custom.master".

Actually it is the opposite,

"Site Master Page" is referring token ~masterurl/custom.master
"System Master Page" is referring token "~masterurl/default.master


So in a publishing portal, if you changed the "custom.master (CustomMasterUrl)" by code or by UI, you changed all publishing pages's master page (pages under Pages library and built using page layout)

If you changed the "default.master (MasterUrl)" by code or by UI, you changed all OOTB application pages's master page.

Use Master Page on Application Page

Refer to this MSDN article 
http://msdn.microsoft.com/en-us/library/ee537530(v=office.14).aspx

SharePoint 2010 supports using DynamicMasterPageFile with the dynamic tokens

~masterurl/default.master
~masterurl/custom.master


However there are situations that you want to reference static master page from custom application page. The only way to do this is to use the old "MasterPageFile" and reference a master page in the same location as the application page.

For example, if the application is at /_layouts/myCompany/myapplication.aspx, then the master page must be at /_layouts/myCompany/mymasterpage.master

and reference it as

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="myapp1.aspx.cs" Inherits="...." MasterPageFile="mymasterpage.master" %>

If the master page is at any other location such as in the master page gallary, any attempt to try something like

MasterPageFile="~sitecollection/_catalogs/masterpage/mymasterpage.master"

or just

MasterPageFile="/_catalogs/masterpage/mymasterpage.master"

will result in errors like

System.Web.HttpException: The file '/_layouts/mycompany.Portal/~sitecollection/_catalogs/masterpage/mymasterpage.master' does not exist.    at System.Web.UI.Util.CheckVirtualFileExists(VirtualPath virtualPath)     at System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile)     at System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile)     at System.Web.UI.BaseTemplateParser.GetReferencedType(VirtualPath virtualPath, Boolean allowNoCompile)     at System.Web.UI.PageParser.ProcessMainDirectiveAttribute(String deviceName, String name, String value, I... 9a0f3bd4-6f73-4d3d-a25d-987cec6180e1

or

System.Web.HttpException: The referenced file '/_catalogs/masterpage/mymasterpage.master' is not allowed on this page. at System.Web.UI.TemplateParser.ProcessError(String message) at System.Web.UI.BaseTemplateParser.GetReferencedType(VirtualPath virtualPath, Boolean allowNoCompile) at System.Web.UI.PageParser.ProcessMainDirectiveAttribute(String deviceName, String name, String value, IDictionary parseData) at System.Web.UI.TemplateParser.ProcessMainDirective(IDictionary mainDirective) 3146ae16-c20e-442f-9aac-90fd9cdd0597

Reference:
http://msdn.microsoft.com/en-us/library/ms476046(v=office.12).aspx

 

Tuesday, June 4, 2013

Use Site Url in SharePoint MasterPage

Use Site Url in SharePoint
 
 
There are several ways to reference site collection or site url in masterpage, layout page, application page and web parts.


1. Token: ~sitecollection ~site

These tokens only works with SharePoint server side controls. They do not work with ASP.NET control or HTML control.

2. SharePoint Server Token <% $SPUrl:~sitecollection/...%>

This token is only available for SharePoint Office Server not the SharePoint Foundation Server and it only works with a few SharePoint server controls.

If it doesn't work, you can use asp.net letral control to work around as

<script type="text/javascript" src='<asp:Literal runat="server" Text="<% $SPUrl:~Site/appBin/js/jquery.min.js %>" />'></script>

3. Emedded Code: <%=SPContext.Current.Site.ServerRelativeUrl %>

You can use the embedded code any where in application page and web parts but don't use it in master page and page layout even though they seem work, because master page and page layout can be customized. The embedded code is only allowed in the uncustomized pages.

4. SharePoint Control: <SharePoint:ProjectProperty Property="Url" runat="server"/>

You can use the value returned by this control as control attribute but this is more like an hack, but it works.

If you don't want to use it directly in attribute, you can use asp.net leteral control like this

<asp:literal runat=”server” Text=”&lt;link href=’”/>
 <SharePoint:ProjectProperty Property=”SiteUrl” runat=”server” />
 <asp:literal runat=”server” Text=”/Style Library/My Branding/MyStyles.css’ rel=’stylesheet’ type=’text/css’/&gt;”/>

 

Here is when to use which option with different controls

1. <SharePoint:ScriptLink>
The only way works for ScripLink is the token ~sitecollection

<SharePoint:ScriptLink ID="ScriptLink2" language="javascript" name="~sitecollection/_layouts/TestScript1.js" OnDemand="true" runat="server"/>

2. <Script>

Use ScriptLink to include JavaScript in SharePoint. If you have to use <Script>, then this usage will work

<script src='<SharePoint:ProjectProperty ID="ProjectProperty2" Property="Url" runat="server"/>/_layouts/TestScript4.js'></script>

3. <SharePoint:CssRegistration>

The only way works for ScripLink is the SharePoint Office Server token <% $SPUrl:~sitecollection %>

<SharePoint:CssRegistration ID="CssRegistration3" Name="<% $SPUrl:~sitecollection/_layouts/TestStyle2.css %>" After="corev4.css" runat="server"/>
 
4. <Link>

For link, try this first
 
<link rel="stylesheet" type="text/css" href="<% $SPUrl:~sitecollection/_layouts/TestStyle3.css %>">

If it doesn't work, try

<link rel="stylesheet" type="text/css" href="<SharePoint:ProjectProperty ID="ProjectProperty22" Property="SiteUrl" runat="server"/>Style%20Library/test.css"/>

5. <img>

<img src='<SharePoint:ProjectProperty ID="ProjectProperty22" Property="SiteUrl" runat="server"/>/_layouts/SiteUrlTest/blog3.png' />

Conclusion:

When you need to reference site collection url such as /sites/hr/..., try the token "~sitecollection" first. If it doesn't work, try the SharePoint Office Server token "<% $SPUrl:~sitecollection/...%>".

As last resort, try the control <SharePoint:ProjectProperty Property="Url" runat="server"/> as control attribute value or combine it usage with literal control.

Friday, May 31, 2013

Save PerformancePoint Analytic Reports to SharePoint

Save PerformancePoint Analytic Reports to SharePoint


These are the steps of how to save a "navigated" PerformancePoint Analytic Reports as a custom view into SharePoint programmatically and reference it later .

1. Get the report Id from the client side.

When a PerformancePoint Analytic Report is "navigated" from the default view, there is a custom report created with a newly assigned ID. By referencing this new ID, you can save the custom report into SharePoint.

From JavaScript:

    var webPartRecords = PPSMA.ClientConnectionManager.get_instance().get_connectionManagerRecord().WebPartRecords;

The returned objec collection "webPartRecords" contains object "webPartRecord". This object has "ClientId" which you can use to locate the PPS web part on page and "recordId" which you can use to save the report. The recordId is retrieved from the ViewState F775B8BE98A540C2AB08B34D53460E4B.

var lastReportId = wP.ViewState["F775B8BE98A540C2AB08B34D53460E4B"];

2. Once you have the reportId, pass it to the server side code and save the report.

ReportView report = BIMonitoringServiceApplicationProxy.Default.GetAnalyticReportView(new RepositoryLocation(new Guid(reportId)));
ReportView newReport = SPDataStore.GlobalDataStore.CreateReportView(listUrl, report);

Tuesday, May 14, 2013

Download Item Attachment and Upload it To Document Library

Download List Item Attachment and Upload it To Document Library
(with SharePoint Server Object Model and Client Object Model)

Purpose:

Migrate file attachments of SharePoint list item to SharePoint document library on the same server (Server Object Model) or on different servers (Client Object Model).

Server Object Model:

Using server object model, the code is relatively easy. The sample code assume there is one attachment file per list item.

        private void MigrateFile(SPWeb fromWeb, SPWeb toWeb, string fromListTitle, string toListTitle)
        {
            SPList fromList = fromWeb.Lists.TryGetList(fromListTitle);
            SPList toList = toWeb.Lists.TryGetList(toListTitle);
 
            if (fromList != null && toList != null)
            {
                foreach (SPListItem fromItem in fromList.Items)
                {  
                    string fromFileName = fromItem.Attachments[0];
                    SPFile fromFile = fromWeb.GetFile(fromItem.Attachments.UrlPrefix + fromFileName);
 
                    string toFileName = toList.RootFolder.ServerRelativeUrl + "/" + fromItem.Title + ".xml";
                    fromFile.CopyTo(toFileName, true);
                }
            }
        }

Client Object Model:

Using client object model you can migrate file between servers remotely. It is more flexible than server side object model but a little bit more difficult to write. For each sample code, you can easily write more code to copy the properties of the file too.

                ClientContext fromContext = new ClientContext("http://from.server.com");
                ClientContext toContext = new ClientContext("http://to.server.com");
 
                Web fromWeb = fromContext.Site.OpenWebById(fromWebInfo.Id);
                List fromList = fromWeb.Lists.GetById([listID]); //your own ID here
 
                // find the attachments folder of the list
                fromContext.Load(fromList, l => l.RootFolder.Folders.Where(f => f.Name == "Attachments"));
                fromContext.ExecuteQuery();
 
                if (fromList.RootFolder.Folders.Count > 0)
                {
                    // there is only one Attachments folder
                    Folder attachmentFolder = fromList.RootFolder.Folders[0];
 
                    fromContext.Load(attachmentFolder, f => f.Folders);
                    fromContext.ExecuteQuery();
 
                    foreach (Folder itemFolder in attachmentFolder.Folders)
                    {
                        FileCollection files = itemFolder.Files;
                        fromContext.Load(files);
                        fromContext.ExecuteQuery();
 
                        // assume there should be only one file in the special case
                        // Loop throught each file if there more than one
                        if (files.Count > 0)
                        {
                            Microsoft.SharePoint.Client.File file = files[0];
 
                            //download
                            FileInformation fromFileInfo = File.OpenBinaryDirect(fromContext, file.ServerRelativeUrl);
 
                            string fileUrl = "[ServerRelativeUrlOnTargetServer] + [filename.extension]"// your code here
 
                            //upload
                            File.SaveBinaryDirect(toContext, fileUrl, fromFileInfo.Stream, true);
                        }
                    }
                }

Friday, April 19, 2013

CKS - Dev for VS 2012 Auto GAC Not Work

CKS - Dev for VS 2012 Auto GAC Not Work

Solution:

Use "CKS - Development Tools Edition (Server)" instead.


Friday, April 12, 2013

BIMonitoringAuthoringServiceProxy, BIMonitoringServiceApplicationProxy and SPDataStore

BIMonitoringAuthoringServiceProxy, BIMonitoringServiceApplicationProxy and SPDataStore


To do custom development against SharePoint 2010 PerformancePoint services, there are three sets of API you can use.

1. BIMonitoringAuthoringServiceProxy
2. BIMonitoringServiceApplicationProxy
3. SPDataStore

1. BIMonitoringAuthoringServiceProxy

This one is the least documented but the most useful one. According to http://msdn.microsoft.com/en-us/library/ee556849(v=office.14).aspx , BIMonitoringAuthoringServiceProxy is an internal class that shouldn't be used.

Actually BIMonitoringAuthoringServiceProxy is a public class and according to book such as Microsoft SharePoint 2010 PerformancePoint Services Unleashed, this is the API should be used when program against PerformancePoint servcies.

The is the API that can create and reretrieve all of the PerformancePoint objects through web servcies calls. SPDataStore API can do the extactly same things too but its calls are not remote calls and must be made on the same the server that PerformancePoint service is deployed.

This is an important difference, since PerformancePoint service is not necessarily deployed to the web front end server where the application will run. PerformancePoint service could run on an application server which is different from the WFE. In this case, your custom BI applications which could be an application page, web parts, or feature activation which usually run from WFE will not be able to use SPDataSource API. For this reason, only BIMonitoringAuthoringServiceProxy should be used to make reliable calls to PerformancePoint servcie.

The syntax to use BIMonitoringAuthoringServiceProxy is

string webServiceUrl = "/_vti_bin/pps/PPSAuthoringService.asmx";
IBIMonitoringAuthoring biService = BIMonitoringAuthoringServiceProxy.CreateInstance(siteUrl + webServiceUrl);
biService.CreateDataSource(SiteServerRelativeUrl + connectionListUrl, dataSource);
CreateInstance returns object of type IBIMonitoringAuthoring. However if you search for IBIMonitoringAuthoring, you won't find any documentation about it. Since it implements IBIMonitoringStore, you can find the API documentation at
http://msdn.microsoft.com/en-us/library/microsoft.performancepoint.scorecards.ibimonitoringstore_members.aspx

2. BIMonitoringServiceApplicationProxy

BIMonitoringServiceApplicationProxy is similiar to BIMonitoringAuthoringServiceProxy as a web service API but unlike BIMonitoringAuthoringServiceProxy, BIMonitoringServiceApplicationProxy is well documented by MSDN. It seems this API is the recommended API to use by MS but it lacks many of the functionalities of BIMonitoringAuthoringServiceProxy.

Also BIMonitoringServiceApplicationProxy requires running in the context of SharePoint such as running from a SharePoint page, if you use BIMonitoringServiceApplicationProxy from a console app without SharePoint context, you will get error "The SharePoint Service context is not known".

3. SPDataStore

As described above, this API is a server side object model and can only be used when PerformancePoint service is deployed to the server which may not always be the case. For reliability, the web servcie API should be used instead.

As an example to show that in some cases all three API can achieve the exact same thing, please see the next three methods

BIMonitoringServiceApplicationProxy.CreateDataSource Method
http://msdn.microsoft.com/en-us/library/microsoft.performancepoint.scorecards.bimonitoringserviceapplicationproxy.createdatasource(v=office.14).aspx

SPDataStore.CreateDataSource Method
http://msdn.microsoft.com/en-us/library/microsoft.performancepoint.scorecards.store.spdatastore.createdatasource(v=office.14).aspx

IBIMonitoringStore.CreateDataSource method
http://msdn.microsoft.com/en-us/library/microsoft.performancepoint.scorecards.ibimonitoringstore.createdatasource.aspx

They all have the exact same API
public DataSource CreateDataSource(string listUrl, DataSource dataSource)

A few useful links for PerformancePoint development

http://blogs.msdn.com/b/performancepoint/
http://msdn.microsoft.com/en-us/library/bb848116(v=office.14).aspx
http://msdn.microsoft.com/en-us/library/ee559635.aspx
http://msdn.microsoft.com/en-US/office/bb660518

Friday, April 5, 2013

Unattended service account and SSS in PerformancePoint and Excel Services

Unattended Service Account and SSS in PerformancePoint and Excel Services

References

Plan Excel Services authentication (SharePoint Server 2010)
http://technet.microsoft.com/en-us/library/ee662541(v=office.14).aspx
 
Create a connection from Dashboard Designer to an Analysis Services data cube by using PerformancePoint Services
http://technet.microsoft.com/en-us/library/ff191198.aspx

When creating data connections in either PerformancePoint Dashboard Designer or Excel, there are three options.

For Excel, the three options are

1. Windows Authentication
2. SSS
3. None

For Dashboard Designer, the three options are

1. Unattended Service Account
2. Use a store account (SharePoint 2013. SP2010 is different).
3. Per-user identity

The equivalence among these options are

1. Windows Authentication = 3. Per-user identity
2. SSS = 2. Use a store account
3. None = 1. Unattended Service Account

Use Windows Authentication to external data will require Kerberos authentication which can do the double-hop authentication among servers.

Since configuring either SSS or Unattended Service Account will use "Secure Store Service", there is big confusion about what user account will be mapped to the external account. Even many of the published the book cannot get this right.

When using "Unattended Service Account" in either PerformancePoint or Excel Service, this means that application pool's service account should be mapped to the external account. By mapping application pool's service account to external account, all users in the farm who have access to the application pages will have access to the data.

From MSDN

Unattended Service Account: The unattended service account is an account that is used by Excel Services to provide broad database access to all users in the farm. Use the unattended service account for accessing data that is not considered sensitive or where you do not want to restrict access to a certain group of users. For information about how to configure this scenario, see Configure Excel Services data refresh by using the unattended service account (SharePoint Server 2010).
(http://technet.microsoft.com/en-us/library/ff191191(v=office.14).aspx)

Unattended Service Account: The unattended service account is an account that is used by PerformancePoint Services to provide broad database access to all users in the farm. Use the unattended service account for accessing data that is not considered sensitive or where you do not want to restrict access to a certain group of users. For information about how to configure this scenario, see Configure the unattended service account for PerformancePoint Services (SharePoint Server 2013).
(http://technet.microsoft.com/en-us/library/jj819321.aspx)
 
When using "SSS" in either PerformancePoint or Excel Service, the current user's account/group needs to be mapped to the external account. This is different from the "Unattended Service Account" which use the application pool's account. Only the users who are mapped in the "Members" in the SSS configuration will have access to the data. This adds another layer of security.

The mistake I had seen (in the books) is that when configuration "Unattended Service Account", the SharePoint user's account is used in the "Members" of SSS instead of the application pool's account.

Another note about next

When SSS connecting the external data, it could pass the credential in two ways: one is the credential in the connection string. One is the "impersonation".

The data provider will determine which credentials will use.

None

When you select the None option, no credential retrieval occurs and no special action is taken for authentication for the connection. Excel Services does not try to delegate credentials, and it does not try to retrieve credentials that are stored for the user from the Secure Store database. Instead, Excel Services impersonates the unattended service account and passes the connection string to the data provider that handles authentication.
The connection string may specify a user name and password to connect to the data source or it may specify that the Windows identity of the user or computer that is issuing the request be used to connect to the data source. In either case, the unattended account is impersonated first and then the data source connection is made. The connection string and the provider determine the authorization method. Additionally, authorization can be based on either the credentials found in the connection string or the impersonated unattended account's Windows identity. For more information, see Unattended service account.

Unattended service account

Excel Services runs under a highly privileged account. Because Excel Services has no control over the data provider and does not directly parse provider-specific connection strings, using this account for the purposes of data access would be a security risk. To lessen this risk, Excel Services uses an unattended service account. This is a low-privileged account that is impersonated by Excel Services if either of the following conditions are true:
  • Any time that it is trying a connection where the None authentication option is selected.
  • Whenever the SSS (Secure Store Service) option is selected and the stored credentials are not Windows credentials. (This means that the call to the external data will have impersonated credential AND user name, password in the connection string).

 

Thursday, April 4, 2013

Reset the Farm Passphrase in SharePoint 2010

Reset the Farm Passphrase in SharePoint 2010


Reference:

http://techtrainingnotes.blogspot.com/2009/12/sharepoint-2010-change-passphrase.html
http://sharepointadam.com/2010/01/21/reset-the-farm-passphrase-in-sharepoint-2010/
http://blah.winsmarts.com/2013-2-SharePoint_2010_and_PowerShell_30.aspx

Use PowerShell

PS C:\Users\Administrator> $passphrase = ConvertTo-SecureString -asPlainText -Force
cmdlet ConvertTo-SecureString at command pipeline position 1
Supply values for the following parameters:
String: hello,world555
PS C:\Users\Administrator> Set-SPPassPhrase -PassPhrase $passphrase -Confirm

cmdlet Set-SPPassPhrase at command pipeline position 1
Supply values for the following parameters:
ConfirmPassPhrase: ********

Confirm
Are you sure you want to perform this action?
Performing operation "Set-SPPassPhrase" on Target "SPPassPhrase".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): y
PS C:\Users\Administrator>


PowerShell Error

If you see this error

Set-SPPassPhrase : Microsoft SharePoint is not supported with version 4.0.30319.18034 of the Microsoft .Net Runtime.
At line:1 char:1
+ Set-SPPassPhrase -PassPhrase $passphrase -Confirm
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (Microsoft.Share...etSetPassPhrase:SPCmdletSetPassPhrase) [Set-SPPassPhrase], PlatformNotSupportedException
    + FullyQualifiedErrorId : Microsoft.SharePoint.PowerShell.SPCmdletSetPassPhrase


Reference
http://blah.winsmarts.com/2013-2-SharePoint_2010_and_PowerShell_30.aspx

and change the SharePoint PowerShello target to (Add -Version 2.0)

C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe -Version 2.0 -NoExit " & ' C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\CONFIG\POWERSHELL\Registration\\sharepoint.ps1 ' "

Friday, March 29, 2013

JavaScript Object Oritented Programming Vs C# (C++, Java)


JavaScript's OOP model is very different from C# or C++, Java. If you are from a background of C#(Java) programmer, it would take a while to really understand and get used to the OOP concepts in JavaScript.

At first glance when you study the object, class and inheritance in JavaScript, they all looks very familiar and you think you could understand them easily but you may not.

One thing that took me quite a while to really understand is that in JavaScript there is no real "Class". (or in other words, the Class in JavaScript is very different from C#).

Another thing that can help you understand OOP in JavaScript is that JavaScript is very "Object Centric" vs C# is "Class Centric".

With C#, you start programming by defining "Classes" and create inheritance among "Classes". In JavaScript, you usually start with defining "Objects" and create inheritance between "Objects". "Class" in JavaScript is really just a special function called "Constructor" (another familiar concept but it is very different).

A third thing that can help your understanding is that almost everything in JavaScript is "Object", object is object, function is object, class is function so it is object, namespace is function so it is object, string is object, array is object, ...

Class in C#

using System;
public class Dog
{
    private string face, color, leg;
    public Dog(string face, string color, string leg)
    {
        this.face = face;
        this.color = color;
        this.leg = leg;
    }
 
    public virtual string Run()
    {
        return face + color + leg + " is running";
    }
 
    public string Name
    {
        get
        {
            return "Dog";
        }
    }
}
 
public class GoldenRetriever : Dog
{
    public GoldenRetriever(string face, string color, string leg): base(face, color, leg)
    {   
    }
 
    public override string Run()
    {
        return "Gollden Retriever " + base.Run();
    }
}
 
class Program
{
    static void Main(string[] args)
    {
        //Create an instance of Dog
        Dog myDog = new Dog("^_^""""# # # #");
        Console.Write(myDog.Run());
 
        //Create an instance of golden retriever
        GoldenRetriever myGoldenRetriever = new GoldenRetriever("^_^""yellow""@ @ @ @");
        Console.Write(myGoldenRetriever.Run());
    }
}
 
The C# example shows that in C#, you starts with define a class "Dog" then define another class "GoldenRetriever" inherits from it. After both classes are defined, you can create objects from them. So in C#, you say "GoldenRetriever" inherits from "Dog". They are all classes. You don't say "myGoldenRetriever" inherits from "myDog", since they are all objects.

However, in JavaScript you do say that "myGoldenRetriever" inherits from "myDog", since in JavaScript "myDog" is used as template to create another object "myGoldenRetriever". Inheritance happens between objects than classes.

Class in JavaScript

Actually it is easier to think JavaScript without thinking about class. In JavaScript when mentioning "Class", you are just mentioning a function which plays the role of constructor of object. In my opinion JavaScript is a "Object Oriented Lanuage" without "Class".

1. Create a "Class".

        // Dog class constructor
        function Dog(face, color, leg) {
            this.face = face; // smily face
            this.color = color;
            this.leg = leg; // four legs
        }
        Dog.prototype = {
            run: function () { return this.face + this.color + this.leg + " is running ..." },
            // object properties added in prototype
            name: "Dog"
        }

2. Create an object from the "Class".

            var myDog = new Dog("^_^""""# # # #");
 
            ShowMessage2("run 1:" + myDog.run());
            ShowMessage2("run 1:" + myDog.face);
 
3. Create an inherited object from another object using ECMAScript 5.
 
            var myGoldenRetriever1 = Object.create(myDog);
            myGoldenRetriever1.face = "^...^";
            myGoldenRetriever1.color = "yellow";
            ShowMessage2("run 2:" + myGoldenRetriever1.run());
            ShowMessage2("run 2:" + myGoldenRetriever1.color);
 
 4. Create an inherited object from another object without ECMAScript 5

        // Create new GoldenRetriever object inheriting from dog
        function CreateGoldenRetriever(dog) {
            // GoldenRetriever class constructor
            function GoldenRetriever() { };
            GoldenRetriever.prototype = dog;
            return new GoldenRetriever();
        }

            var myGoldenRetriever2 = CreateGoldenRetriever(myDog);
            myGoldenRetriever2.face = "^...^";
            myGoldenRetriever2.color = "golden";
            ShowMessage2("run 3:" + myGoldenRetriever2.run());
            ShowMessage2("run 3:" + myGoldenRetriever2.face);

5. Create an inherited object from another object without ECMAScript 5 in more generic way.

        // inherit() returns a newly created object that inherits properties from the
        // prototype object p. It uses the ECMAScript 5 function Object.create() if
        // it is defined, and otherwise falls back to an older technique.
        function inherit(p) {
            if (p == nullthrow TypeError(); // p must be a non-null object
            if (Object.create) // If Object.create() is defined...
                return Object.create(p); // then just use it.
            var t = typeof p; // Otherwise do some more type checking
            if (t !== "object" && t !== "function"throw TypeError();
            function f() { }; // Define a dummy constructor function.
            f.prototype = p; // Set its prototype property to p.
            return new f(); // Use f() to create an "heir" of p.
        }

            var myGoldenRetriever3 = inherit(myDog);
            ShowMessage2("run 4:" + myGoldenRetriever3.run());
            ShowMessage2("run 4:" + myGoldenRetriever3.face);

As you can see in any of aboves ways to do inheritance in JavaScript, a new object is created and inherites from an existing object "myDog". "myGolenRetreiver" inherits from "myDog" but it is not a "sub class" of "myDog" since they are all objects.

In JavaScript it is possible to introduce the concept of "sub class", the "sub class" in JavaScript is a way to create contructor function based on another contructor function. It is more advanced topic and I am not sure how practical to use it in the real world.

Here are few good articles that explains "prototype" in details.

http://msdn.microsoft.com/en-us/magazine/ff852808.aspx

http://yehudakatz.com/2011/08/12/understanding-prototypes-in-javascript/

http://net.tutsplus.com/tutorials/javascript-ajax/prototypes-in-javascript-what-you-need-to-know/