Search This Blog

Wednesday, September 2, 2015

Office 365 - Accessing Power BI Administration - Issue and Fixes

Power BI is a very useful and feature rich Business Intelligence tool in Office 365.
Some of the configuration tasks require admin to log into Admin Portal.
Example: Setting up a Gateway / Data Sources.
What is a Gateway (from Power BI Admin Portal):
A gateway is used to connect to a data source in your corporate environment. You must have at least one gateway installed in your corporate environment before creating a data source.

Even if you are a Global Admin on Office 365 and you have access to Power BI portal, which means you have a license for Power BI,  you may not have access to Power BI Admin Portal which is fine because not everyone in the company would have that role.

However if you need to access Power BI Admin and it does not work: There are 2 reasons / solutions which are explained below.
Screenshot 1)
On clicking Power BI link as shown below you may get the following error:
Screenshot 2)
                                                                    OR

You may not see the Power BI link at all  (highlighted in yellow color in screenshot 1 above)

The Issue above is that Power BI Admin access needs the second option in Power BI License to be checked as shown below.
 Screenshot 3)

The above license screen is Admin --> Users --> Active Users --> (search for Name of the person) --> Click on check box before person name -->  (Use one of the 2 options below)
i.e.
click "Edit" -->  click "Licenses"
        OR 
Assigned License --> click "Edit"

Once the above check box  i.e. Microsoft Power BI Reporting and Analytics Plan 1 is checked   (Screenshot 3 ) --> refresh the web page and now we should see Power BI link in Admin section of Admin portal. So far so good.

Now if we click on Power BI link you will reach the Power BI Admin screen which is at

https://<domain name here>.admin.powerbi.com/?language=en-US
If this worked you can skip the step below. However for your knowledge please continue reading...

If you still can not access Power BI Admin here is another cause and solution:

--> One of the Office 365 Admin in the company would have access to Power BI Admin.
Powershell can be used to find a list of Office 365 Admins.
Administrator need to go from their login and assign the role from the Role Management section as shown below in screenshot 4.

Screenshot 4)

After the login has been assigned the administrator role from the above screen (Screenshot 4), Power BI admin should work.

My suggestion to Microsoft would be: Instead of user looking for reasons why Admin is not working -

a) Power BI Admin link should always be shown to the Global Admin if the Global Admin has been assigned  a Power BI License
b) On clicking the admin link it should:
     b1) Ask the user to check "Microsoft Power BI Reporting and Analytics Plan 1" (Screenshot 3) -  if that is not already checked.
     b2) Show a read only list of current Power BI admins so that they can be contacted to assign the role as shown above.

Well that is it and hopefully these management things will improve since Microsoft updates Office 365 regularly.

Until next time...

Chao
Mohan


Wednesday, April 1, 2015

SharePoint online - Provider hosted Apps - Part 1

This is a series of posts that gives an insight into design / development of provider hosted apps using SharePoint Online - Office 365 and Azure cloud.

Will include issues / challenges and best practices on the way. Please drop in your comments / questions / and feel free to forward the link.

-------------- Here we go..

There are only 2 choices to develop a SharePoint cloud app i.e.
SharePoint hosted and Provider hosted (Autohosted used to be another option earlier).

 .Net CSOM has its advantages for few reasons below (while there are good reasons for a preference on REST based apps also):

Pros:
a)  Working with .Net client side libraries in Visual Studio gives good intellisense (which is also  available in JavaScript to an extent however not that good when compared with .Net)
Objects are strongly typed,  no typo issues in properties / methods.


b)  Working with azure side code - you get other useful features available from Azure i.e. Caching, Scheduled jobs which is not available if it is a SharePoint hosted app

c) IPR: Since .Net code runs on Azure Web Sites (now called Web Apps) it is not visible to end users specially if this is a product you are making. JavaScript also can be obfuscated however it is not as protected as code that is not visible on Azure.  All the dynamic UI functionality would still be in jQuery / JavaScript and that can not be avoided (unless you do not have any dynamic UI stuff in the app which is rare).

d)  Using 3rd party libraries is possible since we can add a reference to it in web project and use it from server side and/or client side. For example: i have used Telerik controls, Newtonsoft JSON.Net serializer. Please check if the 3rd party .Net dll can run on Azure. The above two i used on Azure web sites and they ran okay. The other option is to create a VM on azure where you can run any legacy software as well.

e)  Making modifications to App becomes easier if it being used by Multiple Tenants. We make changes in Azure and everyone gets the updated UI or business logic next time they run the app.

f) Scalable: Given it is on Azure - we can easily scale the application as needed.

