A nearshore team from Uruguay, South America (GMT-3) UruIT Blog

Some days ago, I faced an issue regarding CRM audit feature. A customer was unable to close an active case since there was an open activity related to it. Then I told him to close all open activities before closing a case because that`s the way it works. However, he was unable to close the activity because CRM had experienced an error.

The activity that my customer was trying to close was a draft email (in fact, he wanted to delete the email, but he was unable to, though). When I took a look at it, I found that some recipients (highlighted in red) were not resolved in CRM.The exception was related to the Audit feature enabled by me a couple of days before the user had this error. The plug-in that registers the changes on the entities tried to establish a relationship between the recipients of the e-mail (fields To, CC and BCC) and some existent contact or account in CRM, which in fact, they don't exist in CRM.Just by looking at the server log, you can confirm this: 

“The Web Service plug-in failed in OrganizationId: 0d469757-a137-46d1-8f38-12a6d65f79a5; SdkMessageProcessingStepId: b92673ed-dc92-442b-a6c6-82f2fce14585; EntityName: email; Stage: 25; MessageName: Delete; AssemblyName: Microsoft.Crm.AuditMonikerMessagesPlugin, Microsoft.Crm.Audit, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35; ClassName: Microsoft.Crm.AuditMonikerMessagesPlugin; Exception: Unhandled Exception: System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at Microsoft.Crm.AuditHelper.GetXrmValue(Object attribute)
at Microsoft.Crm.AuditMonikerMessagesPlugin.BuildDeleteData(StringBuilder attributeMaskBuilder, StringBuilder changeDataBuilder, Entity preEntity, EntityMetadata entityMetadata, IPluginExecutionContext context)
at Microsoft.Crm.AuditMonikerMessagesPlugin.BuildChangeData(String& attributeMask, EntityMetadata entityMetadata, IPluginExecutionContext context)
at Microsoft.Crm.AuditBase.LogAuditData(IPluginExecutionContext context, Guid objectId, Boolean allowEntityOnlyAudit, Entity entity, EntityMetadata entityMetadata)
at Microsoft.Crm.AuditMonikerMessagesPlugin.Execute(IServiceProvider serviceProvider)
at Microsoft.Crm.Extensibility.V5PluginProxyStep.ExecuteInternal(PipelineExecutionContext context)
at Microsoft.Crm.Extensibility.VersionedPluginProxyStepBase.Execute(PipelineExecutionContext context)

My workaround to this problem was to disable the audit feature for the fields To, CC and BCC of the e-mail entity.

I hope this helps.

Nicolás Brandl

When installing SharePoint solutions in production environments, configuration often leads to assorted complications. Making installation manuals for non-technical customers, adding configuration parameters to the web.config file, or adding any necessary configuration of third-party components by hand, are things that can be avoided by managing the configuration matters within the solution to be delivered without requiring any manual configuration, all through SharePoint API.

This can be accomplished with a feature with farm scope, which is responsible for changing settings in the web.config. This feature should have FeatureActivated and FeatureDeactivating event receivers in order to add / remove configuration values ​​to the web.config all through SharePoint API.

Then we should create a feature dependency between the configuration feature and the rest of the features in the solution, so that they cannot be activated before activating the farm scoped feature which is the one that provides the necessary configuration (adding it to the web.config) for your solution to work.

Here’s an example event receiver:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    SPSecurity.RunWithElevatedPrivileges(() =>
    {
        string owner = this.GetType().FullName;

        SPWebConfigModification chartImageAppSetting = new SPWebConfigModification();
        //XPath to parent element in which i want to add the child node
        chartImageAppSetting.Path = "configuration/appSettings";
        //XPath that identifies the element I am adding so it can be correctly updated or deleted afterwards
        chartImageAppSetting.Name = "add[@key='ChartImageHandler']";
        chartImageAppSetting.Sequence = 0;
        chartImageAppSetting.Owner = owner;
        chartImageAppSetting.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
        //XML node to add in the web.config
        chartImageAppSetting.Value = "<add key='ChartImageHandler' value='storage=memory;deleteAfterServicing=true;' />";

        SPWebConfigModification chartImageSystemWebHttpHandler = new SPWebConfigModification();
        chartImageSystemWebHttpHandler.Path = "configuration/system.web/httpHandlers";
        chartImageSystemWebHttpHandler.Name = "add[@path='ChartImg.axd']";
        chartImageSystemWebHttpHandler.Sequence = 0;
        chartImageSystemWebHttpHandler.Owner = owner;
        chartImageSystemWebHttpHandler.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
        chartImageSystemWebHttpHandler.Value = @"<add path='ChartImg.axd' 
                    verb='GET,HEAD,POST' 
                    type='System.Web.UI.DataVisualization.Charting.ChartHttpHandler, 
                          System.Web.DataVisualization, 
                          Version=3.5.0.0, 
                          Culture=neutral, 
                          PublicKeyToken=31bf3856ad364e35' 
                    validate='false' />";                               

        //Add the SPWebConfigModifications to the ContentService
        SPWebService service = SPWebService.ContentService;                 
        service.WebConfigModifications.Add(chartImageAppSetting);
        service.WebConfigModifications.Add(chartImageSystemWebHttpHandler);
        service.WebConfigModifications.Add(chartImageSystemWebServerHandler);
        service.Update();
        //All the modifications are applied to the web.configs in the farm
        service.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
    });          
}

 

Thanks for reading!

Federico Rodriguez

Hi! In this post we will see how to consume oData from Android. oData is an open web protocol for querying and updating data that has become very popular lately due to it’s simplicity and availability of tools and libraries.

1. To consume oData from an Android application we will use a library called “Restlet”. It can be downloaded from here: http://www.restlet.org.
Note: We will use the JRE Restlet libraries and the Android Restlet libraries so you will have to download both.

2. Once you downloaded both libraries the first step is to create a Java program to auto-generate the entities and the proxy service that will be used to consume oData from our Android application. The Restlet libraries can automatically generate the entity classes to access the oData service but that functionality isn’t available in the Android Restlet libraries, so we first need to generate a Java project and use the JSE Restlet libraries to generate the entities.

3. So, create a new Java project within Eclipse and add the external JSE jars.

Untitled

This is done by right clicking on the project -> Build Path -> Configure Build Path. Click on Add External JARS.. and go to the folder where Restlet was installed (by default C:\Program Files (x86)\Restlet Framework\Edition Java SE\2.0.4\lib). Add the following libraries:

  • org.restlet.jar
  • org.restlet.ext.odata.jar
  • org.restlet.ext.freemarker.jar
  • org.restlet.ext.atom.jar
  • org.restlet.ext.xml.jar
  • org.freemarker_2.3\org.freemarker.jar

Untitled

4. Then create a Main class and add the following code:

Generator.main(new String[] {
"[service url]",
"[folder path]"
});
  • [service url] – Url of the oData service
  • [folder path] – Folder path where the Generator will copy the auto-generated classes

Untitled

5. Run the project and go to the [folder path], you will see a class in the root of the folder (this is the proxy service) and a folder in the root with all the entities of the service within.

6. After that we have the proxy and the entities ready to be used from our Android App.

7. Import classes to our Android Project: Right click on the src folder, Import->File System and select the [folder path].

Untitled

8. How to use the auto-generated classes?

a. First of all we need to reference the Android Restlet jars (by default C:\Program Files (x86)\Restlet Framework\Restlet Framework\Edition Android\2.0.4\lib). Add these libraries:

  • org.restlet.jar
  • org.restlet.ext.odata.jar
  • org.restlet.ext.atom.jar
  • org.restlet.ext.xml.jar
  • org.restlet.ext.net.jar

b. After creating an instance of the proxy, you are ready to call any method you want:

IDataServiceProxy proxy = new DataServiceAtomPubProxyImpl(DataServiceClient.URL);

9. That’s it! Here is a screen capture of our Android App consuming oData:

Untitled

 

Now we will see some examples that show how to work with the proxy we just created.

 

The following example gets all the café entities and displays some of their properties:

TestAssociationOneToOneService service = new TestAssociationOneToOneService();
Query<Cafe> query = service.createCafeQuery("/Cafes");
for (Cafe Cafe : query) {
System.out.println(“id: ” + Cafe.getID());
System.out.println(“name: ” + Cafe.getName());
}

The following example gets a single entity and displays some of its properties:

Query<Cafe> query = service.createCafeQuery("/Cafes('1')");
Cafe Cafe = query.iterator().next();
System.out.println(“id: ” + Cafe.getID());
System.out.println(“name: ” + Cafe.getName());

Add a new entity:

Cafe Cafe = new Cafe();
Cafe.setID("3");
Cafe.setZipCode(12345);
Cafe.setName("Bar des sports");
Cafe.setCity("Paris");
service.addEntity(Cafe);

Delete an Entity:

Query<Cafe> query = service.createCafeQuery("/Cafes('1')");
Cafe Cafe = query.iterator().next();
service.deleteEntity(Cafe);

Get a single Entity and its associated entities:

Query<Cafe> query = service.createCafeQuery("/Cafes('1')").expand("Item");

 

Conclusions

We saw that is relatively easy to query and update data exposed by oData using the Restlet library. This article together with Consuming OData from iPhone and Consuming OData from Windows Phone7 conform our series of articles on how to consume oData from mobile applications. oData is definitely an important tool to consider when architecting multi platform service oriented applications.

 

I hope you liked the article. Thanks for reading!

Diego Acosta

Introduction


There comes a time in the life of every .NET developer when you need Visual Studio to do something that
can only be described as a "class breakpoint": a quick command to set a breakpoint on every access to a class.
Unfortunately, after googling this concept, you'll find out that there's no easy way to accomplish this in Visual Studio.
In this article I present an addin that I created, which adds this and another similar command to the debug menu of the
development environment:

ConsoleApplication1 - Microsoft Visual Studio (Administrator)_2011-08-03_20-40-57

When the command is activated, it sets a breakpoint on every function and property of every class in the current document:

ConsoleApplication1 - Microsoft Visual Studio (Administrator)_2011-08-03_20-38-46

 

This addin can be downloaded here: Installer | Source code


Also, note that this addin is language agnostic, meaning that it will work for C#, Visual Basic, and even native C++ applications.

In the rest of the article I'll show the basic steps to create a simple addin for Visual Studio 2010.

 

Creating an addin project

New Project_2011-08-03_20-48-32

Visual Studio makes it easy to create an addin project by providing a template. In the New project dialog,
select Other project types, extensibility, Visual Studio Add-In.
You'll see that a very simple project is created, with the core logic around a class named Connect. This class manages
the lifecycle of the addin through the methods OnConnection, OnDisconnection, etc.
The class field _applicationObject holds a DTE2 object through which we communicate with the environment.

 

Handling events

In this particular case we want to add a command to the Debug menu after a solution is loaded. Therefore, we will need
to wait until a solution is loaded. All the solution events are exposed through the DTE2.Events.SolutionEvents object:

    _solutionEvents = _applicationObject.Events.SolutionEvents;  
    _solutionEvents.Opened += new _dispSolutionEvents_OpenedEventHandler(OnSolutionOpened);
    _solutionEvents.AfterClosing += new _dispSolutionEvents_AfterClosingEventHandler(OnSolutionClosed);

There's a minor caveat here. I'm keeping the reference to the SolutionEvents object in a field of the Connect class.
If I didn't do this, the SolutionEvents object would be deleted by the garbage collector, and the events would never
be raised.

Adding commands

Once that we handle the opening event, we need to add the command to the user interface:

    object[] contextGUIDS = new object[] { };  
    Commands2 commands = (Commands2)_applicationObject.Commands;
    string debugMenuName = "Debug";
    //Place the command on the debug menu.  
    //Find the MenuBar command bar, which is the top-level command bar holding all the main menu items:

    Microsoft.VisualStudio.CommandBars.CommandBar menuBarCommandBar =
        ((Microsoft.VisualStudio.CommandBars.CommandBars)_applicationObject.CommandBars)["MenuBar"];
    //Find the Debug command bar on the MenuBar command bar:   
    CommandBarControl debugControl = menuBarCommandBar.Controls[debugMenuName];
    CommandBarPopup debugPopup = (CommandBarPopup)debugControl;
    _command = 
        commands.AddNamedCommand2
        (
            _addInInstance,
            "CommandName",
            "Text to show in the menu",
            "Description of the command",
            true,
            Type.Missing,
            ref contextGUIDS,
            (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled,
            (int)vsCommandStyle.vsCommandStylePictAndText,
            vsCommandControlType.vsCommandControlTypeButton
        );
      
    _command.AddControl(debugPopup.CommandBar, 1);

This code grabs the Debug menu and adds the command with the specified parameters. This code should be wrapped in a
try-catch block to handle cases when the command already exists in the menu.
We can also add a keyboard shortcut to the command in the following way:

    _command.Bindings = "Text Editor::ctrl+d, z"; 

Here "Text Editor" defines the scope of the shortcut. For more information see http://msdn.microsoft.com/en-us/library/envdte.command.bindings.aspx

 

Browsing the code

Visual Studio automatically parses the current document and exposes a nice interface to browse the code. A code document
contains a tree of code elements. Each code element can be a namespace, a class, a method, etc, and it contains a
collection of child code elements in it. The root code elements can be accessed in this way:

    CodeElements elementsInDocument = this._applicationObject.ActiveDocument.ProjectItem.FileCodeModel.CodeElements 

   
To show the browsing algorithm, here's a recursive method that shows how to get all the classes in the current document:
   

    private static void RecursiveClassSearch(CodeElements elements, List<CodeClass> foundClasses) 
    {
        foreach (CodeElement codeElement in elements)
        {
            if (codeElement is CodeClass)
            {
                foundClasses.Add(codeElement as CodeClass);
            }
            RecursiveClassSearch(codeElement.Children, foundClasses);
        }
    }
   

 

Managing breakpoints

Managing breakpoints is very straighforward. The interface exposed through this._applicationObject.Debugger.Breakpoints
is pretty self descriptive, and it contains functionally to add, remove and browse through breakpoints.

 

Installer

Once you finished you addin, the best way to distribute it is to use a Visual Studio Installer project. An addin consists
of only two files: an *.AddIn xml file and a dll. The easiest way to distribute them is to install them in the same
directory, anywhere on the target machine (might be in ProgramFiles), and to add that directory to the addins directories
of Visual Studio. The latter can be done easily with a registry key: In the registry editor window of your installation
project, add a string key at "HKLM\Software\Microsoft\VisualStudio\10.0\AutomationOptions\LookInFolders" with the name
[TARGETDIR] and a descriptive name in the value. The installer will resolve the [TARGETDIR] placeholder at runtime.

 

Download

This addin can be downloaded here: Installer | Source code

 

CodePlex project

Here's the CodePlex site for this project: http://breakall.codeplex.com

 

Conclusions

In this article I presented a useful addin for Visual Studio and I also showed how to create customs addins. For more information on creating addins you can visit the MSDN: http://msdn.microsoft.com/en-us/vstudio/ff677564. I hope you find the addin useful as I do (maybe I'll publish a second version in the future) and I hope to see your great addins soon!

Thanks for reading!
Alfonso Cora

Overview

This article describes the specific problem of creating a control in SharePoint, which will be located on an HTTP page and securely signs in a user through an SSL connection using HTTPS. Although the solution uses SharePoint exclusively, it can be easily modified for ASP.NET environments.

The problem

With the requirement that the user data should transferred securely to the server, the idea of a postback becomes unfeasible. At that point one might come with the idea of an asynchronous and secure request that carries the user data.

Those of you have worked with AJAX, might have stumbled upon asynchronous requests with jQuery more than once. While this type of requests allows building very rich internet applications, most of them have a key restriction regarding protocols and domains. Common requests cannot retrieve data from a different domain than the one hosting the application, and the protocol for the request must also be the same as the one used to retrieve the page.

Knowing of these limitations, our mind is focused to those AJAX requests that allow cross-protocol calls.

JSONP at the rescue

JSONP is an extension to the well known standard JSON, where the added "P" stands for "Padding". The padding is usually a JavaScript function call (might be any JavaScript code too) that is added by the server as a prefix to the data returned. These are two requests and responses from a server in both, JSON and JSONP formats:

JSON request:

        http://example.com/planets?json=true&planetid=4

JSON response:

        {
            "id" : 4,
            "name" : "Mars",
            "satellites" : 2
        }

JSONP request:

        http://example.com/planets?jsonp=true&planetid=4&jsonpcallback=callthisfunction

JSONP response:

        callthisfunction({            
            "id" : 4,
            "name" : "Mars",
            "satellites" : 2
        })     

As you can see, the only differences between both requests, is the "jsonpcallback" parameter, which is used as a function call to wrap the data in the response. This parameter can actually have any name, but in order to make it work with jQuery, it needs to end with the suffix "callback".

So, when a web page has a script tag with the previous request as the source, JSONP comes to life

        <script type="text/javascript" src="http://example.com/planets?jsonp=true&planetid=4&jsonpcallback=callthisfunction"></script>

Script tags can bring scripts from any domain, using any protocol. Using the previous script tags, not only brings the data from the server, but also calls

the callback function, allowing the client to run any desired code.

 

Putting all together

Now that we know the power of JSONP, we can use it to design our solution. On the client side, we will use a web part that uses jQuery to perform the request. On the server side, we will have an ASP.NET handler (.ashx) that logs the user in, or returns an error if the user or password supplied are invalid.

Let's begin with the server side. To publish the handler from SharePoint, we need the ashx file to look something like this:

    <%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    <%@ Assembly Name="MyNamespace", Version=1.0.0.0, Culture=neutral, PublicKeyToken=a39c10d65c32c9c1, processorArchitecture=MSIL" %> 
    <%@ WebHandler Language="C#" Class="MyNamespace.MyHandler" %>
 

For the code file, we will use the SharePoint method "SPClaimsUtility.AuthenticateFormsUser" to perform the login. But also, we have to return a JSONP

response indicating whether that method succeeded or not. Let's see the easiest way of doing it:

    public partial class MyHandler : IHttpHandler
    {
        public bool IsReusable
        {
            get { throw new NotImplementedException(); }
        }
 
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/html";
            context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
            // Parse the JSON callback
            string callback = context.Request["callback"] ?? string.Empty;
            callback = Regex.Replace(callback, @"[^a-zA-Z0-9\?]", "");
            string user = context.Request["User"];
            string password = context.Request["Password"];
            if (SPClaimsUtility.AuthenticateFormsUser(context.Request.Url, user, password))
            {
                context.Response.Write(callback + "({ \"result\" : true });");
            }
            else
            {
                context.Response.Write(callback + "({ \"result\" : false });");
            }
        }
    }

From this code, you can see how we parse the "callback" parameter, parsing the basic characters on it, and we use it to send the response to the client, which is an object containing only the "result" boolean property.

Another thing interesting in this code is the "Access-Control-Allow-Origin" header, which filters the domains that can request data from this server. By using the character "*", we are allowing any domain to request data from our server.

Now, let's see the client side. When a user enters his information in the "txtUser" and "txtPassword" fields, this script does the trick:

        function onLogin(evt, message) {
            var user = $("#txtUser").attr("value");
            var password = $("#txtPassword").attr("value");
            $.getJSON(
                https://example.com/_layouts/MyNamespace/MyHandler.ashx?callback=?,
                {
                    User: user,
                    Password: password
                },
                function (data) {
                    if (data.result) {
                        // Login succeeded, redirect to home page:
                        window.location = "https://example.com/default.aspx"; 
                    }
                    else {
                        // Login failed, show error message without leaving the page:
                        document.getElementById('lblLoginResult').innerHTML = "Wrong Userid or Password";
                    }
                }
            );
        }

 

To perform a JSONP request in jQuery, we just perform a normal JSON request. jQuery automatically detects the string "callback=?" in the url and

performs the request as JSONP. The function we supplied as the callback, is called with a JavaScript object, which is parsed by jQuery from the response

sent by the server.

We now have both sides working. We have built a login control that works on every browser, protects the users' security, and efficiently uses

HTTP/HTTPS protocols.

 

Error handling

Although some of the errors can be seen on the browser's error console, there is no way to handle JSONP errors in JavaScript. This is one of the main drawbacks of the protocol. When an error occurs, it just fails silently.

 

Security concerns

As we saw, JSONP is a powerful tool that makes possible some scenarios that would otherwise be unfeasible. However, it should be used with extreme care, especially with cross domain requests. Remember that the padding is nothing more than JavaScript code that will be run by the user's browser. This gives the external server, the possibility to send a malicious script to start an attack.

 

Conclusions

We have seen JSONP in action, resolving a specific problem in a very simple way. However, we also saw the drawbacks of this approach. Like any other tool, it is useful to keep in mind how powerful it is, the kind of problems it addresses, and the weak points it presents.

 

Thanks for reading!

Alfonso Cora

marketplace Download PhoneSocial+ from the marketplace
pspluslogo

PhoneSocial+ is a new application for Windows Phone that lets you read your tweets from your phone. With PhoneSocial+ you will be able to:

  • Connect to your Twitter account to see your tweets, mentions list, inbox and favorites.
  • Listen to your tweets and private messages.
  • Send tweets, private messages, reply, or retweet them.
  • Add tweets to favorites to review them later.
psplus1 psplus2 psplus3
marketplace Download PhoneSocial+ from the marketplace
twitter Follow PhoneSocial+ on Twitter!

[Click here to download sample code for this article]

Introduction

ListBox grouping is one of the features that Silverlight did not inherit from WPF, even though is a common requirement. Here we present a very simple yet powerful way to implement grouping in the ListBox control that also allows subgrouping and sorting.

This approach is supported on traditional Silverlight applications, and also on Windows Phone 7 applications.

 

Untitled2 Untitled

 

The problem

Although WPF supports grouping for the ListBox control, Silverlight doesn’t. The developer is restricted to load a plain, unstructured collection of items. However, the hierarchical scenario is very common in applications that display different types of data.

The solution

To overcome this issue, we will use a Binding Converter, which will group the items internally, adding to the ListBox a ContentControl element with a specific template, for each group header it creates, and a ContentControl with another template, for each item on each group it creates. Sounds complicated? It’s not, let’s do it!

Suppose you have a list of items that you want to display hierarchically. You proceed by creating the ListBox and binding its ItemsSource dependency property to the collection of items. In XAML it would look like this:

<ListBox x:Name="List" ItemsSource="{Binding}"/>

And the code-behind would look like this:

IEnumerable<ItemType> items = ...;

List.DataContext = items;

At this point, the ListBox shows the list of items without any structure. Now, let’s add a Converter to the binding. A converter is an instance of a class that implements IValueConterter, which has only two methods: Convert and ConvertBack. Before Silverlight binds the collection of items, it will call the Convert function, allowing us to transform the data as we want. The ConvertBack method will never be called for this type of binding, since this is a OneWay binding. For more information about data bindings, see http://msdn.microsoft.com/en-us/library/ms752347.aspx

So, all we need is a new class that implements the IValueConverter interface. In this case, “PetGrouper”:

public class PetGrouper : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        // ...
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Because ConvertBack will never be called, we can leave it untouched, throwing a NotImplementedException. For the Convert method, we already know the type of data we are assigning to the DataContext. That same instance comes as an object in the value parameter. We can ignore the rest of the parameters in this case.

Next, we have to group and sort the data. For each group we create, we will add a control with a template designed for headers, and for each one of its items, we will add a control with a template designed for items.

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    IEnumerable<Pet> pets = value as IEnumerable<Pet>;
    List<ContentControl> groupedPets = new List<ContentControl>();
    foreach (IGrouping<string, Pet> animal in pets.GroupBy(x => x.Animal).OrderBy(x => x.Key))
    {
        groupedPets.Add(new ContentControl() { Content = animal.Key, ContentTemplate = App.Current.Resources["AnimalTemplate"] as DataTemplate });
        foreach (Pet pet in animal.OrderBy(x => x.Breed))
        {
            groupedPets.Add(new ContentControl() { Content = pet, ContentTemplate = App.Current.Resources["BreedTemplate"] as DataTemplate });
        }
    }
    return groupedPets;
}

AnimalTemplate and BreedTemplate are resources in App.xaml. In this example we are grouping the pets by animal type, sorting the groups by animal type name, and sorting each item on the groups by breed name.

The type IGrouping<string, Pet>, describes a list of groups whose headers (“keys”) are strings, and each one of them is populated by pets. The Key type may vary for different scenarios. For example if we were grouping by vertebrates and invertebrates, the Key would be a bool value, and we would have to add a significant text to the header content, so it doesn’t show “True” and “False”.

As you may note, this approach is unrestricted as to how the data is shown. You can group items on several levels, sort the items by any property, and even sort the groups themselves.

Finally, we have to link our converter to the binding. This is done by adding a resource in the page containing the ListBox, and linking the binding to that resource:

<UserControl.Resources>
    <local:PetGrouper x:Key="PetValueConverter"></local:PetGrouper>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
    <ListBox x:Name="List" ItemsSource="{Binding Converter={StaticResource PetValueConverter}}" />
</Grid>

Sample application

Here is a sample application that implements grouping and sorting in a ListBox.

The solution contains two projects: a traditional browser application, and a Windows Phone 7 application.

Conclusion

Even the Silverlight ListBox does not have native support for structured data; we can use a binding converter to customize the binding, creating the layout that best fits our case. We have seen that this approach is simple, straightforward, and yet incredible powerful, and it’s supported on classic Silverlight applications and Phone applications.

 

Alfonso Cora

Hi,

We have seen in the previous post how to consume OData services from Windows Phone 7, this time I want to show you how to do it from an iPhone.

1. To consume OData from an iPhone App I have used a library called “OData Client for Objective-C”. It can be downloaded from here: http://odataobjc.codeplex.com/

The library contains some examples using the Netflix Catalog that can help you get familiar with more advanced stuffs than what are going to be explained in this article.

2. Once you downloaded the library the first thing you have to do on XCode is to add the references to the OData library.

This is done by accessing the Project Properties:

clip_image002

3. On the Build tab of the Properties window locate the section “Search Paths” and add the following reference in “Header Search Paths” and “Library Search Paths”:

clip_image004

Also make sure that you selected the recursive checkbox to both paths.

4. After both paths are added you need to add the library to the Frameworks folder of the solution, looking into the file system for the libMSODataLib.a located at this relative path inside the OData SDK folder: “/framework/bin/odatalib/lib/iPhoneSimulatorLibs/iPhone_Simulator_4.1/release/libMSODataLib.a”

clip_image006

5. After that’s done you will have the library for the project ready to be used.

6. Creating the proxy class.

To connect to OData you need to generate the proxy class. To do that open terminal, navigate to the folder where the odatagen executable is located and run this command:

./odatagen /uri=http://domain.com/YourService.svc /out=/Development/odataproxy

On the folder odataproxy you will find the generated proxy, now you need to import the “.h” and “.m” file into the classes folder of the project.

7. After that’s ready, use the proxy to connect to the server at any of the classes.

In this example, I assume that the proxy generated is called CustomersEntities.

With the next line you will have the proxy connected to the server:

CustomersEntities *proxy = [[CustomersEntities alloc]initWithUri:@”URL TO SERVICE” credential:nil];

And to get data simply do the following:

NSArray *customers;

customers = [proxy Customers];

With this example you will have a list of Customers loaded using OData services.

Of course, you can run much more complex queries using OData but that’s not the main focus of this article.

Here is a screen capture of my iPhone App consuming OData :)

clip_image008

Sebastián Rodríguez

Hi,

In this article I want to show you quickly how easy, funny and powerful is to consume OData services in Windows Phone 7.

I am going to take this article from Microsoft as reference, adding screenshots and comments about the process.

So, in order to write your first Windows Phone 7 application that consumes OData, you may want to follow the following steps:

1. Download Windows Phone 7 OData Client libraries.

http://go.microsoft.com/fwlink/?LinkId=207900

The OData client library for Windows Phone generates HTTP requests to a data service that supports OData and transforms the entries in the response feed into objects on the client. Using this client, you can bind Windows Phone controls, such as ListBox or TextBox, to an instance of a DataServiceCollection class that contains an OData data feed. This class handles the events raised by the controls to keep the DataServiceContext class synchronized with changes that are made to data in the controls. For more information about using the OData protocol with Windows Phone applications, see Open Data Protocol (OData) Overview for Windows Phone.

Pasted from <http://msdn.microsoft.com/en-us/library/gg521145(v=vs.92).aspx>

clip_image001

2. Create a new Windows Phone application. In Solution Explorer, right-click the Solution, point to Add, and then select New Project.

3. In the Add New Project dialog box, select Silverlight for Windows Phone from the Installed Templates pane, and then select the Windows Phone Application template. Write a name for the project (e.g. 'WP7ODataSampleApp')

clip_image002

4. Click OK. This creates the application for Silverlight.

5. Generate the proxy classes by running the command datasvcutil.exe included in the  OData client libraries ZIP.

Go to Start->Run

Write 'cmd' and press Enter

clip_image004

Within the console, move to the directory where you have downloaded the OData client libraries.

For instance, '> cd D:\pablop\Documents\WP7\odata client libraries'

clip_image005

Then, run the datasvcutil.exe in order to generate the local proxy for the exposed OData services.

For the purposes of this article we are going to use the Northwind public OData services, exposed at the following Url: http://services.odata.org/Northwind/Northwind.svc

(you can take this as an example and actually use whatever OData service you have access to)

Take the following command line  as reference to generate the proxy:

datasvcutil /uri:http://services.odata.org/Northwind/Northwind.svc/ /out:.\NorthwindModel.cs /Version:2.0 /DataServiceCollection

clip_image006

You can check the generated proxy class file by running a 'dir *.cs' command, like shown below:

clip_image008

6. Move the generated file to the directory where the WP7 solution is located. You can do that just with Windows Explorer.

7. Add the file by selecting it from Project -> Add Existing item … or just by clicking on 'Show All Files' in Solution Explorer, right clicking then on the new .cs file  and choosing 'Include in Project'

clip_image010

clip_image011

8. Add a reference in the project to the System.Data.Services.Client.dll included in the OData Client library ZIP.

clip_image012

clip_image013

9. In the project, double-click the MainPage.xaml file.

Add the following attributes to your phone:PhoneApplicationPage node:

xmlns:my="clr-namespace:NorthwindModel"

d:DataContext="{d:DesignInstance Type=my:Customer, CreateList=True}"

Loaded="PhoneApplicationPage_Loaded">

Take the following xaml as a reference:

<phone:PhoneApplicationPage

    x:Class="ODataNorthwindPhone.MainPage"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    xmlns:my="clr-namespace:NorthwindModel"

    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"

    d:DataContext="{d:DesignInstance Type=my:Customer, CreateList=True}"

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

    SupportedOrientations="Portrait" Orientation="Portrait"

    shell:SystemTray.IsVisible="True" Loaded="PhoneApplicationPage_Loaded">

    <Grid x:Name="LayoutRoot" Background="Transparent">

        <Grid.RowDefinitions>

            <RowDefinition Height="Auto"/>

            <RowDefinition Height="*"/>

        </Grid.RowDefinitions>

        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">

            <TextBlock x:Name="ApplicationTitle" Text="Northwind Sales"

                       Style="{StaticResource PhoneTextNormalStyle}"/>

            <TextBlock x:Name="PageTitle" Text="Customers" Margin="9,-7,0,0"

                       Style="{StaticResource PhoneTextTitle1Style}"/>

        </StackPanel>

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

            <ListBox x:Name="MainListBox" Margin="0,0,-12,0" ItemsSource="{Binding}">

                <ListBox.ItemTemplate>

                    <DataTemplate>

                        <StackPanel Margin="0,0,0,17" Width="432">

                            <TextBlock Text="{Binding Path=CompanyName}" TextWrapping="NoWrap"

                                       Style="{StaticResource PhoneTextExtraLargeStyle}"/>

                            <TextBlock Text="{Binding Path=ContactName}" TextWrapping="NoWrap"

                                       Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>

                            <TextBlock Text="{Binding Path=Phone}" TextWrapping="NoWrap" Margin="12,-6,12,0"

                                       Style="{StaticResource PhoneTextSubtleStyle}"/>

                        </StackPanel>

                    </DataTemplate>

                </ListBox.ItemTemplate>

            </ListBox>

        </Grid>

    </Grid>

</phone:PhoneApplicationPage>

The 'd:DataContext' line above allows to create data bindings at design time for a data context that is assigned at run time. This way you will be able to see sample data within the Silverlight Visual Designer in  Visual Studio and Expression Blend. Obviously this line is not required but recommended :).

10. Replace ContentPanel grid with something like this:

      <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <ListBox x:Name="MainListBox" Margin="0,0,-12,0" ItemsSource="{Binding}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Margin="0,0,0,17" Width="432">
                            <TextBlock Text="{Binding Path=CompanyName}" TextWrapping="NoWrap"
                                       Style="{StaticResource PhoneTextExtraLargeStyle}"/>
                            <TextBlock Text="{Binding Path=ContactName}" TextWrapping="NoWrap"
                                       Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
                            <TextBlock Text="{Binding Path=Phone}" TextWrapping="NoWrap" Margin="12,-6,12,0"
                                       Style="{StaticResource PhoneTextSubtleStyle}"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </Grid>

11. Open MainPage.xml and add the following namespaces:

using System.Data.Services.Client;

using NorthwindModel;

12. Add the following declarations to the MainPage class:

        private DataServiceContext northwind;

        private readonly Uri northwindUri =

            new Uri("http://services.odata.org/Northwind/Northwind.svc/");

        private DataServiceCollection<Customer> customers;

        private readonly Uri customersFeed = new Uri("/Customers", UriKind.Relative);

13. Add the following PhoneApplicationPage_Loaded method to the MainPage class:

        private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)

        {

            // Initialize the context and the binding collection

            northwind = new DataServiceContext(northwindUri);

            customers = new DataServiceCollection<Customer>(northwind);

            // Register for the LoadCompleted event.

            customers.LoadCompleted

                += new EventHandler<LoadCompletedEventArgs>(customers_LoadCompleted);

            // Load the customers feed by using the URI.

            customers.LoadAsync(customersFeed);

        }

The above code initializes the binding collection and registers the method 'customers_LoadCompleted' (to be created on next step) to be called when collection has been loaded.

Remember that in Silverlight, all data must be retrieved asynchronously.

14. Now, let's handle the LoadCompleted event by adding the customers_LoadCompleted method. Take the following code as reference:

void customers_LoadCompleted(object sender, LoadCompletedEventArgs e)

{

   if (e.Error == null)

    {

        // Handling for a paged data feed.

        if (customers.Continuation != null)

        {

            // Automatically load the next page.

            customers.LoadNextPartialSetAsync();

        }

        else

        {

            // Set the data context of the listbox control to the sample data.

            this.LayoutRoot.DataContext = customers;

        }

    }

    else

    {

        MessageBox.Show(string.Format("An error has occurred: {0}", e.Error.Message));

    }

}

When the LoadCompleted event is handled, the following operations are performed if the request returns successfully:

o The LoadNextPartialSetAsync method of the DataServiceCollection object is called to load subsequent results pages, as long as the Continuation property of the DataServiceCollection object returns a value.

o The collection of loaded Customer objects is bound to the DataContext property of the element that is the master binding object for all controls in the page.

o Now, we are ready to test our first WP7 OData sample application. Just press F5  and wait for the emulator to be loaded and run our app. (this typically takes several secs)

clip_image014

clip_image015

clip_image016

16. As shown above, the main page is retrieving customers from OData.

Hope you find this article useful in order to start to play and/or build robust solutions on top of OData and Windows Phone 7, two extremely powerful platforms. Better together, for sure! :)

PP.

In some cases it is necessary to hide some items from the side menu according to the CRM user’s assigned role. To do this we need to modify the SiteMap from the CRM.

The example given in this post is done on CRM 2011 but it also applies to CRM 4.

We are going to see:

· How to hide items from the Settings section.

· How to hide the whole Settings area.

Firstly, we are going to export the CRM SiteMap as follows:

Go to Settings > Solutions >

Create a new solution.

image

Complete data.

image2

In the “Add Existing” menu we select “SiteMap” option and then “Save and Close”.

image3

Once we create the solution we select and export it, by clicking the “Export” button.

Click “Next”

image4

Select “Customizations”

image5

Mark the “Unmaneged” choice. Click “Export” and save the file .zip.

image6

When extracting the zip we find the customizations.xml file which contains the customizations from our CRM, just the ones from the “SiteMap” in this case.

Inside the <SiteMap> node is the complete structure from the side menu.

The privilege level the user has over the entity assigned to the menu item means what is going to determine it to be shown for some users but not for others.

Example:

image7

In this case only those roles having the “Read” permission over the “Solution” entity will be able to see this menu item. This compels us to attach a role to an entity in order to determine if the menu item is visible or not.

So we have two options: to create an entity just to define the visibility of the menu item, or to use an already created entity not working with it in our solution, for example “Solution”.

To determine which permissions has a role over an entity we go to Settings > Administration > Security Roles

image8

In the role properties window we can assign or remove the permissions over the entities. In this case we remove the “Read” permission from the “Solution” entity.

In this example the users of the role “User” won’t have the “Business Management” option visible inside the “Settings” menu.

Keep in mind the privileges are set over the <SubArea> nodes, if it necessary to hide the “Settings” menu we need to hide all the <SubArea> nodes.

More Posts Next page »