So one of my customers ran into this issue while opening an Opportunity.  As you can see, a custom plugin was throwing an exception because it could not find a Account with a specified ID.

SNAGHTML5c035ae

That part is 100% correct.  The Account with that ID indeed does not exist in the database.

The problem is, this plugin should never have been fired. As I mentioned, this was happening on a Retrieve operation and there are no plugins registered against the Retrieve Message.

So I waited until tonight so I could turn on Tracing (on-premise, of course), and this is what I found:

[2014-10-16 20:12:57.600] Process: w3wp |Organization:d98bbf24-8eed-4cb4-a379-6aa848499cb0 |
    Thread:   25 |Category: Exception |User: fb9a439c-b578-4a4b-83e0-39ea0059ad2a |
    Level: Error |ReqId: eb0bc9e4-e6e6-4552-b322-1c2fa0bdbc10 | 
    CrmException..ctor  ilOffset = 0x7

    at CrmException..ctor(String message, Exception innerException, Int32 errorCode,
       Boolean isFlowControlException)  ilOffset = 0x7

    at CrmException..ctor(String message, Exception innerException, Int32 errorCode)  ilOffset = 0x5
    at RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig,
       Boolean constructor)  ilOffset = 0xFFFFFFFF

    at RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder,
       Object[] parameters, CultureInfo culture)  ilOffset = 0xF7

    at RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args,
       CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)  ilOffset = 0x1E8

    at Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args,
       CultureInfo culture, Object[] activationAttributes)  ilOffset = 0xBB

    at Activator.CreateInstance(Type type, Object[] args)  ilOffset = 0xA
    at VersionedPluginProxyStepBase.WrapExceptionToThrow(CrmException exception)  ilOffset = 0xD3
    at VersionedPluginProxyStepBase.Execute(PipelineExecutionContext context)  ilOffset = 0x65
    at Pipeline.Execute(PipelineExecutionContext context)  ilOffset = 0x65
    at MessageProcessor.Execute(PipelineExecutionContext context)  ilOffset = 0x1C5
    at InternalMessageDispatcher.Execute(PipelineExecutionContext context)  ilOffset = 0xE4
    at ExternalMessageDispatcher.ExecuteInternal(IInProcessOrganizationServiceFactory serviceFactory,
       IPlatformMessageDispatcherFactory dispatcherFactory, String messageName, String requestName, 
       Int32 primaryObjectTypeCode, Int32 secondaryObjectTypeCode, ParameterCollection fields, 
       CorrelationToken correlationToken, CallerOriginToken originToken, UserAuth userAuth, Guid callerId,
       Guid transactionContextId, Int32 invocationSource, Nullable`1 requestId, Version endpointVersion)  ilOffset = 0x156

    at OrganizationSdkServiceInternal.ExecuteRequest(OrganizationRequest request, CorrelationToken correlationToken,
       CallerOriginToken callerOriginToken, WebServiceType serviceType, UserAuth userAuth, Guid targetUserId, 
       Boolean traceRequest, OrganizationContext context, Boolean returnResponse)  ilOffset = 0x145

    at OrganizationSdkServiceInternal.ExecuteRequest(OrganizationRequest request, CorrelationToken correlationToken,
       CallerOriginToken callerOriginToken, WebServiceType serviceType)  ilOffset = 0x3D

    at OrganizationSdkServiceInternal.Retrieve(String entityName, Guid id, ColumnSet columnSet,
       CorrelationToken correlationToken, CallerOriginToken callerOriginToken, WebServiceType serviceType)  ilOffset = 0x66

    at InprocessServiceProxy.RetrieveCore(String entityName, Guid id, ColumnSet columnSet)  ilOffset = 0x28
    at OrganizationServiceProxy.Retrieve(String entityName, Guid id, ColumnSet columnSet)  ilOffset = 0x4
    at Utility.UpdateAccountKeyword(IOrganizationService service, Guid accountId)  ilOffset = 0xE8 
        C:\Plugins\SupportingClasses\Utility.cs(205)

    at InvoiceCancelOpportunityCloseKeywords.Execute(IServiceProvider serviceProvider)  ilOffset = 0x164 
        C:\Plugins\InvoiceCancelOpportunityCloseKeywords.cs(70)

    at V5PluginProxyStep.ExecuteInternal(PipelineExecutionContext context)  ilOffset = 0xD0
    at VersionedPluginProxyStepBase.Execute(PipelineExecutionContext context)  ilOffset = 0x65
    at Pipeline.Execute(PipelineExecutionContext context)  ilOffset = 0x65
    at MessageProcessor.Execute(PipelineExecutionContext context)  ilOffset = 0x1FB
    at InternalMessageDispatcher.Execute(PipelineExecutionContext context)  ilOffset = 0xE4
    at ExtensiblePlatformMessageDispatcher.Execute(PipelineExecutionContext pluginContext)  ilOffset = 0x0
    at ExtensiblePlatformMessageDispatcher.UpdateWithInvocationSource(BusinessEntity entity, FilterExpression filter,
       Int32 invocationSource, ExecutionContext context)  ilOffset = 0xCE

    at ExtensiblePlatformMessageDispatcher.Update(BusinessEntity entity, FilterExpression filter, ExecutionContext context) 
       ilOffset = 0x5

    at BusinessProcessObject.UpdateWithPipelineAndExtensions(IBusinessEntity entity, ExecutionContext context)  ilOffset = 0x78
    at QOIPriceService.UpdateEntity(BusinessEntity newQoi, BusinessEntity oldQoi, ExecutionContext context)  ilOffset = 0x87
    at PriceService.CalculatePrice(BusinessEntity entity, Guid lineItemId, Boolean skipQOIDetailPricing,
       Boolean overridePricePerUnitLock, Boolean overrideDiscountLock, ExecutionContext context)  ilOffset = 0x6E1

    at OpportunityPriceService.CalculatePrice(BusinessEntity entity, Guid lineItemId, Boolean skipQOIDetailPricing,
       Boolean overridePricePerUnitLock, Boolean overrideDiscountLock, ExecutionContext context)  ilOffset = 0x70

    at QOIPriceService.CalculatePrice(Guid qoiId, Guid lineItemId, Boolean skipLineItemPricing, Boolean overridePricePerUnitLock,
       Boolean overrideDiscountLock, Boolean isModifiedBySystem, ExecutionContext context)  ilOffset = 0x2E

    at OpportunityService.CalculatePrice(Guid opportunityId, Guid opportunityProductId, Boolean skipOpportunityProductPricing,
       Boolean overridePricePerUnitLock, Boolean overrideDiscountLock, Boolean isModifiedBySystem, ExecutionContext context) 
       ilOffset = 0x12

    at QOIService.Retrieve(BusinessEntityMoniker moniker, EntityExpression entityExpression, ExecutionContext context,
       Boolean isModifiedBySystem, Boolean calculatePrice, Int32 state)  ilOffset = 0x2D

    at OpportunityService.Retrieve(BusinessEntityMoniker moniker, EntityExpression entityExpression,
       ExecutionContext context)  ilOffset = 0x14

    at RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig,
       Boolean constructor)  ilOffset = 0xFFFFFFFF

    at RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) 
       ilOffset = 0x25

    at RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder,
       Object[] parameters, CultureInfo culture)  ilOffset = 0x89

    at LogicalMethodInfo.Invoke(Object target, Object[] values)  ilOffset = 0x4F
    at InternalOperationPlugin.Execute(IServiceProvider serviceProvider)  ilOffset = 0x57
    at V5PluginProxyStep.ExecuteInternal(PipelineExecutionContext context)  ilOffset = 0x58
    at VersionedPluginProxyStepBase.Execute(PipelineExecutionContext context)  ilOffset = 0x65
    at Pipeline.Execute(PipelineExecutionContext context)  ilOffset = 0x65
    at MessageProcessor.Execute(PipelineExecutionContext context)  ilOffset = 0x1C5
    at InternalMessageDispatcher.Execute(PipelineExecutionContext context)  ilOffset = 0xE4
    at ExternalMessageDispatcher.ExecuteInternal(IInProcessOrganizationServiceFactory serviceFactory,
        IPlatformMessageDispatcherFactory dispatcherFactory, String messageName, String requestName, 
        Int32 primaryObjectTypeCode, Int32 secondaryObjectTypeCode, ParameterCollection fields, 
        CorrelationToken correlationToken, CallerOriginToken originToken, UserAuth userAuth, Guid callerId, 
        Guid transactionContextId, Int32 invocationSource, Nullable`1 requestId, Version endpointVersion)  ilOffset = 0x156

    at OrganizationSdkServiceInternal.ExecuteRequest(OrganizationRequest request, CorrelationToken correlationToken,
        CallerOriginToken callerOriginToken, WebServiceType serviceType, UserAuth userAuth, Guid targetUserId, 
        Boolean traceRequest, OrganizationContext context, Boolean returnResponse)  ilOffset = 0x145

    at OrganizationSdkServiceInternal.ExecuteRequest(OrganizationRequest request, CorrelationToken correlationToken,
       CallerOriginToken callerOriginToken, WebServiceType serviceType)  ilOffset = 0x3D

    at OrganizationSdkServiceInternal.Execute(OrganizationRequest request, CorrelationToken correlationToken,
       CallerOriginToken callerOriginToken, WebServiceType serviceType)  ilOffset = 0x24

    at InprocessServiceProxy.ExecuteCore(OrganizationRequest request)  ilOffset = 0x34
    at PlatformCommand.XrmExecuteInternal()  ilOffset = 0xF6
    at RetrieveCommand.Execute()  ilOffset = 0x2
    at EntityProxy.Retrieve(String[] columns, Guid auditingTransactionId, Boolean addRequiredColumns)  ilOffset = 0x69
    at EntityProxy.Retrieve(String[] columns, Guid auditingTransactionId)  ilOffset = 0x4
    at EntityProxy.Retrieve(String columnSet, Guid auditingTransactionId)  ilOffset = 0xB
    at EntityProxy.Retrieve(String columnSet)  ilOffset = 0x7
    at AppForm.FormLoadEvent()  ilOffset = 0x11
    at AppForm.RaiseDataEvent(FormEventId eventId)  ilOffset = 0xC7
    at EndUserForm.Initialize(Entity entity)  ilOffset = 0x1F
    at CustomizableForm.Execute(Entity entity, FormDescriptor fd)  ilOffset = 0x62
    at RecordPageHandler.ConfigureFormWrapper()  ilOffset = 0xC
    at GenericEventProcessor.RaiseEvent(String eventName)  ilOffset = 0x2D
    at PageManager.OnPreRender(EventArgs e)  ilOffset = 0x47
    at Control.PreRenderRecursiveInternal()  ilOffset = 0x54
    at Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)  ilOffset = 0x6D3
    at Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)  ilOffset = 0x3C
    at Page.ProcessRequest()  ilOffset = 0x14
    at Page.ProcessRequest(HttpContext context)  ilOffset = 0x33
    at CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()  ilOffset = 0x18D
    at HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)  ilOffset = 0x15
    at ApplicationStepManager.ResumeSteps(Exception error)  ilOffset = 0x10A
    at HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)  ilOffset = 0x5C
    at HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr)  ilOffset = 0x16A
    at ISAPIRuntime.ProcessRequest(IntPtr ecb, Int32 iWRType)  ilOffset = 0x4B

