gpt4 book ai didi

c# - CRM 插件 : Custom Exception in Sandbox

转载 作者:太空狗 更新时间:2023-10-29 21:39:22 27 4
gpt4 key购买 nike

我有一个在沙盒中执行的 Dynamics CRM 2013 插件。

此代码具有以下自定义异常类:

    [Serializable]
public class PluginValidationException : Exception
{
public PluginValidationException()
{
}

protected PluginValidationException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}

public PluginValidationException(string message)
: base(message)
{
}

public PluginValidationException(string message, Exception inner)
: base(message, inner)
{
}
}

当在插件中抛出此异常时,它会产生一个通用错误窗口,日志文件中没有详细信息:

enter image description here

未处理的异常:System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: System. Runtime.Serialization.SerializationException:Microsoft Dynamics CRM 遇到错误。管理员或支持人员的引用编号:#1355B4E4详细信息: -2147220970 调用栈 在 Microsoft.Crm.Application.Platform.ServiceCommands.PlatformCommand.XrmExecuteInternal() 在 Microsoft.Crm.Application.Platform.ServiceCommands.CreateCommand.Execute() 在 Microsoft.Crm.Application.Platform.EntityProxy.Create( bool performDuplicateCheck,Guid auditingTransactionId) 在 Microsoft.Crm.Application.Platform.EntityProxy.Create( bool performDuplicateCheck) 在 Microsoft.Crm.Application.Platform.EntityProxy.CreateAndRetrieve(String[] columnSet,Boolean performDuplicateCheck) 在 Microsoft.Crm.Application.WebServices.InlineEdit.CommandBase.UpdateEntity(实体实体, bool 检索) 在 Microsoft.Crm.Application.WebServices.InlineEdit.SaveCommand.ExecuteCommand(字符串 commandXml) 在 Microsoft.Crm.Application.WebServices.InlineEdit.CommandBase.Execute(字符串 commandXml) System.Runtime.Serialization.SerializationException:Microsoft Dynamics CRM 遇到错误。管理员或支持引用号:#1355B4E4 2014-04-06T02:04:30.0972001Z [Demo.DemoPlugin: Demo.DemoPlugin.BasicCrmPlugin][d86b89ab-f1bc-e311-9408-000c29254b18:Demo.DemoPlugin.BasicCrmPlugin:创建联系人]

查看 CRM 跟踪日志显示以下内容:

System.Runtime.Serialization.SerializationException:程序集“Demo.DemoPlugin,Version=1.0.0.0,Culture=neutral,PublicKeyToken=fbb51ba1e588d276”中的类型“Demo.Helpers.PluginValidationException”未标记为可序列化。 在 Microsoft.Crm.Sandbox.SandboxAppDomainHelper.Execute(IServiceEndpointNotificationService serviceBusService、IOrganizationServiceFactory organizationServiceFactory、String pluginTypeName、String pluginConfiguration、String pluginSecureConfig、IPluginExecutionContext requestContext) 在 Microsoft.Crm.Sandbox.SandboxWorker.Execute(SandboxCallInfo callInfo、SandboxPluginExecutionContext requestContext、Guid pluginAssemblyId、Int32 sourceHash、String assemblyName、Guid pluginTypeId、String pluginTypeName、String pluginConfiguration、String pluginSecureConfig、SandboxRequestCounter 和 workerCounter)

根据一些阅读,我不认为这是一个错误 - 而是因为自定义 Exception 类从 .NET 4 开始就不是本质上受信任的(我使用的是 .NET 4.5 .)

有谁知道如何制作将与 CRM 沙盒一起使用的自定义异常类。我正在使用自定义异常类,因为我捕获了错误并且需要区分 InvalidPluginExecutionException 和由于插件未正确注册而导致的异常。

2014 年 4 月 8 日更新

这是插件中捕获异常的代码,将其放在 Stackoverflow 上进行了显着简化:

        try
{
//TODO: Prevalidation Logic
ValidatePluginExecution(crmContext, logging, out keyName);
//TODO: Postvalidation Logic
}
catch (PluginValidationException ex)
{
//TODO: Specific logging for Plugin Validation Exception
throw new InvalidPluginExecutionException("Did Not Validate");
}
catch (InvalidPluginExecutionException ex)
{
logging.Write("InvalidPluginExectionException at Plugin Validation");
throw;
}
catch (Exception ex)
{
logging.Write("Unhandled Exeception During Plugin Validation Operation");
logging.Write(ex);
throw new InvalidPluginExecutionException("Error. Download Log and submit to the Help Desk.", ex);
}

最佳答案

经过一些额外的测试,这是我能够确定的:

显然,您可以访问 Stack Trace 以查找异常,前提是明确这样做。当从沙盒插件中抛出异常时,只要异常是 CRM 平台“知道”的异常,实际上就不会显示异常的堆栈跟踪(不确定它在做什么,但我猜它是正在查看异常的类型,并以不同的方式处理不同的类型)。如果类型未知,则会导致 CRM 尝试序列化 a 中不允许的异常,因为它使用反射(为什么必须序列化,不确定)。