Side Note: There are comparisons on Rest versus JSOM versus .Net CSOM which are plenty out there there on web. Using Rest or JSOM  is also fine - it is more of a suitability for a given requirement as well personal choice.

Cons:

a) Need subscription to Azure which may add to the cost.

Note: While you may use your own App server on Internet also however setting up OAuth, security, patch management of server and other things may make that a complicated process. Also tight integration with VS.Net for Azure makes it very easy to work. Hence using Azure is recommended for a provider hosted app.


Now once we have design document ready for the App we come to using tools and processes that can be used for building the app.

UI Design Tool Choices
a) For prototyping UI - the best tool i have used is Axure. Provides even dynamic UI interface
and you can very quickly realize the benefits.

a)  Do we need any 3rd party control for UI. Example: complex hierarchical grid, server side binding of data to grid - then we can use a 3rd party control suite like Telerik / Component One etc.
They also have client side programming model available for UI controls which can be used thru JavaScript. Using those can save time in building our custom UI components. All the dynamic UI functionality would still be in jQuery / JavaScript on client side (browser). 3rd party DLLs will run on Azure web apps.

b) Design the UI just with jQuery and CSS - use Napa app by Microsoft.
It's a free app available from App Store in Office 365.
  1. For using data binding i.e. bind HTML to data from SharePoint -  get JSON data from JSOM / REST and use Knockout library to bind to that JSON. This is a different approach than the focus of this post and need another  blog post all together to describe the design / implementation.
  2. We can also use Napa to just build the UI and later move the UI to vs.net project. Could also help when multiple team members are working on the project. One on UI and other Azure side code. There are potential issues which need to be taken care while integrating (ToDo..write integration issues and solution link here...)
  3. For using Napa - we just need internet connection and a modern browser (and of course a office 365 account).  Also no need for VS.Net installed on your machine for this. Coming to browser - my preference is Firefox because of quick CSS mods within browser and a neat JavaScript debugger. One could have a browser preference and you are right if you have a different one.  
  4. The Napa app can be converted to a VS.Net project using a link within the napa tool on the left side. This will be app project of VS.Net solution. The other is the web project which contains the Azure code.

Question: Is it necessary to use Napa tool for a provider hosted App?
Answer: Not at all. We can build all the UI within VS.Net also.

To be continued in next Post...

Please write back with questions / comments.

-- Mohan













Monday, November 11, 2013

Reading SharePoint web.config

Usage Scenarios:
 
Read configuration information like SQL connection string, custom application settings etc. from SharePoint web.config file
 
Here is the code snippet:
 
-----------------------------------------------
 
using System.Configuration;
using System.Web.Configuration;
...
...
 
string webAppName = SPContext.Current.Site.WebApplication.Name;  // use SPSite object hierarchy to get web application name.
 
Configuration config = WebConfigurationManager.OpenWebConfiguration("/", webAppName);
string dataFromAppSettings = config.AppSettings.Settings["Setting Name to read"].Value;

 
 
-------------------------------------------------------

That's all for this post. Until next time...

-- Mohan





Wednesday, October 30, 2013

Send customized email Alerts from SharePoint Workflow (2007 / 2010 / 2013)

The purpose of this blog post is to discuss a design which can send customized email alerts / reminders from a SharePoint workflow.

Skills Needed: 
C# and SharePoint custom workflows


Let's have a look at the different methods:

a) Use SPAlert
This works okay however the problem using SPAlert object is the customization of the message.
There are ways to modify/create custom messages by changing the XML files in 14 hive but i prefer not to change those.

b) Using Listen activity

We need a customized email message to be sent to the workflow users i.e. be it approvers or delegates etc. and here is a design which can provide that functionality in a custom SharePoint workflow.



The CreateTask activity (not shown in the image above) is above the While Activity i.e. while loop.

Legends for the Image:
1:   Listen Activity
2.  Delay Activity
3.  Code Activity


Nested inside the While loop is a Listen Activity (1)  with two branches as shown above. Both the branches must start with a Event Driven activity. Example: OnTaskChanged, DelayActivity etc.

The listen activity will wait for any of the branch to wake up and whichever wakes up first - completes the activity.

Hence in above case either the user completes the task (ontaskchanged1 fires) OR the time in delay activity is up (delayActivity1 completes) and hence the code activity fires up. The code activity above i.e. codeActivitySendReminder contains custom email code i.e. Email reminders for Task

Here is what the delay Activity handler looks like:

  private void delayActivity1_InitializeTimeoutDuration(object sender, EventArgs e)
        {
            DelayActivity dAct = sender as DelayActivity;
            dAct.TimeoutDuration = new TimeSpan(<Number of Days here>, 0, 0, 0);             

        }