That is 75 calls, if you didn’t feel like counting, and in the middle of all of that was the failing call to my plugin.

The nearest thing I can figure is that this Opportunity is set to be System Calculated and when it was opened, a update to the revenue numbers. This ended up firing my plugin which failed because data that was passed to it turned out to be invalid.

I temporarily disabled the plugin and was able to save the Opportunity and correct the invalid data issue.

I could not have done this troubleshooting without the following tools:

If you do not have these tools in your toolbox, you need to fix that today.

Like most Xamarin developers I have a Mac setting on my desk.  Unfortunately I do not find myself to be as productive on a Mac keyboard as I do on the Windows Keyboard.

When Xamarin’s Visual Studio integration was released, and it became stable enough to develop with Visual Studio on my Windows workstation instead of Xamarin Studio on the Mac, I could not have been happier.

The problem still remained that I needed to access the Mac for at least some testing on the iOS simulator.  At first I was just turning my chair and using the Macbook directly.

Then I remembered that GoToMyPC has a Mac client, and I happen to have a two-host license.  So, I installed GotoMyPC on the Mac, and have really enjoyed how much code I can write, and test, using this setup.

I am comfortable with my development tools (Visual Studio, Resharper, etc)., and when I need test my iOS apps, I just open a GotoMyPC session to my Mac and run the simulator.

