Tag Archive 'crm'

Nov 14 2012

Beating CRM2011 Anti-XSS with a Web Resource Shim

Published by under Microsoft CRM

Background

In Microsoft Dynamics CRM we’ve got several places that documents relating to an account can be uploaded to SharePoint.  Some are custom solutions developed whilst we were using CRM4 and others are using the built-in CRM2011 SharePoint integration.

To keep things simple for users, I have created a SharePoint web part that allows them to see a consolidated view of documents relating to each account.  This web part has a menu against each document that allows users to open the record that the document was uploaded against.

The Problem

Previously, I was just opening the CRM record in an Internet Explorer (IE) window and everything was fine.  However, now CRM has got a nifty Xrm.Utility.openEntityForm() JavaScript function that will open entity forms in either an IE or Outlook window, depending on which client the user is using to access CRM.

If you are using a CRM Web Page WebResource, you’ve got the option of either including ClientGlobalContext.js.aspx or using parent.Xrm to access the Microsoft Xrm JavaScript object model.  Unfortunately, Crm is on one website address and SharePoint is another website address.  Therefore, although SharePoint is being displayed in CRM using an iFrame, Anti-XSS (Cross Site Scripting) prevents the use of parent.Xrm in the SharePoint page.

The Solution

Given that the Xrm JavaScript object model needs to be used from a page in CRM the solution I came up with is to use a WebResource html page that will act as a shim for SharePoint:

!DOCTYPE html>
<html>
<head>
    <title>Xrm Shim</title>
    <base>
    <script type="text/javascript" src="../ClientGlobalContext.js.aspx"></script>
    <script type="text/javascript" src="../c5_javascript/lib/jquery.min.js"></script>
    <script type="text/javascript">
        $(function () {
            var data = Xrm.Page.context.getQueryStringParameters();
            Xrm.Utility.openEntityForm(data.typename, data.id);
        });
    </script>
    <meta charset="utf-8">
</head>
<body>
</body>
</html>

I then updated my SharePoint web part to run the following script when the user clicks the CRM Record menu item:

crmRecordMenuItem.ClientOnClickScript =
    string.Format(@"ifrm = document.createElement('IFRAME');
        ifrm.setAttribute('src', '{0}/{1}/WebResources/xrmshim.htm?typename=%DocTypeName%&amp;id=%CRMDocID%');
        ifrm.style.width = 1+'px';
        ifrm.style.height = 1+'px';
        document.body.appendChild(ifrm);", crmUrl, crmOrgName);

This creates an iFrame that loads from html shim from CRM which in turn calls Xrm.Utility.openEntityForm using the typename and id passed from SharePoint in the query string parameters.

The shim is simple enough that it can be used on any page that is hosted on any site other that CRM.  It could be extended to call any Xrm object model methods provided by ClientGlobalContext.js.aspx.

No responses yet

Jun 08 2012

CRM2011 Automated Testing – Integration Testing

Published by under .NET,General,Microsoft CRM

The integration testing is concerned with testing customisations within the context of CRM to ensure that the various components work together correctly. In my current work this is mostly related to custom plugins in CRM and custom integration with SharePoint. The key point is that with this type of testing I am not concerned with the user interface, rather the underlying processes.

In many ways the integration tests are very similar to the unit tests, they are code based test created using the Gallio/MbUnit framework. However, instead of testing code in isolation and mocking dependencies, the integration tests test whole systems. This is achieved by making create, update, delete, etc. calls to the web service to simulate user actions.

Test setup and tear down code can become length as you need to be able to setup scenarios to be able to test, including creating test records and enabling/disabling plugin to allow actions to be performed that may otherwise be blocked.

It is also during integration testing that I introduce testing as specific users to test security related constraints. This is easily achieved in CRM as connections to the Organization Service support impersonation.

Integration tests are also good where a user has identified an issue with a plugin in a scenario you hadn’t thought of before. I tend to use this as a trigger to create new integration test to match that case, and then one or two more boundary cases around it.

As these tests require connection and interaction with CRM, they can be slow to run. As a result, I tend to run these in TeamCity, where they can be left to run on their own, or I will run specific tests in order to help track down an issue. Whilst setting them up may seem to take a long time, relative to “productive development” time, they soon become invaluable for regression testing as new functionality is developed or existing code is refactored to improve performance, etc.

Example:

namespace Tests.Plugin.AddressTests
{
    public class AddressTests
    {
        #region Setup/Teardown

        [SetUp]
        public void BeforeEachTest()
        {
            _testEntity = createEntityForTests();
        }

        [TearDown]
        public void AfterEachTest()
        {
            if (_testEntity != null)
            {
                _testEntity.DeleteAndIgnoreException();
            }
        }

        #endregion

        #region Instance variables

        protected CrmEntity _testEntity;
        protected static readonly string ExpectedExceptionMessageContains = "This record already has an active";

        #endregion

        [Test]
        public void TestMultipleMailingAddressesCanBeUnchecked()
        {
            setAddressPluginState(PluginStepState.Disabled);
            var address1 = CustomerAddressBuilder.NewMailingAddress(_testEntity.ToEntityReference(), "Mailing 1");
            var address2 = CustomerAddressBuilder.NewMailingAddress(_testEntity.ToEntityReference(), "Mailing 2");
            var address3 = CustomerAddressBuilder.NewMailingAddress(_testEntity.ToEntityReference(), "Mailing 3");
            setAddressPluginState(PluginStepState.Enabled);

            address1.C5_Mailing = false;
            address1.Save();

            setAddressPluginState(PluginStepState.Disabled);
            address1.Delete();
            address2.Delete();
            address3.Delete();
            setAddressPluginState(PluginStepState.Enabled);
        }

        #region Protected Methods

        protected enum PluginStepState
        {
            Enabled = 0,
            Disabled = 1
        }

        protected void setAddressPluginState(PluginStepState state)
        {
            using (var context = ServicesFactory.CrmContext())
            {
                var steps = from step in context.CreateQuery<SdkMessageProcessingStep>()
                            where step.Name.Contains("Address")
                            select new SdkMessageProcessingStep { SdkMessageProcessingStepId = step.SdkMessageProcessingStepId, Stage = step.Stage };

                foreach (var step in steps)
                {
                    EntityReference entityref = step.ToEntityReference();

                    SetStateRequest req = new SetStateRequest();
                    req.EntityMoniker = entityref;
                    req.State = new OptionSetValue((int)state);
                    req.Status = new OptionSetValue(-1);

                    SetStateResponse resp = (SetStateResponse)context.Execute(req);
                }
            }
        }

        #endregion
    }
}

In this example you can see that the test is disabling a plugin, setting up some test address records, re-enabling the plugin and then executing the test. After the test is complete it cleans up the test records.

Related Posts

No responses yet

Jun 07 2012

CRM2011 Automated Testing – Unit Testing

Published by under .NET,Microsoft CRM

Ideally the code being tested should not rely on external resources, where such dependencies exist they should be mocked to isolate the code being tested form the external system. In the case of plugins, this means that testing units of code should not require the code to have a connection to an actual instance of CRM.

CRM2011 has improved the way that plugins are developed against CRM, especially with the introduction of the CrmSvcUtil.exe tool for creating early bound classes for entities in CRM that can be used alongside the CRM SDK assemblies. Additionally Microsoft has provided interfaces for accessing CRM and data provided by CRM to the plugin:

  • IOrganizationService
  • IPluginExecutionContext
  • ITracingService

This means it is simple to mock the CRM services to test the plugin in isolation.

However, mocking a whole execution context would be a bit of a lengthy exercise, especially the IPluginExectionContext object is different depending on what messages and what pipeline stages you are writing the plugin for.

Thankfully there is a project on Codeplex that makes this job simple: CrmPluginTestingTools. There are two parts to this tool:

  • A plugin that you register in CRM as you will register your final plugin (including configuring pre- and post-images) that serialises the plugin execution context to xml files.
  • A library of classes for de-serialising the xml files into objects that match the IPluginExecutionContext interface.

Once you’ve registered their plugin, perform the steps that you plugin will handle; grab the output xml files; head into Visual Studio and start crafting your unit tests.

I tend to use the de-serialized xml files in my unit tests as a starting point and then use the object model to update the IPluginExecutionContext objects to structure the data for the specific test.

The execution context is only half of the story, I also use Moq to create a mock IOrganizationService that code being tested will be given instead of an actually connection to CRM. By doing this I am able to isolate the code from the CRM server plus I can determine what will be returned without having to setup records in CRM. I can even mock any type of exception if I want to test that aspect of my code.

As with all my automated tests, the unit tests are built on top of Gallio/MbUnit testing framework. This means that I don’t need to think about how to run the tests, I know they will all work with TestDriven.net in Visual Studio, the Gallio Test Runner – for a more graphical UI on my workstation, and TeamCity continuous integration server.

Overall Process

Of course, the plugins I write and single-class monsters, instead I break up the code in logical units (classes/methods) of responsibility and I test each unit on its own. If a unit of functionality doesn’t require access to CRM or the plugin execution context then I don’t worry about mocking those for that specific test.

Solution Structure

This solution contains several projects, these being:

  • Crm2011.Common

This contains the early-bound classes generate by CrmSvcUtil.exe which are used by several solutions.

  • Crm2011.Plugins.Address

The plugin that is being written/tested.

  • Crm2011.Plugins.DeploymentPackage

The project for deploying the plugin into CRM. The steps and images registered in this project should match how the CrmPluginTestingTools plugin was registered.

  • Plugin.Unit.Tests

This contains the unit tests created for testing the plugin, as well as the serialized execution contexts used by the unit tests. This project also contains a .gallio file that is the project used to run the tests in Gallio; and a .msbuild file that is the MsBuild project used to compile and run the tests in TeamCity.

  • SerializePluginContext & TestPlugin

The CrmPluginTestingTools projects for de-serializing the xml execution contexts in the unit tests.

Examples

[TestFixture]
public class CompanyAddressPreDelete
{

	MyServiceProvider serviceProvider;
	IPluginExecutionContext pluginContext;

	[SetUp]
	public void Setup()
	{
		var context = TestContext.CurrentContext.Test.Metadata["Context"][0];
		var service = new Mock&lt;iorganizationservice>();
		var assemblyPath = typeof(IndividualAddressPreCreateTests).Assembly.Location;
		var contextFile = Path.Combine(Path.GetDirectoryName(assemblyPath), @"Address\Contexts\Company\Delete\"+context+".xml");
		serviceProvider = new MyServiceProvider(service.Object, contextFile);
		pluginContext = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
	}

	[Test, Metadata("Context", "PreOperation-BothTicked-Active")]
	public void both_active_should_clear_parent()
	{
		var plugin = new Crm2011.Plugins.Address.PreAddressDelete();
		plugin.Execute(serviceProvider);

		Assert.Exists(pluginContext.SharedVariables, sv => sv.Key == "AddressChanges", "Address Changes not registered in SharedVariables");
		var changes = new SharedVariables(pluginContext.SharedVariables).AddressChanges;
		Assert.Count(2, changes);
		Assert.Exists(changes, x => x.Address == AddressType.Mailing && x.Change == ChangeType.Remove);
		Assert.Exists(changes, x => x.Address == AddressType.Invoice && x.Change == ChangeType.Remove);

		Assert.Exists(pluginContext.SharedVariables, sv => sv.Key == "MakeChanges", "Make Changes not registered in SharedVariables");
		Assert.IsTrue((bool)pluginContext.SharedVariables["MakeChanges"]);
	}
}

The above code is a single test fixture (class that contains unit tests); a SetUp method that is run before each test; and a single unit test. I have added Metadata attribute to the test method so the setup method can determine which execution context xml files should be de-serialized for the test. The first two lines of the test setup and execute the plugin, the rest of the test ensures that the ShareVariables on the execution context have been correctly set of the given data.

The following example indicates how the organization service can be mocked to ensure that the plugin is making the correct call to CRM:

[TestFixture]
public class CompanyPostDeleteTests
{
	Mock&lt;iorganizationservice> service;
	MyServiceProvider serviceProvider;
	IPluginExecutionContext pluginContext;

	[SetUp]
	public void Setup()
	{
		service = new Mock&lt;iorganizationservice>();
		var assemblyPath = typeof(IndividualAddressPreCreateTests).Assembly.Location;
		var contextFile = Path.Combine(Path.GetDirectoryName(assemblyPath), @"Address\Contexts\Company\Delete\PostOperation.xml");
		serviceProvider = new MyServiceProvider(service.Object, contextFile);
		pluginContext = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
	}

	[Test]
	public void deleted_mailing_and_invoice_address_should_clear_account_twice()
	{
		var parentId = Guid.NewGuid();
		pluginContext.SharedVariables.Add("MakeChanges", true);
		pluginContext.SharedVariables.Add("AddressChanges", "Mailing:Remove|Invoice:Remove");
		pluginContext.PreEntityImages.Add("Image", CreateTestAddress(parentId));


		var plugin = new PostAddressDelete();
		plugin.Execute(serviceProvider);

		service.Verify(s => s.Update(It.Is&lt;entity>(e =>
			 e.Id == parentId &&
			 e.LogicalName == "account" &&
			 e.Attributes.Contains("address1_line1") && (string)e["address1_line1"] == ""
		)), Times.Once());

		service.Verify(s => s.Update(It.Is&lt;entity>(e =>
			e.Id == parentId &&
			e.LogicalName == "account" &&
			e.Attributes.Contains("address2_line1") && (string)e["address2_line1"] == ""
		)), Times.Once());
	}
}

By using unit testing in isolation of CRM, it is possible to create the vast majority of a plugin without having to touch the CRM server itself (with the exception of creating the test serialized execution contexts). Not only that, once you have created the unit tests, it is possible to run them again and again without having to manually click through CRM, so if you make changes to entities in CRM you can easily re-run the CrmSvcUtil.exe to update your early-bound classes and then run the unit tests to verify that they still pass.

Related Posts

One response so far

Jun 06 2012

CRM2011 Automated Testing – Tool Stack

Published by under .NET,Microsoft CRM

To mark my return to blogging, I’ve decided to write a series of blog posts around automated testing in CRM2011.  This is part 1, an overview of the types of tests I’m creating and the tools I’m using for creating and running the tests.  Future posts will look at each of the types of tests in turn and look at how I’m using TeamCity to automate these tests.

The automated testing in place for CRM2011 is broken downv into the following three types of tests:

  • Unit Tests
  • These are small, fast tests that are written in code and are designed to test isolated pieces of code.
  • Integration Tests
    • The tests are for complete systems or sub-systems, e.g. a plugin running in the context of CRM.  However, they are still code based and tested in without User Interface interaction.
  • User Interaction Tests
    • This is tests of the system from the perspective of the user.  They are based on a simulation of the user clicking and entering values in the browser.

    Testing Components

    The basic components that are being used for automated testing of CRM are as follows:

    • Used for creating the test classes and test runner used for executing the tests.
  • CrmPluginTestingTools
    • This is used to create copies of actual plugin execution contexts from CRM.  These are then used in plugin unit tests outside of CRM.
  • Moq
    • Used for creating mock copies of external systems, e.g. CRM Web Services, so that unit tests do not require access to CRM.
  • WatiN
    • This is a web browser runner that simulates a user clicking in the browser.
  • TestDriven.Net
    • This integrates testing functionality into Visual Studio, making it quicker and easier to write and run tests from within Visual Studio without having to rely on an external application.
  • TeamCity
    • This is an automated continuous integration system that is used to both compile the source code and run unit tests.  It has also been configured to create a backup of the customisation solution from CRM into Subversion.

    Tool Stack

    The following diagram illustrates the tool stack used for each of the types of tests, with the system under test at the top of the stack and the host environment at the bottom:

    All of the test can be run in either Visual Studio or TeamCity and all of the test are based on the Gallio/MbUnit test framework.  In addition, the unit tests uyse Moq and CrmPluginTestingTools to allow the unit tests to run in isolation; the integration tests simply call straight to the CRM Web Services for both setting up the test and confirming the results; the user interaction tests use WatiN to control IE to run the test.

    Related Posts

    One response so far

    Mar 23 2009

    ScriptManager vs ClientScript

    Published by under .NET,General,Programming

    As part of a Microsoft Dynamics CRM customisation project, I was recently tasked with modifying an ISV add-in page so that individual sections of the page could be refreshed without having to refresh the entire page.

    That in itself was nice and easy, it just required the use of a couple of UpdatePanel and UpdateProgress controls to be dropped on the page along with a ScriptManager control to handle the partial postback requests.

    However, there were a couple of gotchas that I didn’t foresee.  Along with the partial updates, the client wanted the parts of the page to load the first time after the page had first loaded in the following order:

    1. Load base page.
    2. Start load of Application Status section.
    3. Start load of Risk section.
    4. Start load of Alerts section.

    Unfortunately, the ScriptManager that comes with ASP.Net AJAX only handles one postback at a time.  Any subsequent postbacks take precedence over earlier request, which is fine if you only have one update panel on a page but this initially resulted in only the Alerts section being loaded – the other postbacks being canceled.

    Luckily I found a very useful post on Amit’s Blog: Asp.Net Ajax UpdatePanel Simultaneous Update.  This post provides code that queues postback requests.  Ideally I would have liked to have the requests happening at the same time, but this is the next best thing.

    The other problem that I found was that one of the sections on the page had previously been dynamically creating and reqistering script that got loaded and executed when the page loaded using:

    Page.ClientScript.RegisterClientScriptBlock(this.GetType(),
        "ShowNavBarItem", script.ToString());

    Unfortunately that doesn’t work with the AJAX ScriptManager.  Instead I had to change the code to use the ScriptManager to load and execute the code using the following:

    ScriptManager.RegisterClientScriptBlock(updatePanelApplications,
        typeof(UpdatePanel), "showNavBarItems", script.ToString(), true);

    This means that each time the section is updated I can re-generate the script and it will be executed again.

    With this AJAX loading and some enhancements to the SQL code, users now get a much fasted load and response time for the page as the no longer have to wait for the whole page to be rendered before seeing information appearing on the page.

    kick it on DotNetKicks.com

    One response so far

    Feb 25 2009

    CRM 4 iFrame Printing

    Published by under Programming,Software

    Last year I was working with a client to develop some ISV add-ins for Microsoft Dynamics CRM.  Recently I was alerted to the fact that one of them – a seperate aspx page that loads in an iFrame on the account details panel – wasn’t printing correctly.

    It displayed correctly in the normal view form, appeared correctly on the print preview form but when actually printed it was collapsed down to one or two pixels high.

    After doing a bit of research, I found this post by Vince Bullinger, in which he gets around the problem by, as far as I can tell, modifying a core CRM css file.  Whilst this will work, it should be noted that any modification to core CRM files is not supported and will almost certainly break or be lost by updates and hotfixes.

    Another problem with the code Vince Bullinger gives is that the iFrames a fixed height and that applies to ALL ISV iFrames.  However, with this knowledge I was able to  come up with my own solution that uses a bit of Javascript to ensure that iFrames are printed and at the correct height to display all the content:

    <%@ Page Language="C#" AutoEventWireup="true"
        CodeBehind="Summary.aspx.cs" Inherits="CRMWeb.SummaryStatus.Summary" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>Summary Status</title>
        <style type="text/css">
            #pageWrapper
            {
                position: absolute;
                top: 0;
                left: 0;
            }
        </style>
    </head>
    <body>
        <div id="pageWrapper">
        <form id="form1" runat="server">
            <!-- content goes here -->
        </form>
        </div>
        <script language="javascript" type="text/javascript">
            var dh = document.getElementById("pageWrapper").offsetHeight;
            document.parentWindow.frameElement.height = dh;
            document.parentWindow.frameElement.style.display = "block";
            document.parentWindow.frameElement.style.height = dh + "px";
        </script>
    </body>
    </html>

    This solutions requires that you surround the content of your page with a div, in this case <div id=”pageWrapper”></div>.  This is used by the block of Javascript at the end.

    The purpose of the Javascript is to use the pageWrapper div to find out the height of the content.  This height is then used to set the height of the iFrame that contains the page and to set the display style of the iFrame to block.

    It probably doesn’t require the iFrame height and the iFrames style.height both being set but I decided to take a belts and braces approach.

    In addition to ensuring the iFrame content is printed, I am also planning on implementing the code on Vince Bullingers page for loading a specific css stylesheet for printing.

    kick it on DotNetKicks.com

    2 responses so far

    Aug 26 2008

    CRM4 Web Service Errors

    Published by under Programming

    As well as starting to work with SharePoint in the last two months, I’ve also been doing some development in Dynamics CRM4.  In the past week I’ve been porting an ISV add-on that was written for CRM3.  Whilst most of the code is pretty much the same, there are a few gotcha to watch out for.

    The first problem I came across was the web-service authentication.  I’m not a CRM expert but I believe this has something to do with the new multi-tenancy installation option.  Now when you connect to a web service you need to create a CrmAuthenticationToken and pass it to the web service.  This allows you to specify which organisation you are connecting to.

    Once connected to I started getting the following error when running a FetchXML query:

    <error>
      <code>0x8004111a</code>
      <description>An aggregate operation was initially specified, but no aggregate operator was encountered.</description>
      <type>Platform</type>
    </error>

    This error was being generated by the following FetchXML query:

    <fetch mapping="logical" aggregate="true">
       <entity name="account">
          <filter>
             <condition attribute="accountid" operator="eq" value="edd2b749-9f58-dd11-90aa-00155d0a0e03" />
          </filter>
          <link-entity name="contact" from="accountid" to="accountid">
             <attribute name="contactid" aggregate="count" alias="myCount" />
          </link-entity>
       </entity>
    </fetch>

    The purpose of this query is to count all the contacts that are linked with a specific account.  It does this selecting an account entity with a specific id and then counting all the contact id’s for the contacts that are linked to the account.

    For some reason the xml parser finds the aggregate=”true” flag but doesn’t find the count aggregate on the linked entity.  Quite why this works in CRM3 but not in CRM4 is beyond me but what I do know is that turning this query around works:

    <fetch mapping="logical" aggregate="true">
       <entity name="contact">
          <attribute name="contactid" aggregate="count" alias="count" />
          <link-entity name="account" from="accountid" to="accountid">
             <filter>
                <condition attribute="accountid" operator="eq" value="edd2b749-9f58-dd11-90aa-00155d0a0e03" />
             </filter>
          </link-entity>
       </entity>
    </fetch>

    In this case the query is run against contract and the id’s are counted where they are linked to a specific account.  I assume this works because the aggregate attribute is on the root entity.  I haven’t tested if it is possible to add more aggregates to the link entities or not.

    One response so far

    May 30 2008

    Large Downloads From Microsoft

    Published by under General

    For my new job, which I’ll be starting in a little over three weeks, I’m going to be working heavily with Microsoft SharePoint (MOSS 2007 – I’ll leave the versions for another post) and Microsoft Dynamics CRM 4 (again a guide to version can wait for another post).  Whilst there is loads of information out there about development with these two platforms, what someone starting out with these needs to some hands-on experience.  

    It’s wonderful reading about creating custom workflows in CRM but right now I’m suffering from serious information overflow because I’ve got all these theoretical concepts flying around in my head without being able to see how they work in reality – a picture is worth a thousand words but an hours hands-on experience is worth a thousand pictures.

    Microsoft has been kind enough to provide free pre-configured demonstration Virtual PC disk images for free that allow you experiment and test without the cost or time spent in setting up your own server.  The images themselves are about 4Gb to download.  Considering all the software installed on them that isn’t too bad.  The trouble is that Microsoft has split these images into 700Mb self-extracting rar files that have to downloaded separately and extracted, which requires upwards of 8Gb of free space.

    Over the past couple of weeks I have made several attempts to download the files but I have yet to get a working copy on my machine.  I have had problems with disconnection’s, running out of disk space (my bootcamp partition was too small) and corrupted files when they did download.  The fact that I have to download multiple files is a serious pain in the ass.  Why can’t Microsoft provide the disk images as a single file and embrace BitTorrent for distribution.   I’m sure it would be a lot quicker and less error prone.

    In the meantime my new employer is sending over a portable hard drive with the disk images on it for me to use.

    No responses yet