init commit

This commit is contained in:
iFlip721
2025-04-16 09:55:57 -04:00
commit a03209dc9e
935 changed files with 177492 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# msbuild output directories
/bin
/obj
# vs intermediate directory
/.vs
# MSBuild Binary and Structured Log
*.binlog

View File

@@ -0,0 +1,30 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/$safeprojectname$.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"${workspaceFolder}/$safeprojectname$.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
]
}

View File

@@ -0,0 +1,44 @@
using Microsoft.Xrm.Sdk;
using System;
namespace $safeprojectname$
{
/*
* Plugin development guide: https://docs.microsoft.com/powerapps/developer/common-data-service/plug-ins
* Best practices and guidance: https://docs.microsoft.com/powerapps/developer/common-data-service/best-practices/business-logic/
*/
public class Plugin1 : PluginBase
{
public Plugin1(string unsecureConfiguration, string secureConfiguration)
: base(typeof(Plugin1))
{
// TODO: Implement your custom configuration handling
// https://docs.microsoft.com/powerapps/developer/common-data-service/register-plug-in#set-configuration-data
}
// Entry point for custom business logic execution
protected override void ExecuteDataversePlugin(ILocalPluginContext localPluginContext)
{
if (localPluginContext == null)
{
throw new ArgumentNullException(nameof(localPluginContext));
}
var context = localPluginContext.PluginExecutionContext;
// TODO: Implement your custom business logic
// Check for the entity on which the plugin would be registered
//if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
//{
// var entity = (Entity)context.InputParameters["Target"];
// // Check for entity name on which this plugin would be registered
// if (entity.LogicalName == "account")
// {
// }
//}
}
}
}

View File