When I work from home I actually use GotoMyPC to connect to my desktop at the office and when doing iOS development, just start another session to my Mac, which is also at the office.

I mention this now because I don’t think a lot of people think about a remote desktop tool being a productivity aid for developers – and it may not be for everyone – but it sure was for me.

Fellow MVP Jason Lattimer (@JLattimer) has released a really cool tool for us Dynamics CRM JavaScript developers: CRM Rest Builder

This is a solution you install inside of Dynamics CRM with the main interface looking like this:

 

Features

We can utilize the following SDK methods:

  • Retrieve
  • RetrieveMultiple
  • Create
  • Update
  • Delete
  • Associate
  • Disassociate

 

Generated JavaScript

CRM Rest Builder will generate code that utilizes the following JavaScript libraries to actually execute the methods:

  • XrmSvcToolkit,
  • jQuery
  • SDK.REST
  • SDK.JQUERY
  • XMLHTTP

It can also generate Asynchronous or Synchronous method calls, depending on your requirements.

 

Data Selection and Filters

You can select a variety of data points to utilize including:

  • The Entity
  • Set the maximum number of values to be returned
  • Fields
  • One to Many relationships
  • Many to One relationships
  • Many to Many relationships

You can specify the data be filtered much as you would with the Dynamics CRM Advanced Find feature including:

  • Field-level filters
  • Sort orders

 

