We've had couple of instances where we needed to embed existing image attachments in dynamics crm into sql server reporting services reports. Here are the steps you need to take in order to make it happen. It's pretty straight forward.

  1. Create a new report
  2. Add a new table
  3. Drag an image control onto the table and place it into the column that you want, select 'Database' from the options
  4. Click on the image -> go to the 'Properties' tab -> from the 'Value' dropdownlist select '<Expression...>' and use the following bit of code
    =System.Convert.FromBase64String(Fields!documentbody.Value)
  5. 'documentbody' is the field from the FilteredAnnotation view.

    EXAMPLE



    RESULT


Enjoy!

We are working on a version of the Dynamics CRM 4 SDK that will work with the iPhone via MonoTouch. Here is a preview of it creating an account in Dynamics CRM using the MonoTouch C# library. We're creating this to speed up development of xRM solutions that can leverage the power of touch based mobile devices as well as the Dynamics CRM platform.


Challenges so far...

MonoTouch doesn't support web services natively yet, therefore we had to use the HttpWebRequest class to make raw calls to the crm web service. We also had to duplicate Request, Response, CreateRequest, CreateResponse, TargetCreateDynamic as well as all Dynamics CRM specific data types (CrmDateTime, CrmDateTimeProperty...etc).

Sample Code

// IFD not supported yet
CrmAuthenticationToken token = new CrmAuthenticationToken
{
    AuthenticationType = 0,
    OrganizationName = "MagnetismLimited",
    CallerId = Guid.Empty
};
 
CrmWebRequest sdk = new CrmWebRequest("http://virtualcrm03/mscrmservices/2007/crmservice.asmx",
    "MAGNETISM", "Administrator", "h3rew3g0", token);
 
// only difference here is that entity.Properties is an array instead of type PropertyCollection
DynamicEntity entity = new DynamicEntity("account");
entity.Properties = new Property[] { 
    new StringProperty("name", accountName),
};
 
TargetCreateDynamic target = new TargetCreateDynamic { Entity = entity };
CreateRequest cr = new CreateRequest { Target = target };
 
CreateResponse response = sdk.Execute(cr) as CreateResponse;
Console.WriteLine(response.id);

Dynamics CRM SDK for the iPhone is still in its early stages, we plan to release a public beta by the end  of October. If you'd like to be part of our test team please contact me.

Time for another crm goodie...

We've been working on a little project that needed blocking of certain outbound emails, with the Dynamics CRM plugin architecture this made it very very simple. For whatever reason, if you want to block outbound emails from Dynamics CRM programmatically, hook into the Send message on the email entity at the Pre stage synchronously then set the IssueSend property to false.

A bit of code
if (context.MessageName.Equals("Send", StringComparison.InvariantCultureIgnoreCase))
{
    context.InputParameters["IssueSend"] = false;
}

A little gotcha, the system marks the email as Sent even though we've blocked it, so be careful with that one. Hopefully this is useful to someone else. We've used this technique to write a neat little addon for Dynamics CRM, keep an eye out for it!

Mobile Express for Dynamics CRM is now available for free from Microsoft. You can download it from http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=f592ec6c-f412-4fd5-9a80-cd3bcbd26d8b

Here it is running on the iPhone

Main Accounts
Active Accounts New Account

Here is a simple class you can use to backup, restore and publish dynamics crm customizations programmatically. Please keep in mind that dynamics crm customizations are additive, which means, if you import a set of customizations lets say a new attribute on the account entity and you restore a backup of the old customizations the new attribute on the account entity that was imported will not be deleted.

Usage
CrmCustomizations customizations = new CrmCustomizations(service);

You can backup to an xml file or a zip file by calling the Backup method. Backup method takes care of creating the xml or zip file by looking at the output file extension.
    bool backedup = customizations.Backup(@".\customizations_backup.xml");
    // or to a zip file
    backedup = customizations.Backup(@".\customizations_backup.zip");

To restore a backup call the Restore method. You can pass it a .zip file or a .xml file path.
    bool restored = customizations.Restore(@".\customizations.xml");

Once you have restored you need to publish the customizations, to publish call the Publish method. It will publish all customizations.
    bool published = customizations.Publish();

Download the class file

Enjoy!

Here is a sneak preview of Dynamics CRM integrated with Xero that we have just completed. Yesterdays post (automatically emailing pdf invoices) is part of this whole system we've been working on. If you are using Xero as your accounting software it can now be integrated seemlessly into Dynamics CRM.

