Microsoft Dynamics CRM 2011 (5.0) : C# - Add file to an account
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:
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'
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:
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"); }
Posted by - Christoff Truter
Date - 2011-04-18 17:21:00
Comments - 1
Date - 2011-04-18 17:21:00
Comments - 1
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:
When you click on "Add Extender", the following popup will appear that displays a list of available extenders:

(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.
Posted by - Christoff Truter
Date - 2011-04-10 19:39:39
Comments - 0
Date - 2011-04-10 19:39:39
Comments - 0
First 1 2 3 4 5 6 7 8 9 10 Last / 62 Pages (124 Entries)