Now let's say we want to send a reminder every 2 days  if the task has not completed,  then the above line would look like:
     dAct.TimeoutDuration = new TimeSpan(2, 0, 0, 0);       

Going further more:
The above code can be replaced with the days based on
actual Due date of the task in CreateTask activity.
i.e.
Example: 
TimeSpan ts = TaskObject.DueDate -  DateTime.Today (Calculate ts before the While loop above);
and hence use 

 ts.Days above i.e.
dAct.TimeoutDuration = new TimeSpan(ts.Days, 0, 0, 0);       


How to send custom emails is out of scope for this article since that is very common piece of code around and easily available on internet.


And that's all for this post.

Any questions / comments are welcome.

Please write back...

-- Mohan


( By the way I saw this on linkedin:
Question: Why do Java developers need eye glasses?
Answer:   Because they do not C# 
)

Saturday, June 15, 2013

Display workflow history in custom InfoPath task forms

If you have worked on custom InfoPath task forms with code behind, here is a ready made enhancement which users loved and hope your users will too..

What it does:
Retrieves the workflow history items associated with a workflow instance and shows them in a Grid in InfoPath form.

How is it useful:
For a given custom workflow in SharePoint - the InfoPath task form and associated workflow history are 2 different pages.  If you already have a custom task form in IP,  then using this method we can display workflow history so that every approver can see what has happened so far in the workflow (with latest on the top so that they can quickly see the task history prior to their approval), and this could help in making informed decision on task approval. Additionally the dates are shown similar to SharePoint 2013 format i.e. for example:
Today at 3:45 PM
Yesterday at 12:10 PM
Day before yesterday at 12:15 PM

Sample output:


Skills needed to implement this:
SharePoint workflows, InfoPath code behind knowledge

Can it be used on ASPX task forms?
Yes, it can be. Please change the yellow highlighted lines below which are specific to InfoPath

Our User Feedback:
They love it.

How to configure (please refer the image below):
a) Select main data source in InfoPath
b) Create a group element as shown below with name HistParent
c) Under HistParent group create an element with name "hs".  Data type is text and check on "repeating"
d) Remaining i.e. pos, un, oc, cm, dt are all text type and are "attributes" (not element)




e) Copy and paste the function below in code behind of your InfoPath task form.
f)  Call the method from form load passing in the WorkflowInstanceId and HistoryList Id
     How to pass in the above values:
      f1) Assuming you are using itemMetadata.xml for the task form - create 2 new fields for
            workflowInstanceId and historyListId
      f2) from the custom code workflow pass in the values like
   taskProperties.ExtendedProperties["workflowInstanceId"] = workflowproperties.WorkflowId.ToString("B") ; // Important to put B here since we need { } to be included in string
     
  taskProperties.ExtendedProperties["historyListId"] = workflowProperties.HistoryList.ID.ToString() ;