Dynamics CRM to Xero 
   Take a look at this 5 minute video (audio coming soon...)

What Can It Do?


In real-time

  • Synchronize accounts in Dynamics CRM to and from Xero
  • Synchronize invoices from Dynamics CRM to Xero
  • Synchronize invoice payments from Xero to Dynamics CRM
  • Synchronize account codes from Xero to Dynamics CRM

It has been a pleasure working with the Xero API, Xero has done a very nice job. Looking forward to v2 which will provide the ability to synchronize credit notes, currency, additional payment options and more...

Thanks to Tony Rule from Xero for guiding us through the API and Amanda Mattson from XrmLinq for the LINQ to Dynamics CRM tool.

Time for another Dynamics CRM goodie...

Send an invoice to a customer with a pdf attached using a dynamics crm workflow

We try to automate as many things as we can, automatically sending invoices is one of them. Workflow as you know in Dynamics CRM is very powerful, specially the ability to create custom activities and hook into the pipeline. We took advantage of this, we created a custom workflow activity that takes in any entity, Email and a Report, automatically turn it into a PDF, attach it to the email and send the email.

Take a look at this 5 minute video to see how it works. If you're interested in using this in your organization contact me via this link.

Under The Hood


Report2Pdf
This class does the heavy lifting, it has a method called Download, connects to the report server, configures the parameters and renders the report as a PDF then returns a byte array.