@@ -0,0 +1,282 @@
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Extensions;
using Microsoft.Xrm.Sdk.PluginTelemetry;
using System;
using System.ServiceModel;
namespace $safeprojectname$
{
/// <summary>
/// Base class for all plug-in classes.
/// Plugin development guide: https://docs.microsoft.com/powerapps/developer/common-data-service/plug-ins
/// Best practices and guidance: https://docs.microsoft.com/powerapps/developer/common-data-service/best-practices/business-logic/
/// </summary>
public abstract class PluginBase : IPlugin
{
protected string PluginClassName { get; }
/// <summary>
/// Initializes a new instance of the <see cref="PluginBase"/> class.
/// </summary>
/// <param name="pluginClassName">The <see cref="Type"/> of the plugin class.</param>
internal PluginBase(Type pluginClassName)
{
PluginClassName = pluginClassName.ToString();
}
/// <summary>
/// Main entry point for he business logic that the plug-in is to execute.
/// </summary>
/// <param name="serviceProvider">The service provider.</param>
/// <remarks>
/// </remarks>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", Justification = "Execute")]
public void Execute(IServiceProvider serviceProvider)
{
if (serviceProvider == null)
{
throw new InvalidPluginExecutionException("serviceProvider");
}
// Construct the local plug-in context.
var localPluginContext = new LocalPluginContext(serviceProvider);
localPluginContext.Trace($"Entered {PluginClassName}.Execute() " +
$"Correlation Id: {localPluginContext.PluginExecutionContext.CorrelationId}, " +
$"Initiating User: {localPluginContext.PluginExecutionContext.InitiatingUserId}");
try
{
// Invoke the custom implementation
ExecuteDataversePlugin(localPluginContext);
// Now exit - if the derived plugin has incorrectly registered overlapping event registrations, guard against multiple executions.
return;
}
catch (FaultException<OrganizationServiceFault> orgServiceFault)
{
localPluginContext.Trace($"Exception: {orgServiceFault.ToString()}");
throw new InvalidPluginExecutionException($"OrganizationServiceFault: {orgServiceFault.Message}", orgServiceFault);
}
finally
{
localPluginContext.Trace($"Exiting {PluginClassName}.Execute()");
}
}
/// <summary>
/// Placeholder for a custom plug-in implementation.
/// </summary>
/// <param name="localPluginContext">Context for the current plug-in.</param>
protected virtual void ExecuteDataversePlugin(ILocalPluginContext localPluginContext)
{
// Do nothing.
}
}
/// <summary>
/// This interface provides an abstraction on top of IServiceProvider for commonly used PowerPlatform Dataverse Plugin development constructs
/// </summary>
public interface ILocalPluginContext
{
/// <summary>
/// The PowerPlatform Dataverse organization service for the Current Executing user.
/// </summary>
IOrganizationService InitiatingUserService { get; }
/// <summary>
/// The PowerPlatform Dataverse organization service for the Account that was registered to run this plugin, This could be the same user as InitiatingUserService.
/// </summary>
IOrganizationService PluginUserService { get; }
/// <summary>
/// IPluginExecutionContext contains information that describes the run-time environment in which the plug-in executes, information related to the execution pipeline, and entity business information.
/// </summary>
IPluginExecutionContext PluginExecutionContext { get; }
/// <summary>
/// Synchronous registered plug-ins can post the execution context to the Microsoft Azure Service Bus. <br/>
/// It is through this notification service that synchronous plug-ins can send brokered messages to the Microsoft Azure Service Bus.
/// </summary>
IServiceEndpointNotificationService NotificationService { get; }
/// <summary>
/// Provides logging run-time trace information for plug-ins.
/// </summary>
ITracingService TracingService { get; }
/// <summary>
/// General Service Provider for things not accounted for in the base class.
/// </summary>
IServiceProvider ServiceProvider { get; }
/// <summary>
/// OrganizationService Factory for creating connection for other then current user and system.
/// </summary>
IOrganizationServiceFactory OrgSvcFactory { get; }
/// <summary>
/// ILogger for this plugin.
/// </summary>
ILogger Logger { get; }
/// <summary>
/// Writes a trace message to the CRM trace log.
/// </summary>
/// <param name="message">Message name to trace.</param>
void Trace(string message, [CallerMemberName] string method = null);
}
/// <summary>
/// Plug-in context object.
/// </summary>
public class LocalPluginContext : ILocalPluginContext
{
/// <summary>
/// The PowerPlatform Dataverse organization service for current user account.
/// </summary>
public IOrganizationService InitiatingUserService { get; }
/// <summary>
/// The PowerPlatform Dataverse organization service for system user account.
/// </summary>
public IOrganizationService PluginUserService { get; }
/// <summary>
/// IPluginExecutionContext contains information that describes the run-time environment in which the plug-in executes, information related to the execution pipeline, and entity business information.
/// </summary>
public IPluginExecutionContext PluginExecutionContext { get; }
/// <summary>
/// Synchronous registered plug-ins can post the execution context to the Microsoft Azure Service Bus. <br/>
/// It is through this notification service that synchronous plug-ins can send brokered messages to the Microsoft Azure Service Bus.
/// </summary>
public IServiceEndpointNotificationService NotificationService { get; }
/// <summary>
/// Provides logging run-time trace information for plug-ins.
/// </summary>
public ITracingService TracingService { get; }
/// <summary>
/// General Service Provider for things not accounted for in the base class.
/// </summary>
public IServiceProvider ServiceProvider { get; }
/// <summary>
/// OrganizationService Factory for creating connection for other then current user and system.
/// </summary>
public IOrganizationServiceFactory OrgSvcFactory { get; }
/// <summary>
/// ILogger for this plugin.
/// </summary>
public ILogger Logger { get; }
/// <summary>
/// Helper object that stores the services available in this plug-in.
/// </summary>
/// <param name="serviceProvider"></param>
public LocalPluginContext(IServiceProvider serviceProvider)
{
if (serviceProvider == null)
{
throw new InvalidPluginExecutionException("serviceProvider");
}
ServiceProvider = serviceProvider;
Logger = serviceProvider.Get<ILogger>();
PluginExecutionContext = serviceProvider.Get<IPluginExecutionContext>();
TracingService = new LocalTracingService(serviceProvider);
NotificationService = serviceProvider.Get<IServiceEndpointNotificationService>();
OrgSvcFactory = serviceProvider.Get<IOrganizationServiceFactory>();
PluginUserService = serviceProvider.GetOrganizationService(PluginExecutionContext.UserId); // User that the plugin is registered to run as, Could be same as current user.
InitiatingUserService = serviceProvider.GetOrganizationService(PluginExecutionContext.InitiatingUserId); //User who's action called the plugin.
}
/// <summary>
/// Writes a trace message to the CRM trace log.
/// </summary>
/// <param name="message">Message name to trace.</param>
public void Trace(string message)
{
if (string.IsNullOrWhiteSpace(message) || TracingService == null)
{
return;
}
if (PluginExecutionContext == null)
{
TracingService.Trace(message);
}
else
{
TracingService.Trace(string.format(
"{0}, Correlation Id: {1}, Initiating User: {2}",
message,
PluginExecutionContext.CorrelationId,
PluginExecutionContext.InitiatingUserId));
}
}
}
/// <summary>
/// Specialized ITracingService implementation that prefixes all traced messages with a time delta for Plugin performance diagnostics
/// </summary>
public class LocalTracingService : ITracingService
{
private readonly ITracingService _tracingService;
private DateTime _previousTraceTime;
public LocalTracingService(IServiceProvider serviceProvider)
{
DateTime utcNow = DateTime.UtcNow;
var context = (IExecutionContext)serviceProvider.GetService(typeof(IExecutionContext));
DateTime initialTimestamp = context.OperationCreatedOn;
if (initialTimestamp > utcNow)
{
initialTimestamp = utcNow;
}
_tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
_previousTraceTime = initialTimestamp;
}
public void Trace(string message, params object[] args)
{
var utcNow = DateTime.UtcNow;
// The duration since the last trace.
var deltaMilliseconds = utcNow.Subtract(_previousTraceTime).TotalMilliseconds;
try
{
if (args == null || args.Length == 0)
_tracingService.Trace($"[+{deltaMilliseconds:N0}ms] - {message}");
else
_tracingService.Trace($"[+{deltaMilliseconds:N0}ms] - {string.Format(message, args)}");
}
catch (FormatException ex)
{
throw new InvalidPluginExecutionException($"Failed to write trace message due to error {ex.Message}", ex);
}
_previousTraceTime = utcNow;
}
}
}

View File

@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net462</TargetFramework>
<PowerAppsTargetsPath>$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\PowerApps</PowerAppsTargetsPath>$SignAssemblyBlock$
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<ProjectTypeGuids>{4C25E9B5-9FA6-436c-8E19-B395D2A65FAF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
</PropertyGroup>
<Import Project="$(PowerAppsTargetsPath)\Microsoft.PowerApps.VisualStudio.Plugin.props" Condition="Exists('$(PowerAppsTargetsPath)\Microsoft.PowerApps.VisualStudio.Plugin.props')" />
<ItemGroup>
<PackageReference Include="Microsoft.CrmSdk.CoreAssemblies" Version="9.0.2.*" />
<PackageReference Include="Microsoft.PowerApps.MSBuild.Plugin" Version="1.*" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
<Import Project="$(PowerAppsTargetsPath)\Microsoft.PowerApps.VisualStudio.Plugin.targets" Condition="Exists('$(PowerAppsTargetsPath)\Microsoft.PowerApps.VisualStudio.Plugin.targets')" />
</Project>