Source Code (included as is - no warranties)

        /// <summary>
        /// Function to display Workflowhistory for a given workflow instance in reverse chronological order
  /// </summary>
        /// <param name="workflowId">Contains the workflow instance guid with { } in string format</param>
        /// <param name="historyListId">GUID for history list without { } </param>
        public void GetWorkflowHistory(string workflowId, string historyListId, string siteURL, string webRelativeURL)
        {
            SPList historyList = null;
            // Open site collection
            using (SPSite site = new SPSite(siteURL))
            {
                // Open web
                using (SPWeb web = site.OpenWeb(webRelativeURL))
                {
                    try
                    {
                        // Check for existence of history list
                        historyList = web.Lists[new Guid(historyListId)];
                    }
                    catch // History list has been deleted or renamed
                    {
                        throw new ApplicationException("History List not found");
                    }
                    SPQuery qry = new SPQuery();
                    qry.ViewFieldsOnly = true; // Optimize performance
                    qry.ViewFields = "<FieldRef Name='User'/><FieldRef Name='Occurred'/><FieldRef Name='Outcome'/><FieldRef Name='Description'/>"; // Get specific fields only -  user name, date, task outcome and, task comments
                    // WorkflowInstance field contains the GUID of the workflow instance in history
                    qry.Query = string.Format("<Where><Eq><FieldRef Name=\"WorkflowInstance\"/><Value Type=\"Text\">{0}</Value></Eq></Where><OrderBy><FieldRef  Name=\"ID\" Ascending='False' /></OrderBy>", workflowId);
                    qry.DatesInUtc = false;
                    SPListItemCollection coll = historyList.GetItems(qry);
                    SPListItem item = null;
                    StringBuilder sb = new StringBuilder();
                    string userName, outcome, comments, sDT;
                    DateTime dt;
                    SPUserCollection uColl = web.AllUsers;
                    SPFieldUserValue uVal;
                    SPFieldUser uField = historyList.Fields.GetFieldByInternalName("User") as SPFieldUser; 
                    int count = coll.Count;
                    for (int ctr = 0; ctr < count; ctr++)
                    {
                        item = coll[ctr];
                        uVal = uField.GetFieldValue(item["User"] as string) as SPFieldUserValue; // get SPFieldUserValue object using User from history list
                        if (uVal != null)
                        {
                            userName = uVal.User.Name;
                        }
                        else
                        {
                            userName = "Not known";
                        }
                        outcome = item["Outcome"] as string;
                        dt = DateTime.Parse(Convert.ToString(item["Occurred"])); // Convert date occurred
                        /*The following block displays the date in SP 2013 kind of format i.e.
                         * when current date == Today then displays "Today at 3:45PM" (assuming time is 3:45 in occurred field).
                         * Similary for Yesteray and Day before yesterday. 
                         * When none of the if are satisfied - display the Long Date string format
                         */
                        if (dt.Date == DateTime.Today)
                        {
                            sDT = "Today at " + dt.ToShortTimeString();
                        }
                        else if (dt.AddDays(1).Date == DateTime.Today)
                        {
                            sDT = "Yesterday at " + dt.ToShortTimeString();
                        }
                        else if (dt.AddDays(2).Date == DateTime.Today)
                        {
                            sDT = "Day before yesterday at " + dt.ToShortTimeString();
                        }
                        else
                        {
                            sDT = dt.ToLongDateString();
                        }
                        comments = item["Description"] as string;
                        comments = (comments == null ? string.Empty : comments);
                        /*  The assumption here is that we have fields in our InfoPath main data source with these names.
                         * Abbreviations are:
                         * pos -- position (in reverse) 
                         * hs -- History
                         * un -- UserName (display name)
                         * oc -- Task outcome
                         * cm -- Comments by approving user or system
                         * dt -- date of history item - in reverse chronological order
                         */
                        sb.AppendFormat("<my:hs my:pos='{0}' my:un='{1}' my:oc='{2}' my:cm='{3}' my:dt='{4}' />", count - ctr, userName, outcome, comments, sDT);
                    }
                    // If there are any history items
                    if (sb.Length > 1)
                    {
                        XPathNavigator nav = CreateNavigator();
                        // Set the generated XML to InfoPath main datasource "Group" element i.e. History Parent
                        nav.SelectSingleNode("/my:myFields/my:HistParent", NamespaceManager).InnerXml = sb.ToString();
                    }
                }
            }
        }


Finally please let me know your feedback:

Saturday, May 11, 2013

Display Ratings control inside Data View Web Part (DVWP - SharePoint Designer) aka Data Form Web Part (DFWP)

Though this looks straightforward i.e. drag and drop the rating field from data source in data view web part and it will show the rating stars (asterisks) but the output does not show as expected in data form web part.

There are few posts on internet to create a custom code data view web part that can display the ratings (by inheriting from data view web part). Well how about doing it out of the box. Yes - there is a 3 step solution  we have and that is what this post is about. So here we go:

Steps
1.  Modify the web.config file for SharePoint web application. Open web.config in a editor and
search for <Controls> section. There is already one line there for asp.net. We add another one as below:

  <add tagPrefix="Portal" namespace="Microsoft.SharePoint.Portal.WebControls" assembly="Microsoft.SharePoint.Portal, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />

Why we do the above: Data View Web Part does not use the import / register tags defined on top of .aspx page.  It has its own independent system (built within its compiled code) to use the namespace it wants to use. By adding the above line in <Controls> section it makes those namespaces available.

2. In SharePoint Designer open the page containing data view web part
    Switch to code view: On the top of DVWP in xslt, there are all the namespaces that are defined.
    We will add the namespace so that we can use any control from

    "Microsoft.SharePoint.Portal.WebControls" defined in controls section in step 1) above

xmlns:Portal="Microsoft.SharePoint.Portal.WebControls

Why : This is because for any dll methods we want to use in DVWP, it must define the namespace for that in XSLT.


3. Finally to display the ratings controls add the following tag in the XSLT wherever we need to display the ratings:


<Portal:AverageRatingFieldControl  runat="Server" itemid="{@ID}"  id="MyRating{generate-id()}" FieldName="AverageRating" ControlMode="Edit" />