public
class Report2Pdf
{
    public static byte[] Download(string rsUrl, string rseUrl, 
        System.Net.NetworkCredential credentials, string report, 
        Report2PdfParameter[] inputParameters, string culture)
    {


Workflow Activity
Straight forward, read the configuration data, makes a call to the Report2Pdf.Download method, creates an activitymimeattachment then executes a SendEmailRequest.

byte[] data = Report2Pdf.Download(config.Url, config.ExecutionUrl,
    new NetworkCredential(config.UserName, config.Password, config.Domain),
    report.Location, rps.ToArray(), config.Culture);


LINQ and Dynamics CRM
Thanks to Amanda and the team at XrmLinq for giving us access to their library. This has made data access so much easier. Something that would take atleast 10-20 lines of code and a lot of effort messing around with FetchXml has now been reduced to 3 lines and LINQ!

var
config = (from c in xrm.ReportServerConfigurations
              where c.ReportServerConfigurationId == report.ConfigurationId
              select c).SingleOrDefault();

I was browsing the dynamics forums the other day and saw a post asking about the progress bar in CRM, we created one awhile back, here it is for anyone else that's looking for something similar.

Click here to download a working sample.

Dynamics CRM 4 - Progress Bar

What you'll need

crmprogressbar.js

function
crmProgressBar(id) {
    this.bar = $("#" + id);

    this.bar.css({
        'height': '23px',
        'width': '357px',
        'background': 'transparent url(img/statusbar.gif) no-repeat'
    });

    this.bar.find("div").css({
        'height': '19px',
        'width': '1px',
        'background': 'transparent url(img/step.gif) repeat-x',
        'position': 'relative',
        'top': '2px',
        'left': '3px'
    });

    this.step = function(percentage) {
        var width = parseInt((percentage / 100) * 351);
        if (width > 351) { width = 351; }

        this.bar.find("div").css({ 'width': width + 'px' });
    }
}

Example

  1. Create a new html file
  2. Create a new javascript file and copy the above code into it
  3. Include a reference to the jQuery javascript library
  4. Include a reference to the javascript in your html file
  5. Add a "div" tag to the html file and give it an "id"
  6. Add another "div" tag inside the "div" you created in step 4. and put a blank space
  7. To initialize the progress bar; create a new variable to hold the progress bar, then create a new instance of the progress bar by specifying the "id" of the div you created in step 4.
    eg: var progressBar1 = new crmProgressBar("id-of-div");
  8. To step/increment the progress bar use the step() instance method
    eg: progressBar1.step(10); // will increment to 10%;

<div id="p1">
    <div>
        &nbsp;</div>
</div>

<script type="text/javascript">
    var i = 5;
    var cpb = null;

    $(document).ready(function() {
        cpb = new crmProgressBar("p1");
        increment();
    });

    function increment() {
        if (i <= 100) {
            i += 5;
            cpb.step(i);
            setTimeout(increment, 1000);
        }
    }
    
</script>

We've decided to release another component we've been using internally. This little webcontrol allows you put pass data from a Web Form to Dynamics CRM 4.

How does it work?
Create a UserControl to layout the form.

<%@ Control Language="C#" %>
Topic:
<asp:TextBox ID="topic" runat="server" /><br />
First Name:
<asp:TextBox ID="firstname" runat="server" /><br />
Rating:
<asp:DropDownList ID="rating" runat="server">
<asp:ListItem Text="Hot" Value="1"></asp:ListItem>
<asp:ListItem Text="Warm" Value="2"></asp:ListItem>
<asp:ListItem Text="Cold" Value="3"></asp:ListItem>
</asp:DropDownList>
<br />
<br />
<asp:Button ID="submit" runat="server" Text="Add to CRM" />
Next we add the Web2EntityControl into our .aspx page and configure the connection settings (Url, Username, Password, Domain ...etc of CRM) as well as Mappings.
For example:
Which field in Dynamics CRM should the topic field (from above) map to?

Here is a sample configration
<magnetism:Web2EntityControl ID="leadform" runat="server" SkinPath="~/lead.ascx"
Async="true">
<Settings Url="http://virtualcrm/mscrmservices/2007/crmservice.asmx"
Domain="MAGNETISM" OrganizationName="Demo" UserName="Administrator"
Password="itsasecret" EntityName="lead" />
<Mappings>
<magnetism:Mapping CrmFieldSchemaName="subject" CrmFieldType="NVarChar"
ControlID="topic" ValuePropertyName="Text" />

<magnetism:Mapping CrmFieldSchemaName="firstname" CrmFieldType="NVarChar"
ControlID="firstname" ValuePropertyName="Text" />

<magnetism:Mapping CrmFieldSchemaName="leadqualitycode" CrmFieldType="Picklist"
ControlID="rating" ValuePropertyName="SelectedValue" />
</Mappings>
</magnetism:Web2EntityControl>
This form is mapped to the Lead entity (EntityName="lead")
Topic textbox is mapped to the "subject" field in Dynamics CRM
First Name textbox is mapped to "firstname" field in CRM
Rating dropdownlist is mapped to "leadqualitycode" picklist in Dynamics CRM

This control works with On-Premise, Partner Hosted & IFD installations. This works really well for data entry forms, we use it on our Contact Us page as well as client contact us pages and hand the data through to leads or cases depending on the customer query.

If you'd like a copy contact me.

Enjoy!

While browsing the online Dynamics CRM SDK a while back I noticed that FetchXml had a XSD schema. So I grabbed the xsd.exe tool from Visual Studio, generated a cs file to see if I can use that to create FetchXml queries. Here are my findings.

To generate the cs file
xsd.exe /c /n:ExamplNamespace FetchXml.xsd

You'll notice that the resulting code file has an object array called Items, if have a look at the metadata attributes on that field you'll see which elements are supported. For example the "fetch" class Items array will support "entity" and "order"; how do we use it?

fetch sample = new fetch
{
    Items = new object[] 
    {
        new entity { name = "account" },
        new order { attribute = "name", descending = false }
    }
};

Dig a little deeper and you'll see that you are able to generate more complex queryes. For example:
Get the first 10 accounts ordered by account name along with the primary contact.

fetch f = new fetch
{
    mapping = fetchMapping.logical, // not required
    aggregate = false, // not required
    count = "10", // not required
    distinct = false, // not required
    page = "1",
    Items = new object[] {
        new entity { 
            name = "account", 
            Items = new object[] {
 
                new linkentity {
                    name = "contact", // link entity schema name
                    from = "contactid", // link entity key schema name
                    to = "primarycontactid", // parent link entity key schema name
                    Items = new object[] {
                        new attribute { name = "contactid" },
                        new attribute { name = "fullname" },
                        new order { attribute = "fullname", descending = false } 
                    }
                },
 
                new attribute { name = "accountid" }, // or new allattributes { }
                new attribute { name = "name" }
            }
        },
        new order { attribute = "name", descending = false } 
    }
};

Now that we have defined the query we need to create a string representation of it so that the crm web service can understand it. To do that we will use the XmlSerializer to serialize this fetch instance.

XmlSerializer xs = new XmlSerializer(typeof(fetch));
StringWriter sw = new StringWriter();
xs.Serialize(sw, f);
sw.Close();
 
string fetchXml = sw.ToString();
string result = sdk.Fetch(fetchXml);
More Posts Next page »