Output

The generated code is displayed in a window like this:

Conclusion

I actually quite mad at Jason right now.  He would have saved me a couple of hours banging my head against the wall last week.  Actually, I can’t blame Jason for me not paying attention. Smile

Anyway, this is a great tool to add to your development toolbox and I for one, am excited to see it released.

Here is a small method to help you determine if a User is a member of a specified Team:

Hi Everyone,

Just wanted to send you a reminder that next month we are holding two workshops for Dynamics CRM developers:

Plugin Development with Dynamics CRM

JavaScript Development with Dynamics CRM

This may be the last offerings of these workshops for the remainder of the year.

Let me know if you have any questions.

Thanks, Mitch

I thought I’d put together a few reasons why you, the Dynamics CRM developer, should be attending my Extending Dynamics CRM 2013 workshop on July 21st.

 

Reason #1: Hands-on Instruction

Can you type?  Good; because you’ll be doing a lot of exercises.

While I like to hear the sound of my own voice, nothing beats practical practice and all of my courses have lots and lots of labs.

 

Reason #2: The Goodies

My main job is Dynamics CRM architecture and development. I have lots of tools that help me do my job and I share some of those with my development students.

Mostly they are code samples and frameworks to help you become more productive as a Dynamics CRM developer.

 

Reason #3: What Other People Have To Say