Few things above: 
a) {@ID} links the ID of the listitem for which we want to display or display/edit the ratings
b) FieldName must be AverageRating only
c) ControlMode: If we want to only display the ratings use "Display" however for display as well as allow  user to modify the rating use "Edit"


Additionally 
a) The user profile service must be is running since rating data is stored in Social Database, and ups should be associated with the web application.
 b) The Users Profile Social .... timer services must be running (2 of those). By default the update time is in hours i.e. when user clicks the asterisk, it would take few hours to show the updated rating. Change the settings to make it update faster (the downside of running more frequently means more load on server).

Hope this will be useful to anyone looking to get ratings without writing any code.


 -- Mohan



Thursday, March 21, 2013

Export a list using Powershell

Well this post is more for a syntax reference.

Using Export-SPWeb is one of the ways copy list schema and data from one web app to another Or one server to another.


Onw of the reasons I have used this many times is for a list that is in production - copy that list only to a Dev environment to work and develop artifacts for that list like workflow, event handlers etc.

Here is the sample that explains the syntax:

Export-SPWeb -Identity "http://str-sp2010/subsite" -ItemUrl "/subsite/lists/List Title here"
-path "c:\folder\filename.dat"


Where:

-Identity: full url (absolute) of the site where the list exists
-ItemUrl:  relative path of the list from subsite level. Do not forget to include the leading "/"
-path: path of the output file to save the data in. This does not need any extension but I usually give it .dat meaning data

There are lot more additional parameters but above are the minimum for copying a list


To recreate the list in other environment - we use Import-SPWeb command.



Friday, September 21, 2012

Server for SharePoint Production and Development environments

There are many vendors out there who provide server hardware. However this post I will mention a specific one which I have had good experience with.
Traditionally all servers from HP / Dell / IBM have been so that it does not allow for adding PCI / PCIe cards for adding your own Video cards. Well a possible reason for that: Who will buy a workstation PC if servers allowed that? However with the new VDI (Virtual Desktop Infrastructure) scenarios things have changed. Ofcourse we always want the server to be powerful and at the same time would be nice to see the display in full HD i.e. atleast 1920 x 1080 Pixels and in 32 bit colors. So far that was not possible as mentioned above. But now it is - Here is a server (besides few other from Dell which do that) i.e. Dell R720 server. It is a 12th Generation server and there are many neat things about it:

a) Allows video cards to be added using the PCIe x16 slots. - Tested with AMD FirePro 4900 and works ok. The only thing to make it work - disable the onboard video from BIOS after adding the new card and on re-boot.
b) How about Sound card - well most of the sound cards are PCI. PCI and PCIe slots are not compatible.
However PCIe is backward compatible which means a PCIe 1x card would work ok in a PCIe X16 slot.
Hence a PCIe 1x sound card should work just fine. Have not tested this though therotically it looks feasible.
An external USB sound connection works very well - Tested and this works.
c) 10 GBPS ethernet card. Now that is fast. We can have the VMs on the server talk to each other thru 10GBps connection. Now imagine that network speed betweeb SharePoint WFE and SQL VM if they are on the same server. It has a LOM (Lan on Motherboard) module which makes traffic within VM at blazing speeds.
d) Dual Xeon 8 core processors with hyperthreading i.e. 16 physical cores however shows 32 CPU in windows because each core is hyperthreaded.
e) Noise: Really low noise i.e. less than what a Desktop PC makes
f)  Heat: Remains around 26 C to 27 C most of the time. Higher CPU usage may push that number higher.
g) Allows maximum RAM to upto 768 GB. That's pretty high a number.
h) RAID card options with 512 Mb or 1 Gb caching - a must for good I/O performance.
i) Cost: Similar config from HP would cost atleast 2K-3K more than Dell (number may vary based on configuration).
j) Plenty of disk slots. If you need xtra storage Dell has R720xd  (xd is for Xtra Drives or Disk). However xd may not support a GPU I believe (please check with Dell).


While playing video files on this server in a VM- the CPU usage percentage occasionlly jumps to 1% and most of the time remains at 0%.  Well that is a powerfull server! Ofcourse using more resources would trigger that to high number.

Dell has really outperformed with its 12th generation server and I want to kudos to the guys for the new design. Overall this server would be a good candidate for SharePoint production server as well as for SharePoint development team so that they can get the full desktop experience from VMs on this server.

With Windows Server 2012 now some things have improved i.e. RemoteFX does not require a physical GPU since it provides a s/w based Virtual GPU. Though for intensive video work, H/W card is still recommended.

I will definitely recommend this server to our clients for SharePoint installations.

That's all for now. Untill next time...

