Category Archives: ASP.NET

Minimize JavaScript and CSS – Web Essentials

When working on a Website or Intranet environment and you are using a lot off JavaScript and CSS files you would like to have the possibility to minimize/bundle the files.

On the web you can find a lot of solutions for this, on my last project when I was working on a website based on SharePoint 2013 (http://www.motion10.nl). I found a great extension for Visual Studio called: Web Essentials.

Key features of this extension are:

  • Bundling of JavaScript and CSS files.
  • Minimize files.

 

The extension does much more for example it also display’s a color swatch next to a specified color in you Stylesheet file Glimlach .

CSS Class

For a complete list off the features you can look on the website of Web Essentials.

The extension gives you the option to minimize a JavaScript files by clicking on it with your second mouse button. Once generated it keeps synching your changes to the minimized file (so you will keep working in the normal file).

 

Minimize files

All of the settings of the extension can be managed from the default options menu within the “Web Essentials” category that the extension adds.

Options

In my opinion this extension should be added to the list of items you install on a development environment.

Retrieve the Friendly URL of a Publishing Page

One of my first projects with SharePoint 2013 is building a SharePoint website. For the website we had to build a functionality that display’s the URL of specific pages.

For the website we are using Managed Navigation. Displaying URLs meant we wanted to display the friendly URLS. After searching for a while with ILSpy and looking at some MSDN articles:

I found out that the friendly URL can be retrieved by first getting a list of NavigationTerm items from a SharePoint list item. When you have a NavigationTerm you can retrieve the display URL of that term using the method “GetResolvedDisplayUrl”.

In short the code to retrieve the friendly URLs will look something like this.

public List<string> GetPagesUrls() {
    
    //list for saving the urls
    List<string> retVal = new List<string>();

    //current web
    SPWeb web = SPContext.Current.Web;

    //check if the current web is a publishing weg
    if (PublishingWeb.IsPublishingWeb(web)) {

        //get the pages list id
        Guid listId = PublishingWeb.GetPagesListId(web);

        //retrieve the pages list
        SPList pagesList = web.Lists[listId];

        //itterate trough the pages
        foreach (SPListItem item in pagesList.Items) {
            //retrieve the terms used for the navigation (this can be multiple terms)
            IList<NavigationTerm> terms = TaxonomyNavigation.GetFriendlyUrlsForListItem(item, false);

            string url = string.Empty;

            //check if the pages has terms associated with it
            if (terms.Count > 0) {
                //use the GetResolvedDisplayUrl to retrieve the page friendly urls
                url = terms[0].GetResolvedDisplayUrl(string.Empty);
            } else {
                //if the page does not have any terms get the normal url
                url = item.File.Url;
            }

            retVal.Add(url);
        }
    }
    return retVal;
}

What’s New for SharePoint Development in Visual Studio 2012

Now that the Visual Studio 2012 Release Candidate is released (31 may) it is the question, what kind of new features there are in Visual Studio 2012 when you are looking at SharePoint Development.

Most of the time the release candidates that Microsoft releases contain all of the features that should be in the Final Release.

Some of the new features to facilitate SharePoint Development are:

  • Create Lists and Content Types by Using New Designers
  • Create Site Columns
  • Create Silverlight Web Parts
  • Publish SharePoint Solutions to Remote SharePoint Servers
  • Test SharePoint Performance by Using Profiling Tools
  • Create Sandboxed Visual Web Parts
  • Improved Support for Sandboxed Solutions.
  • Support for JavaScript Debugging and IntelliSense for JavaScript
  • Streamlined SharePoint Project Templates
  • Test Your Code by Using Microsoft Fakes Framework

You can read all about it on this MSDN page:

http://msdn.microsoft.com/en-us/library/ee290856(v=vs.110).aspx

Using the ConditionedActivityGroup in Workflow Foundation 3.5

When you create a SharePoint approval workflow the While activity is often used to check if a Task is approved by placing the “OnTaskChanged” activity within the While Activity.

workflow

When you also want to check if the Moderation status on the workflow item is approved you can’t do this in the same While activity.

If you only check the task status there will be situation in which the item is approved and the approval workflow is still running because the item was approved directly. If you would like to check de moderation status of an item and the task status you can use a “ConditionedActivityGroup”.

The “ConditionedActivityGroup” will cause the workflow to continue when the moderation status is changed or when the status of the task is changed. To use the “ConditionedActivityGroup” drag the activity within the workflow designer.

Workflow_ConditionedActivityGroup

Next drop the activities you want to check within the small window at the top that states “Drop Activities Here”. For our example we will use the “OnTaskChanged” and the “OnWorkflowItemChanged” activities.

Workflow_ConditionedActivityGroup_Activities_2

Open the workflow in code view and add three boolean properties:

  • IsFinished
  • EnableItemChanged
  • EnableTaskChanged
public bool IsFinished { get; set; }

public bool EnableItemChanged { get; set; }

public bool EnableTaskChanged { get; set; }

These properties will be used to activate the conditions within the condition group. The “IsFinshed” property will be used to finish the conditioned group. To activate the conditions we will also have to set the “EnableItemChanged” and “EnableTaskChanged” properties to true within the initialization of the workflow.

/// <summary>
/// Initializes a new instance of the worfklow.
/// </summary>
public Workflow1() {
    InitializeComponent();
    this.EnableItemChanged = true;
    this.EnableTaskChanged = true;
}

 

After writing those lines of code open the workflow designer and select the “ConditionedActivityGroup” and change the “UntilCondition” property of the activity to: Declarative Rule Condition.

Select the “…” at the end of the “ConditionName” property and create a new “Condition”. The value of the condition has to be “this.IsFinished”.

Condition

This will mean that the ConditionedActivityGroup is finished when “IsFinished” equals true.

The next step is to set the “WhenCondition” on the activities that are in the group activity. These properties we also be a “Declarative Rule Condition” and set the condition values to “this.EnableTaskChanged” for the task activity and “this.EnableItemChanged” for the item activity.

Besides this we will also set the “Invoked” property of the activities to perform a code action when the event take place (You can also let Visual Studio do this by double clicking the activities).

 

WhenCondition

 

With all this in place when can start to write some code for the invoke methods. Because the “WhenCondition” mean that when they are set to true these conditions can occur. We will have to set these properties to true each time a Condition is met because the Workflow instance will automatically set them to false. In our example this will occur when the task status is set to approved or the item is approved.

public const string FieldId = "YourFieldID";

/// <summary>
/// Tasks the item changed.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Workflow.Activities.ExternalDataEventArgs"/> instance containing the event data.</param>
private void TaskItemChanged(object sender, ExternalDataEventArgs e) {
    //retrieve the task and check its status
    SPListItem task = workflowProperties.TaskList.GetItemById(CreateTaskActivity.ListItemId);
    string status = task[YourFieldID] != null ? task[YourFieldID].ToString() : string.Empty;

    if (status.ToUpperInvariant() != "PENDING") {
        IsFinished = true;
        EnableTaskChanged = false;
    } else {
        IsFinished = false;
        EnableTaskChanged = true;
    }
}

/// <summary>
/// Workflows the item changed.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Workflow.Activities.ExternalDataEventArgs"/> instance containing the event data.</param>
private void WorkflowItemChanged(object sender, ExternalDataEventArgs e) {
    //View the moderation status of the workflow item
    SPModerationStatusType type = workflowProperties.Item.ModerationInformation.Status;
    Status = type.ToString();
    if (type == SPModerationStatusType.Approved || type == SPModerationStatusType.Denied) {
        IsFinished = true;
        EnableItemChanged = false;
    } else {
        IsFinished = false;
        EnableItemChanged = true;
    }
}

 

When you set the “IsFinished” property to true the “ConditionedActivityGroup” will finish. And by setting the “EnableItemChanged” and the “EnableTaskChanged” property to true you inform the “ConditionedActivityGroup” that that condition can occur again.

Creating a SharePoint Designer Action for the Sandbox

One of the new features in SharePoint 2010 was the possibility to create Sandbox solutions. Sandbox solutions are custom build solutions that run in another process with another CAS policy.

Sandbox solutions allow you to do the following:

  • Deploy custom code to you site collection when you do not have access to Central Administration.
  • Sandbox solutions cannot jeopardize the stability of your farm.
  • With SharePoint in a hosted environment you will be able to deploy Sandboxed solutions.

With the ability to deploy Sandbox solutions you also have some important restrictions:

  • A certain part off the SharePoint API is not available.
  • You cannot read/write to the file system.
  • You cannot call assemblies deployed out of Global Assembly Cache.

After all Sandbox solutions are a powerful feature of SharePoint. SharePoint designer gives you the possibility to develop Custom actions. But when you try to develop those for the sandbox it is totally different.

Let’s start of by creating a empty SharePoint project. When you created a empty project add a new Class file. Mark the class public and add a method that returns a Hashtable that has a SPUserCodeWorkflowContext object as parameter. The Hashtable will give you the ability to return values in the workflow. The SPUserCodeWorkflowContext on the other hand is a ‘In’ parameter.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using Microsoft.SharePoint.UserCode;
using Microsoft.SharePoint;

namespace Motion10.SharePoint.Sandbox.Designer
{
    public class SPCreateSubSiteAction
    {
        public Hashtable CreateSubSite(SPUserCodeWorkflowContext context)
        {
        }
    }
}

In the above code example you see that I created a method called ‘CreateSubSite’ within this method you can add the logic of your custom action. In the upcoming examples we will create a action that creates a sub site.

To add the custom action to SharePoint you have to create a new elements file in which you have  to specify the custom action.

<WorkflowActions>
  <Action Name="Create Sub Site"
          SandboxedFunction="true"
          Assembly="$SharePoint.Project.AssemblyFullName$"
          ClassName="Motion10.SharePoint.Sandbox.Designer.SPCreateSubSiteAction"
          FunctionName="CreateSubSite"
          AppliesTo="all"
          Category="Motion10 Designer Actions">
  </Action>
</WorkflowActions>

To be able to add parameters to the method that you need to create a sub site we will have to define a ‘RuleDesigner’ section to enable users to fill in those parameters.

<RuleDesigner Sentence="Create sub site with the title: %1, url: %2 and description: %3.">
  <FieldBind Field="Title" Text="Title" Id="1" DesignerType="TextBox" />
  <FieldBind Field="Url" Text="Url" Id="2" DesignerType="TextBox" />
  <FieldBind Field="Description" Text="Description" Id="3" DesignerType="TextBox" />
</RuleDesigner>

The ‘RuleDesigner’ section has to be placed within the ‘Action’ section. In the ‘Action’ section you also have to place a ‘Parameters’ section to pass the actual values in the workflow action.

<Parameters>
  <Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext, Microsoft.SharePoint.WorkflowActions" Direction="In" DesignerType="Hide" />
  <Parameter Name="Title" Type="System.String, mscorlib" Direction="In" DesignerType="ParameterNames" />
  <Parameter Name="Url" Type="System.String, mscorlib" Direction="In" DesignerType="ParameterNames" />
  <Parameter Name="Description" Type="System.String, mscorlib" Direction="In" DesignerType="ParameterNames" />
</Parameters>

With all of this in place we can extend our method with the correct parameters and create a simple action to create a sub site.

public Hashtable CreateSubSite(SPUserCodeWorkflowContext context, string Title, string Url, string Description)
{
    //hashtable that will be returned can be used for return values.
    Hashtable retVal = new Hashtable();

    using (SPSite site = new SPSite(context.CurrentWebUrl))
    {
        using (SPWeb web = site.OpenWeb())
        {
            try
            {
                using (SPWeb newWeb = web.Webs.Add(Url, Title, Title, 1033, web.WebTemplate, false, false))
                {
                    SPWorkflow.CreateHistoryEvent(web, context.WorkflowInstanceId, 0, web.CurrentUser, TimeSpan.Zero, "Information", "Sub site created from a Sandbox activity", string.Empty);
                }
            }
            catch (Exception ex)
            {
                SPWorkflow.CreateHistoryEvent(web, context.WorkflowInstanceId, 0, web.CurrentUser, TimeSpan.Zero, "Error", ex.Message,string.Empty );
            }
        }
    }
    return retVal;
}

Make sure you add the elements file to feature that is scoped to ‘Site’ and deploy the Sandbox solution. Open SharePoint Designer and you will see that you have the action available!

.NET Library for quick and easy Twitter integration

A few days ago I wanted to create a solution to automatically tweet new blog posts. Because I did not have enough time to write a custom component to communicate to twitter I started looking for a .NET Twitter library.

After some time I found a very simple and effective library named Twitterizer. With Twitterizer you can easily implement the OAuth security mechanism.

After adding the reference to the Twitterizer library I created a ItemEventReceiver that starts on the ItemAdded event. In that event I post the title and the url to twitter.

public override void ItemAdded(SPItemEventProperties properties)
{
    base.ItemAdded(properties);

    string message = string.Format(CultureInfo.InvariantCulture, "New post #msftplayground :{0} - {1}", ToTinyURLS(properties.Web.Site.Url, properties.ListItem), properties.ListItem.Title);

    //TODO Get OAuth from web
    OAuthTokens tokens = GetTwitterToken(properties);
    TwitterResponse<TwitterStatus> response = TwitterStatus.Update(tokens, message);
}

private OAuthTokens GetTwitterToken(SPItemEventProperties properties)
{
    OAuthTokens retVal = null;
    
    string consumerKeySecret = EncryptionUtility.DecryptedString(properties.Web.GetPropertyBagProperty(Constants.PropertyBagKeyConsumerKeySecret, string.Empty));
    string consumerKey = EncryptionUtility.DecryptedString(properties.Web.GetPropertyBagProperty(Constants.PropertyBagKeyConsumerKey, string.Empty));
    string accessToken = EncryptionUtility.DecryptedString(properties.Web.GetPropertyBagProperty(Constants.PropertyBagKeyAccessToken, string.Empty));
    string accessTokenSecret = EncryptionUtility.DecryptedString(properties.Web.GetPropertyBagProperty(Constants.PropertyBagKeyAccessTokenSecret, string.Empty));

    if (!string.IsNullOrEmpty(consumerKeySecret) | !string.IsNullOrEmpty(consumerKey) | !string.IsNullOrEmpty(accessToken) | !string.IsNullOrEmpty(accessTokenSecret))
    {
        retVal  = new OAuthTokens();
        retVal.AccessToken = accessToken;
        retVal.AccessTokenSecret = accessTokenSecret;
        retVal.ConsumerKey = consumerKey;
        retVal.ConsumerSecret = consumerKeySecret;
    }
    return retVal;

}

In the code above you see the registration of the event. Within the event I retrieve the OAuthTokens for the security to Twitter. The tokens I need for the authentication are saved within the property bag of the current web.

As you can see in the code it is quite easy to post a status update to twitter with Twitterizer. On the site you can find more examples:

http://www.twitterizer.net/

Fully certified SharePoint 2010 Specialist (MCPD & MCITP)

​It took me long enough to get all off the SharePoint certificates but Yesterday I finally passed the last exam.

I know have the following SharePoint 2010 certificates:

  • 70-573: MCTS: Microsoft SharePoint 2010, Application Development
  • 70-667: MCTS: Microsoft SharePoint 2010, Configuring
  • 70-668: PRO: Microsoft SharePoint 2010, Administrator
  • 70-576: PRO: Designing and Developing Microsoft SharePoint 2010 Applications

I have to say that 70-668 was the hardest exams of them all. But I think that everyone that has enough experience with SharePoint can pass these exams you just have to filter out the wrong answers.

For now I will take a few months of rest in which I will move to my new house in Vlaardingen and wait till the moment my lovely girlfriend will give birth to our son/daughter.

And then I will go for the .NET Framework 3.5 exams especially (.NET Framework 3.5, Windows Workflow Foundation Applications (70-504)).

Encoding SharePoint Field names.

The last couple of project I have been asked the same question several times. The question was how can you get the normal name from a SharePoint field name that is encoded like this: Test_x0020_ Name.

The field names get encoded because XML elements names can’t contain spaces or other different characters. In the example above the x0020 represents the space and the _ represents a delimiter.

You can decode these fields by using:

System.XML.XmlConvert.DecodeName("[Fieldname]") ;

You can encode fieldnames if you would like by using:

System.XML.XmlConvert.EncodeName("[FieldName]")

Console Application for SharePoint 2010 [No User Profile Application available to service the request. Contact your farm administrator.]

Today I was working on some cool features to update the User Profile store in SharePoint 2010. To test this feature I usually use a Console Application. In my Console Application I was keep getting an error on a line like below:

UserProfileManager profileConfigManager = new UserProfileManager(ServiceContext);

The exception I kept getting was : ‘No User Profile Application available to service the request. Contact your farm administrator.’ I made sure the User Profile Application was running correctly and it was. I already clicked on the “Administrators” button in the toolbar of the Service Application to give me Full Control, but it still wasn’t working.

Till I noticed that there is also a ‘Permissions’ button. I clicked the button and saw that my current user wasn’t in the permissions box. I gave my user ‘Full Control’ and now everything works great from the console application.

Happy Coding!

Sitemap Provider for Community Server 2.1

For my new blog I had to create a sitemap provider to provide my content to several search engines.

Because I did not find any solution on the internet I thought I would share my solution with you guys:

You can download the source here: MSFTPlayground.Sitemap.zip

The provider is meant for one blog. In the definitions file within the solution you can change the properties for you blog. You only have to add a httphandler to your web.config just like it is done in the file “web.config(extension)” within the solution.

Let me know what you guys think of this provider.