Don’t take my word for it, here are what some former students had to say about the workshops they attended:

Mitch’s Plug-in Development workshop helped me get out of the gate and a good way down the path of C# development for Microsoft Dynamics CRM – including both Plug-ins and Workflow Assemblies.

Mitch is an excellent instructor who responds to all questions and helps people along at their own pace. 

I highly recommend this workshop for anyone who is looking to get into the Microsoft CRM development game. It will accelerate your process and save you more than enough time to pay for itself.

Aron F.

Your class was an eye opening experience.  In addition to learning about Plug-In Development this class exposed me to so many other aspects of Microsoft Dynamics CRM that I was not aware of.

Marlon R. Joseph

Application Analyst III

Houston Baptist University

I found Mitch Milam’s workshop to be a great way to jump-start my plug-in development.  Besides presenting class material in such a way that it was easy to comprehend, Mitch also provided Visual Studio templates.  These templates proved to be extremely useful because they take care of the necessary plumbing when writing plug-ins, speeding up the development time.  Additionally, the labs we worked on in class covered real-life scenarios directly applicable to my day-to-day work.  In fact soon after the workshop, I solved a business problem by building a plug-in that was based on one of the labs we worked on in class.

Natalya Pinsker

Baltimore, MD,

 

Reason #4: There Are Only 15 Student Openings

As I mentioned, this is all hands-on so I have to put a limit to the number of students that can be part of the class.  15 people is at the upper limit of my typical classroom size, but since Microsoft doesn’t offer this course as Instructor-led, I want to make sure I can get as many people trained as possible.

 

Reason #5: A Bonus. Maybe.

I have a Dynamics CRM Architecture course under development and if I get enough students in the Extending course, I might just give you a free preview the week of July 28th.

 

So, what are you waiting for?

Sign up today. Review the original announcement for more information and a link to the registration page:

http://www.infinite-x.net/2014/07/01/extending-dynamics-crm-2013-workshop

And drop me a line if you have any questions:

mitch at xrmcoaches dot com

Hi Everyone,

Since I think a lot of people never get around to searching the archives, I thought I’d mention a project I started a while ago to aid the .NET developer in moving your code to the Dynamics CRM 201x version.

The project may be found here:

https://crmdotnetmigrator.codeplex.com/

Project Description
This project is designed to assist the .NET developer who is migrating their C# code from the CRM 4.0 object model to the CRM 2011 object model.

The initial purpose of the project is to generate Visual Studio macros which perform search and replace operations to which change the code from one syntax to the other.

It is planned that in a later stage of the project, we will read and covert source files directly.

 

This project contains all of the knowledge I accumulated during a couple of CRM 4.0 migrations I performed.

If you have some time, take a look.  If you have some knowledge to share and wish to make additions, then please let me know.

Thanks, Mitch

I still occasionally run into hidden greatness inside of the Dynamics CRM SDK.  Last week I found a great addition to the QueryExpression and QueryByAttribute classes: The TopCount property.

This property was introduced into Dynamics CRM 2011 around the UR10-UR11 timeframe, so if you are on UR11, or later, or have Dynamics CRM 2013, you have this capability.

TopCount works exactly like the TOP operator from a SQL SELECT statement:

SELECT TOP 50 * FROM FilteredAccount

 

Here is how you use it:

Note: I have a small function called IsTopCountSupportedByServer that checks the version number against UR11 to make sure we can use TopCount.  If not, we drop back to the standard PagingInfo class.

var maxBatchSize = 50;

QueryExpression queryExpression = new QueryExpression(Account.EntityLogicalName);

if (IsTopCountSupportedByServer())
{
    queryExpression.TopCount = new int?(maxBatchSize);
}
else
{
    queryExpression.PageInfo.Count = maxBatchSize;
    queryExpression.PageInfo.PageNumber = 1;
}

This is just a really cool addition to our toolboxes and I am shocked I didn’t see this before.