-- Mohan
Disclaimer: Am not associated with Dell and they are not involved in writing of this article in anyway. The above are personal experiences with using Dell R720 server. I liked the product and hence expressesd my opinion.







Wednesday, September 19, 2012

Using LINQPad for SharePoint Development

Well may be you are already familiar and using this but if not - please continue reading.
While Visual Studio 2010 /2012 are great editors for SharePoint Development, there is another tool which we can use for quick function writing and testing. It's called LINQPad

http://www.linqpad.net/

It's a small footprint application with no installation components - just one self contained exe.
I have used this for testing functions and then copy over to large SharePoint projects so that building and testing the function is easier than testing the same function in a large application.
Though there is free version also but in my opinion that is useless i.e. without intellisense it will make it difficult to program. The Pro version is only around $35 - ask your boss and he will not have any issues with that. That same copy of license can be installed on multiple machines which you own and use - that is another plus.


How to setup for SharePoint development:

After downloading the application, run the .exe.
The .exe does not run if it is renamed, so need to be LINQPad.exe only. There are multiple versions however the one which works with SP 2010 is .Net 3.5 version. The X86 and X64 versions do not work with SP 2010.

How to setup for SharePoint development:
After editor shows up, press F4.


Add the references from ISAPI folder. By the way all the references are not required and the bare minimum is Microsoft.SharePoint.dll . Click on set as default for new queries so that these are set for all code files we create henceforth.

Next click on the additional namespce imports tab and

and type in Microsoft.SharePoint.
Click ok.

From editot window - select C# program as shown below (we can use other options also) however this way we can write multiple functions in the same file and then call those from Main( )


The editor is ready to use now.

Overall Pros:
a) Lightweight
b) Low cost
c) Fast editor and with syntax highlighting and intellisense

Cons:
a) No step by step debugging (use .dump( ) function to write the values to output.
b) While testing with a SPWeb and using GetTemplates it cached the list of templates and that was a issue since after creating new Site Templates, the code did not show those. Closing the editor and re-opening fixed the issue.

Well we can not compare it with all the things VS.Net offers but for the given cost - it offers a lot.

Also this would not work with SP 2013 because it is built for .Net 3.5 SP1.
So far have used VS.Net 2012 with SP 2013 but not LINQPad .Net 4.0 and that may work with SP 2013.
If you try that please write back...


That's it and until next time...

-- Mohan

Disclaimer: Am not associated in anyway with LINQPad. The above is only based on personal experience on using this tool.


Tuesday, September 11, 2012

Column .. does not exist. It may have been deleted by another user

System.ArgumentException: Column 'ColumName' does not exist. It may have been deleted by another user.  /ListPath    at Microsoft.SharePoint.SPFieldCollection.GetFieldByInternalN

If we see the above error, don't panic there is a fix.

Cause: A workflow association was deleted from a list. Every time a workflow is associated and "run" on at least 1 item of the list - workflow creates a internal column with the first 8 characters of the workflow association.
Example: if your workflow association name was "MyWorkflow" the column name would possibly be "'MyWorkfl"

Hence above error would be"
Column: 'MyWorkfl' does not exist. It may have been......

Now if workflows were run using this association and later removed, clicking on workflows from context menu (ECB menu) will give the above error.

Fix:
Create a new workflow association with the same name i.e. this time give the exact same name i.e.
MyWorkfl. Use the out of the box approval workflow, check option allow to start manually. Start the workflow manually on one item on the list.
The workflow column MyWorkfl is recreated automatically.
Remove the option allow workflow to be manually started from this association but do not delete this association. Let it sit there. Go back to old items which had these workflows. The error should go away.
Tada...

-- Mohan

Sunday, August 26, 2012

What's new with InfoPath 2013

Well the short answer is there is no new functionality added  to InfoPath 2013 from InfoPath 2010.
Here is a link with more info:
http://msdn.microsoft.com/en-us/library/office/jj229830(v=office.15).aspx#odc_off15_ta_WhatsNewforO15Developers_InfoPath
However for writing form code - Now it uses full Visual Studio 2012 instead of VSTO which is good change.

Reason: The VSTO with InfoPath 2010 was limited to using .Net 2.0 framework
whereas the InfoPath 2013 creates the Form code in .Net 4.0
Hence that limitation of API while writing InfoPath code is overcome now.

 

Wednesday, July 11, 2012

Value cannot be null. Parameter name: source

on updating a list item an error was thrown:

i.e. Value cannot be null: Parameter name: Source:

Reason:  The value supplied to the Lookup column were not correct.

listItem.LookFieldName = new SPFieldLookupValue(Id, Title)
where Id is the Id of the item in destination list and Title is the value of the Title field.