这是一个示例插件,其中一些示例有效,一些示例无效:

public class TestPlugin: IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
try
{
OtherMethod();
}
catch (Exception ex)
{
var trace = (ITracingService)serviceProvider.GetService(typeof (ITracingService));
trace.Trace("Throwing Plugin");
// Doesn't work
throw new InvalidPluginExecutionException("Error ", ex);
}
}

// Works:
//public void Execute(IServiceProvider serviceProvider)
//{
//try
//{
//OtherMethod();
//}
//catch (Exception ex)
//{
//var trace = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
//trace.Trace("Throwing Plugin");
//throw new InvalidPluginExecutionException("Error " + ex);
//}
//}

// Doesn't Work:
//public void Execute(IServiceProvider serviceProvider)
//{
// try
// {
// OtherMethod();
// }
// catch (Exception ex)
// {
// throw;
// }
//}

// Doesn't Work:
//public void Execute(IServiceProvider serviceProvider)
//{
// try
// {
// OtherMethod();
// }
// catch (Exception ex)
// {
// throw new InvalidPluginExecutionException("Error", ex);
// }
//}

public void OtherMethod()
{
throw new MyException();
}
}

public class MyException : Exception
{

}

所以回答你的问题:我写了一个异常处理程序来处理内部异常并确定抛出它是否有效:

/// <summary>
/// Exception Handler For Exceptions when executing in Sandbox Isolation Mode
/// </summary>
public class ExceptionHandler
{
/// <summary>
/// Determines whether the given exception can be thrown in sandbox mode.
/// Throws a Safe if it can't
/// </summary>
/// <param name="ex">The ex.</param>
/// <returns></returns>
/// <exception cref="InvalidPluginExecutionException"></exception>
/// <exception cref="Exception"></exception>
public static bool CanThrow(Exception ex)
{
var exceptionRootTypeIsValid = IsValidToBeThrown(ex);
var canThrow = exceptionRootTypeIsValid;
var innerException = ex.InnerException;

// While the Exception Types are still valid to be thrown, loop through all inner exceptions, checking for validity
while (canThrow && innerException != null)
{
if (IsValidToBeThrown(ex))
{
innerException = innerException.InnerException;
}
else
{
canThrow = false;
}
}

if (canThrow)
{
return true;
}

var exceptionMessage = ex.Message +
(ex.InnerException == null
? string.Empty
: " Inner Exception: " + ex.InnerException.ToStringWithCallStack());

// ReSharper disable once InvertIf - I like it better this way
if (exceptionRootTypeIsValid)
{
// Attempt to throw the exact Exception Type, with the
var ctor = ex.GetType().GetConstructor(new[] { typeof(string) });
if (ctor != null)
{
throw (Exception) ctor.Invoke(new object[] { exceptionMessage });
}
}

throw new Exception(exceptionMessage);
}

/// <summary>
/// Determines whether the specified ex is valid to be thrown.
/// Current best guess is that it is not
/// </summary>
/// <param name="ex">The ex.</param>
/// <returns></returns>
private static bool IsValidToBeThrown(Exception ex)
{
var assembly = ex.GetType().Assembly.FullName.ToLower();
return assembly.StartsWith("mscorlib,") || assembly.StartsWith("microsoft.xrm.sdk,");
}
}

这可以从你的插件中最上面的 try catch 调用,如下所示:

catch (InvalidPluginExecutionException ex)
{
context.LogException(ex);
// This error is already being thrown from the plugin, just throw
if (context.PluginExecutionContext.IsolationMode == (int) IsolationMode.Sandbox)
{
if (Sandbox.ExceptionHandler.CanThrow(ex))
{
throw;
}
}
else
{
throw;
}
}
catch (Exception ex)
{
// Unexpected Exception occurred, log exception then wrap and throw new exception
context.LogException(ex);
ex = new InvalidPluginExecutionException(ex.Message, ex);
if (context.PluginExecutionContext.IsolationMode == (int)IsolationMode.Sandbox)
{
if (Sandbox.ExceptionHandler.CanThrow(ex))
{
// ReSharper disable once PossibleIntendedRethrow - Wrap the exception in an InvalidPluginExecutionException
throw ex;
}
}
else
{
// ReSharper disable once PossibleIntendedRethrow - Wrap the exception in an InvalidPluginExecutionException
throw ex;
}
}

我相信这是一个真正的错误,我已经向微软开具了支持票,我们将看看他们是否同意...

更新!!

我与 Microsoft 创建了一个票证:(不确定这些数字的含义,但它们在主题中并且希望将来对某人有益:REG:115122213520585 SRXCAP:1318824373ID)。他们确实确认 CRM 中不支持沙盒插件的自定义异常。

请对此投票 Connect Ticket让 Microsoft 修复此问题或至少更好地处理它!

关于c# - CRM 插件 : Custom Exception in Sandbox,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22889215/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com