Hi Folks,

In preparation of my JavaScript workshop next week, I usually hold a one-hour Introduction to JavaScript webinar that gives students a brief introduction to what JavaScript is and how it works.

I am opening up registration for that webinar to everyone, should you have interest in attending.

And I apologize the for the short notice. It really just occurred to me.

As part of this webinar, you’ll receive a self-paced study guide that you complete on your own time.  It contains some simple exercises that show you how to do JavaScript tasks such as math functions, conditional logic operators, etc.

This webinar will not exactly make you a JavaScript expert, but it show you the basics of JavaScript.

Registration information is below:

 

Introduction to JavaScript

 

Join us for a Webinar on April 25

 

 

Space is limited.
Reserve your Webinar seat now at:
https://www4.gotomeeting.com/register/732347127

 

This is an introduction to JavaScript for Dynamics CRM users who would like to start using JavaScript but do not know where to start.

Title:

Introduction to JavaScript

Date:

Friday, April 25, 2014

Time:

1:30 PM – 2:30 PM CDT

After registering you will receive a confirmation email containing information about joining the Webinar.

System Requirements
PC-based attendees
Required: Windows® 8, 7, Vista, XP or 2003 Server

 

Mac®-based attendees
Required: Mac OS® X 10.6 or newer

 

Mobile attendees
Required: iPhone®, iPad®, Android™ phone or Android tablet

 

Hi Everyone,

Registration closes tonight for next week's Dynamics CRM JavaScript Development workshop.

Eventbrite - JavaScript Development with Dynamics CRM (April)

When:

Monday, April 28th through Thursday, May 1st. 1:00pm-5:00pm each day.

Where:

Online using GoTo Meeting.

What:

This is a hands-on workshop utilizing Dynamics CRM Online.

Cost:

$895 per person (multi-student discounts available)

Note: Due to the interactive nature of this workshop, it will be limited to 10 students.

Student Prerequisite Knowledge:

  • Each student must have working knowledge of Dynamics CRM 2011.
  • Knowledge of JavaScript is also required.

Note: For those students that have not worked with JavaScript previously, a short introduction webinar will be conducted on Friday, April 25th. Students attending this webinar will be expected to have completed the accompanying self-study materials before Monday's class begins. Everyone must be ready to run on Monday for the main class.

Agenda:

Each classroom day will run from 1:00pm to 5:00pm (CST) with the virtual environments available for student use until midnight of May 1st.

And thanks to our virtual development environments, the majority of our time will be spent actually developing JavaScript solutions for Dynamics CRM.

Think labs. Lots and lots of labs. And homework. There will be homework.

We'll cover the following topics:

  • Creating a development environment
    • Setup
    • Source control
    • Working in teams
    • Working with Visual Studio
  • Working with Web Resources
  • Working with Solutions
  • Working with Forms
    • JavaScript libraries
    • Form events
    • Form Event Handler Execution Context Reference
  • Working with the Xrm.Page Object Model
    • Working with Collections
    • Data operations
    • Tabs and Sections
    • Working with Controls
    • Working with iFrames
    • Working with Navigation Items
  • Ribbon button and JavaScript connection
  • Opening Dynamics CRM Forms and Web Resources via JavaScript
  • Using the XrmSrcToolkit to CRM-related data operations

We will be using about 75 of the methods found in the Xrm.Page object model so you should leave class with a fairly good understanding of where things are and how to access them.

If we have time, we will also cover some of the freely available JavaScript components that can be used to aid in your development efforts and to increase your user's productivity.

Students will also receive a draft copy of my upcoming book on Dynamics CRM JavaScript development along with sample code and utility web resources that should help you kick start your CRM JavaScript development efforts.

Eventbrite - JavaScript Development with Dynamics CRM (April)

 

Thanks, Mitch

Sign up for our new KnowledgeBits service and get news, tips and tricks and more, delivered straight to your inbox.