If the value of Id is wrong this error is generated.

Solution: Obvious: Provide the correct value for Id from destination list.

Tuesday, May 1, 2012

Workflow configurations settings using Powershell - SP 2010

MOSS 2007 had Stsadm get and set property commands to change the workflow config settings.

In SP 2010 using Powershell it is Get-SPFarmConfig and Set-SPFarmConfig
Example:

Set-SPFarmConfig -WorkflowPostponeThreshold 30

Verify the configuration is set by Get-SPFarmConfig as shown in image above.

Here is more info on these:
http://technet.microsoft.com/en-us/library/ff607962.aspx



Thursday, January 26, 2012

Validate comments at the time of Check in of a document

When a document library has "Require documents to be checked out before they can be edited" enabled and if the comments are required - there is no out of the box way to do so.




Well here is a small trick to get that functionality:

Write a cusom event handler on ItemCheckingIn which validates if the comments are entered; and if not - Cancels the check in with a error message shown to the end user. In the following code snippett an additional check is made for length of characters entered which can ofcourse be removed or changed to a different length. Would be ideal if that length is read from another List which could be called as Config list for a project hence if it was 20 chars - change the config list and we are done. 

public override void ItemCheckingIn(SPItemEventProperties properties)
{
string checkInComment = properties.AfterProperties["vti_sourcecontrolcheckincomment"]  as string;
//check for comments being blank or length less than some number of chars.
 if (string.IsNullOrEmpty(checkInComment) || checkInComment.Trim().Length < 5)
   {
      properties.ErrorMessage = "The Version Check in comments should be atleast 5  characters long.";

properties.Cancel = true  
    }

}

The key above is the property "vti_sourcecontrolcheckincomment" which contains the comments entered by user. Just to re-iterate ChekingIn event is raised before the document is checked in.

-- Mohan

     

Sunday, July 10, 2011

Using Jquery and/or JqueryUI? Get better Performance this way...

Always use JQuery / JQueryUI javascript API from a CDN. This gives better performance for your application specially if it is on Internet. Since some of these large CDN have caches and are available throughout the world acessing these .js files is faster than storing them in your local network. It also saves bandwidth for your local network.

Here are the links:

Microsoft CDN: This page below contains links for all Jquery versions on MS CDN.

http://www.asp.net/ajaxlibrary/cdn.ashx


Here is for Google:

 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" type="text/javascript"></script>
 <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js" type="text/javascript"></script>

The query uses unsupported elements, such as references to more than one list, or the projection of a complete entity by using EntityRef/EntitySet."}

"The query uses unsupported elements, such as references to more than one list, or the projection of a complete entity by using EntityRef/EntitySet."}
System.SystemException {System.InvalidOperationException}"

While using LINQ to SharePoint if you get this exception the possible reason is:

a) The LINQ query is using Except or Union or any possibly other operator/function (another example - Join) that performs action on two or more LINQ queries.

I recently encountered this while using Except and Union.

Cause: SharePoint tries to convert these into CAML queries but there are no equivalents in CAML. Hence the above error is generated.

Example
var result1 = from x in dataContext.SharePointList where ....

var result2 = from...

var resultFinal = result1.Union<DataClass>(result2)

The above statement resultFinal would result in this error.

Solution: use ToList before using such function / operation:

var resultFinal = result1.toList<DataClass>.Union<DataClass>(result2.toList<DataClass>)

i.e. before Union - convert to a list using ToList which will avoid CAML generation for Union internally.

Thursday, February 3, 2011

Vague Error from Enterprise Library 5.0

In a project which used  Data Access to SQL I got the following error:

Cannot open log for source 'Enterprise Library Data'. You may not have write access

Cause of the Error: Database name was not correct in the connection string.
It should have been something like "Database XYZ not found or unable to connect to DB XYZ"

-- Mohan

Sunday, August 15, 2010

Error message not shown even after setting CustomErrors in web.config

We know that if we want to see the details of error message, we can change the
<customErrors mode="On" />  to Off and we can see the exact error message.

But wait - ever after changing this to Off in web.config file - it still shows this page below:


Well the solution is to edit the web.config file in this location with <customErrors mode="Off" />  i.e.

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS

After changing the web.config, refresh the page and you will see the specific error message.

Wednesday, June 16, 2010

Visually stunning Map with color highlights in SharePoint

Lot of large organizations have offices around the world. Displaying those on map is visually appealing as well as allow users to interact with the map by clicking or hovering on a given region/country.
Examples: Display the sales figure, Display the Regional Heads / office addresses when a location is clicked on the map. Further more Data Form web part (aka Data View web part) can be configured on the same page to take input from the QueryString. The value for these QueryString Parameters can be configured on the Map (as shown in the example here).

