Microsoft Dynamics CRM 2011 (5.0) : C# - Add file to an account



Microsoft CRM 2011 Logo

In one of my previous posts we had a look at how to add a file to a CRM 4.0 account using the webservices that ship with CRM - in this post we're going to look at how to accomplish this using CRM 2011.

In CRM 4.0 I used the webservice "/MSCRMServices/2007/CrmService.asmx", which is also available in CRM 2011 - which in theory should provide us with some compatibility, allowing us to still use our older code. (in my example I didn't use the CRM 4.0 SDK)

But unfortunately (at the moment I wrote this, perhaps Microsoft fixed it by the time you read this) this is not the case at all, if we attempt to add a file using the 2007 service provided by CRM 2011 you will get an exception that looks something like this:

Server was unable to process request

If we look at the detail of our SoapException, we'll find a message looking something like this:
 
<error>
  <code>0x80040216</code>
  <description>Attribute objectidtypecode must have the same value as attribute objecttypecode</description>
  <type>Platform</type>
</error>
 

Now this is obviously a new field added to CRM 2011, one thats not being exposed by the service - not sure if this is neglect or on purpose, but there is an easy workaround - try to avoid this workaround if possible (will show you a better alternative in this post).

Assuming you're using a web reference (not to be confused with the newer service reference WCF), you will need to find reference.cs in your web references folder, search for the annotation class and add the following property within the annotation class:
 
public EntityNameReference objectidtypecode  {
	get {
		return this.objecttypecodeField;
	}
	set {
		this.objecttypecodeField = value;
	}
}
 

If you're using a service reference (WCF), you will need to add something like this:

 
[System.Xml.Serialization.XmlElementAttribute(Order=24)]
public EntityNameReference objecttypecode {
	get {
		return this.objecttypecodeField;
	}
	set {
		this.objecttypecodeField = value;
		this.RaisePropertyChanged("objecttypecode");
	}
}
 

Even though this will probably solve the problem, we must rather try to use the new webservice "/CSTruter/XRMServices/2011/Organization.svc", because how many other underlying issues will we have without knowing about them?

Instead of consuming the above mentioned webservice like we generally consume services, we can use the CRM service utility (located in the CRM 2011 SDK bin folder) which will generate us some early-bound entity classes via the following command:
 
crmsvcutil /url:"http://dionysis:5555/CSTruter/XRMServices/2011/Organization.svc" /out:Xrm.cs
 

Note: chances are that you might receive the following exception if you run this tool:
 
Exiting program with exception: Could not load file or assembly 'Microsoft.IdentityModel, 
Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
 
This means that you need to install the WIF (Windows Identity Foundation) on your machine, available from here


To make all of this work you'll need to include the generated code along with references to the following .NET 4.0 assemblies:

microsoft.xrm.sdk assembly (also located within the CRM 2011 SDK bin folder)
System.Runtime.Serialization
System.ServiceModel

In the following snippet we consume the webservice:
 
using System;
using System.Linq;
using System.IO;
using Microsoft.Xrm.Sdk.Client;
using System.ServiceModel.Description;
 
class Program
{
    static OrganizationServiceContext context;
 
    static void Main(string[] args)
    {
        ClientCredentials credentials = new ClientCredentials();
        credentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
        //credentials.Windows.ClientCredential = new System.Net.NetworkCredential("username", "password", "domain");
        Uri uri = new Uri("http://dionysis:5555/UIT/XRMServices/2011/Organization.svc");
        OrganizationServiceProxy proxy = new OrganizationServiceProxy(uri, null, credentials, null);
        proxy.EnableProxyTypes(); // enable support for early-bound entities
 
        context = new OrganizationServiceContext(proxy);
 

Notice classes OrganizationServiceProxy and OrganizationServiceContext:
In the snippet we're passing the proxy to the service context class, now we don't need to do this, we can use the proxy class directly and skip the use of the context class, but apparently the context class attempts to manage entity relationships etc.

We're going to attempt to add a file to the following CRM account:

CRM 2011 Account

To add the file to this account (or pretty much any entity for that matter) will look something like this:
 
static void AddDocument(string filename, Guid id, string logicalName)
{
    Annotation annotation = new Annotation();
    FileInfo fileInfo = new FileInfo(filename);
    annotation.FileName = fileInfo.Name;
    annotation.DocumentBody = Convert.ToBase64String(File.ReadAllBytes(filename));
    annotation.IsDocument = true;
 
	// rather pass the actual type
    annotation.MimeType = "application/octet-stream";
    annotation.ObjectId = new Microsoft.Xrm.Sdk.EntityReference(logicalName, id);
    context.AddObject(annotation);
    context.SaveChanges();
}
 

We need to pass a filename (full path), Guid (reference to the specific account to which we want to add the file) and the logicalName of the entity (which is "account" in this instance).

In order to retrieve the reference needed for the preceding snippet, you can write a simple LINQ query like seen in the following snippet:

 
Account account = (from p in context.CreateQuery<Account>()
                    where p.Name == "test"
                    select p).SingleOrDefault();
 
if (account != null)
{
    AddDocument(@"c:\test.txt", account.Id, "account");
}
 





Post/View comments
 

ASP.NET(C#) : Autocomplete TextBox - Part 2 (AjaxControlToolkit)



The source code for the following post can be downloaded here.

In the previous part of this post we had a look at how to create an autocomplete textbox from scratch using the scriptmanager, asp.net, c# and javascript.

Now in this post we're going to have a look at how to use a control created by microsoft - which should represent a more mature solution than the one we looked at in the first part of this post

I am of course talking about the open source autocomplete extender control thats part of the Ajax Control Toolkit.

First of all you'll need to download the latest AjaxControlToolkit assembly.

Next you will need to add the assembly to your toolbox, which will add the extender designer item (if you don't have other extenders already), like seen in the following image to the Visual Studio IDE:

Extender control designer

When you click on "Add Extender", the following popup will appear that displays a list of available extenders:

Select Extender Control
(obviously you'll need to select the autocomplete extender ;))

Like in part 1 of this post, we've got two options that we can use as datasources, PageMethods or Webservices.

PageMethod:

 
<asp:AutoCompleteExtender ID="txtValue_AutoCompleteExtender" runat="server" DelimiterCharacters=""
    Enabled="True" TargetControlID="txtValue" ServiceMethod="Get" MinimumPrefixLength="1"
    CompletionSetCount="5" CompletionInterval="500">
</asp:AutoCompleteExtender>
 


 
public partial class _Default : System.Web.UI.Page
{
 
[WebMethod]
public static string[] Get(String prefixText, Int32 count)
{
    // Dummy data - don't do this
    string[] data = new string[] { 
    "Christoff Trüter", 
    "Eugene Stander",
    "Roland Cooper",
    "Alexander Mehlhorn",
    "Derek Campher",
    "Julie Trüter",
    "Hanno Coetzee",
    "Wayne Kleynhans",
    "Pieter Du Plooy",
    "Pam Nizar" };
 
    return (from p in data
            where p.IndexOf(prefixText, StringComparison.OrdinalIgnoreCase) >= 0
            select p).Take<String>(count).ToArray();
}
 

Quick things to remember about PageMethods:
  • need to be public and static. (since its being called client-side it wont have server-side access to the current served page, therefore it would have been pointless to make it an instance method - among other reasons)
  • lives on the page that calls it.

Webservice:

 
<asp:AutoCompleteExtender ID="txtValue_AutoCompleteExtender" runat="server" DelimiterCharacters=""
    Enabled="True" TargetControlID="txtValue" ServiceMethod="Get" ServicePath="~/Services/myService.asmx" MinimumPrefixLength="1"
    CompletionSetCount="5" CompletionInterval="500">
</asp:AutoCompleteExtender>
 
 
[System.Web.Script.Services.ScriptService]
public class myService : System.Web.Services.WebService
{
    [WebMethod]
    public string[] Get(String prefixText, Int32 count)
    {
        // Dummy data - don't do this
        string[] data = new string[] { 
        "Christoff Trüter", 
        "Eugene Stander",
        "Roland Cooper",
        "Alexander Mehlhorn",
        "Derek Campher",
        "Julie Trüter",
        "Hanno Coetzee",
        "Wayne Kleynhans",
        "Pieter Du Plooy",
        "Pam Nizar" };
 
        return (from p in data
                where p.IndexOf(prefixText, StringComparison.OrdinalIgnoreCase) >= 0
                select p).Take<String>(count).ToArray();
    }
}
 

Here is a quick description of some of the most important attributes used.
  • TargetControlID : The texbox that must be autocompleted.
  • ServiceMethod : The PageMethod or Service method (if ServicePath defined)
  • ServicePath : The path to the service thats used for consumption.
  • MinimumPrefixLength : The minimum amount of letters that must be typed within the textbox before a query is attempted to the server.
  • CompletionSetCount : The number of results to return.
  • CompletionInterval : The number (in milliseconds) to wait until a query to the server is attempted.


You can read more about other attributes of this extender control here.




Post/View comments
 
First 6 7 8 9 10 11 12 13 14 15 Last / 65 Pages (130 Entries)

Latest Posts

MS SQL: Parameter Sniffing


2012-05-21 22:38:48

Be the best stalker you can be


2011-12-13 22:33:54

Top 5 posts

Moving items between listboxes in ASP.net/PHP example


Move items between two listboxes in ASP.net(C#, VB.NET) and PHP
2008-06-12 17:07:43

Simple WYSIWYG Editor


Creating a WYSIWYG textbox for your website is actually quite simple.
2007-02-01 12:00:00

C# YouTube : Google API


Post on how to integrate with YouTube using the Google Data API
2011-03-12 08:37:51

Populate a TreeView Control C#


Populate a TreeView control in a windows application.
2009-08-27 16:01:03

Cross Browser Issues: Firefox Word Wrapping


Firefox word wrapping issues
2008-06-09 09:51:21