Next Step:  Just put this code in a Content Editor Web Part and see instant results.

Here is how it looks:


Visual feedback when mouse is over a region/country


Please let me know your feedback.
----------------------------------------

<script type='text/javascript' src='http://www.google.com/jsapi'></script>

<script type='text/javascript'>

// Mohan Taneja, SharePoint Architect, STR Tech, LLC



google.load('visualization', '1', {'packages': ['geomap']});

google.setOnLoadCallback(drawMap);



function drawMap() {

var data = new google.visualization.DataTable();

data.addRows(3); // This is the total number of Regions Added below.



data.addColumn('string', 'Country'); // This is the code for the Country to display on the Map

// Could be any numeric value. Ideally I wanted to supress displaying this in tooltip but did not find any option.

data.addColumn('number', 'Location #');

data.addColumn('string','Comment'); // This becomes the Header for the ToolTip. Optional column



/*

Parameter description for setValue method below.

a) The first parameter denotes the Item number or simply put the record number. Since the array start from index 0, record number 1

is index 0, Record number 2 is index 1 and so on.

b) The second parameter is the column number. Since we configured 3 columns above in data.addColumn for each region/country

there are 3 rows i.e. one for each column i.e. 0, 1, 2

c) The third parameter are the value for different columns. Example: US, 1, 'Unites States of America'



Purpose of the Value column (in our example: the "Location #" column)

------------------------

The second Row for each country below is value of data type number. This is actually for range distribution and visualization of

values with different colors(shown as Data Value below). This value is important because it determines the color coding for different countries.

Examples: Population for countries, Sales for offices of a Multinational company. However if you do not have any specific data to

display you could use the method as I have done for this example i.e. pick up numbers from 0 to max number of region displayed.

The starting value of the range determines the first color from the options['colors'] setting below and

the final value determines the last color used. Example: We are using the values from 0 to 2. Hence 0 would correspond to

0xAE84F4, 1 would correspond to 0x84F491 and 2 would correspond to 0xF4DB84 in options['colors'] below. If there are more value ranges

say 0 to 10 then the code behind the scenes automatically determines the range of colors from first to last value for 3 color

specified in options.

c) The third parameter is optional and would show as header for the ToolTip when mouse is moved over the region.

*/



// Country 1

data.setValue(0, 0, 'US');

data.setValue(0, 1, 1); // Data Value

data.setValue(0, 2, 'Head Quarter - USA');



// Country 2

data.setValue(1, 0, 'CA');

data.setValue(1, 1, 2); // Data Value

data.setValue(1, 2, 'Canada');



// Country 3

data.setValue(2, 0, 'IN');

data.setValue(2, 1, 3); // Data Value

data.setValue(2, 2, 'India');



var options = {};

options['dataMode'] = 'regions'; // There are 2 modes. We are using regions

options['colors'] = [0xAE84F4, 0x84F491, 0xF4DB84]

options['showLegend'] = false; // This shows a Static Legend for value distribution with different colors.



var container = document.getElementById('map_canvas'); // This is the div control in which the Map will be displayed

var geomap = new google.visualization.GeoMap(container);

google.visualization.events.addListener(geomap , 'regionClick', OnRegionClicked); // Attach on on click handler for Region clicked

geomap.draw(data, options); // Draws the Map



};

// This is the function invoked when a specific location is clicked.

function OnRegionClicked(obj)

{



var region = obj.region; // gets the value of the region / Country selected. Example: US

var location = window.parent.location; // Get reference to parent window i.e. window which contains our web part.

var url = location.protocol + "//" + location.hostname + ":" + location.port + location.pathname + "?"; // Create the URL for SharePoint site



switch(region)

{

case 'US': // Based on region clicked, Send parameters to QueryString

url += "location=USA";

break;

case 'CA':

url += "location=CAN";

break;

case 'IN':

url += "location=IND";

break;



}

location.replace(url); // Redirect to this URL

}

</script>







<div id='map_canvas'></div>







Tuesday, June 1, 2010

Deploy custom controls with WSPBuilder

Well we all know it is really easy to deploy web parts and other features with WSPBuilder.

When it comes to deploying custom controls, it  needs only the DLL to be deployed (and other additional artifacts that you may have with the control).

To deploy the dlls and create SafeControl entry with WSPBuilder:
create the Setup.exe.Config file and add the following two lines:

<add key="IncludeAssemblies" value="true" />



<add key="BuildSafeControls" value="true" />
 
That's it build the WSP again and deploy your custom control.
 
-- Mohan