Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.6.x #87

Merged
merged 32 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
3f4978e
Initial work on DynamicsValue/fake-xm-easy#157
jordimontana82 Aug 3, 2024
1ed214b
Use BlockUploadProperties as opposed to BlockUploadRequest
jordimontana82 Aug 4, 2024
a11691f
Update CHANGELOG.md
jordimontana82 Aug 4, 2024
e85ab16
Fix code smells DynamicsValue/fake-xrm-easy#157
jordimontana82 Aug 4, 2024
97a4165
Adding implementation for file block uploads, and commiting of file b…
jordimontana82 Aug 5, 2024
0ac5e1a
Change lock to an object instance
jordimontana82 Aug 5, 2024
5eaa7e6
Add small concurrency test DynamicsValue/fake-xrm-easy#157
jordimontana82 Aug 5, 2024
c4b3f60
Remove unnecessary block
jordimontana82 Aug 5, 2024
25f6b4d
Introduce dedicated exception for DynamicsValue/fake-xrm-easy#158
jordimontana82 Aug 7, 2024
f85ad17
Provides a workaround for DynamicsValue/fake-xrm-easy#158
jordimontana82 Aug 7, 2024
3598f04
Fix new line char
jordimontana82 Aug 7, 2024
e555c74
Adding more tests for DynamicsValue/fake-xrm-easy#158
jordimontana82 Aug 7, 2024
62a3005
Replace constructor by another one that exists across versions Dynami…
jordimontana82 Aug 7, 2024
4f226f0
Validate missing entity reference when trying to upload a file Dynami…
jordimontana82 Aug 7, 2024
ff7f54b
Added logic to also save a new FileAttachment record DynamicsValue/fa…
jordimontana82 Aug 8, 2024
214400e
Adds MaxFileSize validation for file uploads DynamicsValue/fake-xrm-e…
jordimontana82 Aug 8, 2024
0e8bbcd
Rearrange files and add InitializeDownload logic and tests DynamicsVa…
jordimontana82 Aug 9, 2024
69797a8
Update entity reference constructor for backward compatibility Dynami…
jordimontana82 Aug 9, 2024
5c6158b
Implements DownloadBlock logic DynamicsValue/fake-xrm-easy#157
jordimontana82 Aug 10, 2024
376c0ff
Review XML comments for exceptions DynamicsValue/fake-xrm-easy#157
jordimontana82 Aug 10, 2024
7c4b36f
Fix several code smells DynamicsValue/fake-xrm-easy#157
jordimontana82 Aug 10, 2024
3a74af8
Fix last code smell DynamicsValue/fake-xrm-easy#157
jordimontana82 Aug 10, 2024
8d5fb2a
Adds internal DeleteFile method DynamicsValue/fake-xrm-easy#157
jordimontana82 Aug 10, 2024
7be6fb0
Also set file attribute to null when deleting a file DynamicsValue/fa…
jordimontana82 Aug 10, 2024
fe3db51
Deletes a file when an update to the file attribute is set to null Dy…
jordimontana82 Aug 10, 2024
b195f5e
Implements blocked attachments and allowed and blocked mime types Dyn…
jordimontana82 Aug 15, 2024
6cd45ff
Adding Image upload/download tests DynamicsValue/fake-xrm-easy#157
jordimontana82 Aug 15, 2024
bbb932c
Adds basic support for InitializeFiles and several XML comments. Dyna…
jordimontana82 Aug 20, 2024
e51de98
Limit InitializeFiles to v9 DynamicsValue/fake-xrm-easy#157
jordimontana82 Aug 20, 2024
df0aa00
Deletes all associated files when a record is deleted DynamicsValue/f…
jordimontana82 Aug 20, 2024
0a5e2e9
Fix code smells
jordimontana82 Aug 20, 2024
90c023f
Replace Exception by custom Exception DynamicsValue/fake-xrm-easy#157
jordimontana82 Aug 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

### Added

- Added new InMemoryFileDb implementation to support file and image storage - https://github.com/DynamicsValue/fake-xrm-easy/issues/157
- Added default max file size for file and image uploads - https://github.com/DynamicsValue/fake-xrm-easy/issues/157

### Changed

- Resolves an issue in FetchXml queries when using arithmetic values and no early bound assemblies are used. It will now read from injected metadata in absence of proxy type assemblies - https://github.com/DynamicsValue/fake-xrm-easy/issues/158
- Resolves issue in MetadataGenerator where relationship properties were generated in the wrong order, also generates ManyToMany relationship properties - https://github.com/DynamicsValue/fake-xrm-easy/issues/135
- Adds implementation of RelatedEntities in Update message , before it was implemented only for Create - https://github.com/DynamicsValue/fake-xrm-easy/issues/154

Expand Down
22 changes: 20 additions & 2 deletions src/FakeXrmEasy.Core/Db/InMemoryDb.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using FakeXrmEasy.Core.Db.Exceptions;
using System;
using FakeXrmEasy.Core.Db.Exceptions;
using FakeXrmEasy.Extensions;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Metadata;
Expand Down Expand Up @@ -105,13 +106,30 @@ protected internal void AddOrUpdateMetadata(string logicalName, EntityMetadata e

protected internal void AddEntityRecord(Entity e)
{
InMemoryTable table;
if (!ContainsTable(e.LogicalName))
{
InMemoryTable table;
AddTable(e.LogicalName, out table);
}
else
{
table = GetTable(e.LogicalName);
}

table.Add(e);
}

protected internal bool ContainsEntityRecord(string logicalName, Guid id)
{
if (!ContainsTable(logicalName))
{
return false;
}

var table = GetTable(logicalName);
return table.Contains(id);
}

protected internal void AddOrReplaceEntityRecord(Entity e)
{
InMemoryTable table = null;
Expand Down
9 changes: 9 additions & 0 deletions src/FakeXrmEasy.Core/Db/InMemoryTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,5 +126,14 @@ protected internal void SetMetadata(EntityMetadata entityMetadata)
{
_metadata._entityMetadata = entityMetadata.Copy();
}

/// <summary>
/// Returns the entity metadata associated to this column
/// </summary>
/// <returns></returns>
protected internal EntityMetadata GetEntityMetadata()
{
return _metadata._entityMetadata;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;

namespace FakeXrmEasy.Core.Exceptions.Query.FetchXml
{
/// <summary>
/// Exception raised in a query when an attribute value type could not be determined correctly
/// </summary>
public class ArithmeticTypeConversionException: Exception
{
/// <summary>
/// Default constructor
/// </summary>
/// <param name="entityName"></param>
/// <param name="attributeName"></param>
internal ArithmeticTypeConversionException(string entityName, string attributeName) :
base($"When using arithmetic values in a condition of attribute '{attributeName}' of entity '{entityName}' in a Fetch a ProxyTypesAssembly must be used in order to know which types to cast values to. If you are using early bound types, please make sure the early bound type was generated for entity '{entityName}'")
{

}
}
}
48 changes: 31 additions & 17 deletions src/FakeXrmEasy.Core/Extensions/XmlExtensionsForFetchXml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Globalization;
using FakeXrmEasy.Abstractions;
using FakeXrmEasy.Abstractions.Exceptions;
using FakeXrmEasy.Core.Exceptions.Query.FetchXml;

namespace FakeXrmEasy.Extensions.FetchXml
{
Expand Down Expand Up @@ -898,6 +899,26 @@ public static bool ValueNeedsConverting(ConditionOperator conditionOperator)
return !OperatorsNotToConvertArray.Contains(conditionOperator);
}

internal static object GetConditionExpressionBasedOnAttributeType(Type attributeType, string value, string sEntityName, string sAttributeName, ConditionOperator op)
{
try
{
if (ValueNeedsConverting(op))
{
return GetValueBasedOnType(attributeType, value);
}

else
{
return int.Parse(value);
}
}
catch (Exception e)
{
throw new Exception(string.Format("When trying to parse value for entity {0} and attribute {1}: {2}", sEntityName, sAttributeName, e.Message));
}
}

/// <summary>
///
/// </summary>
Expand All @@ -919,25 +940,18 @@ public static object GetConditionExpressionValueCast(string value, IXrmFakedCont
var attributeType = ctx.FindReflectedAttributeType(reflectedType, sEntityName, sAttributeName);
if (attributeType != null)
{
try
{
if (ValueNeedsConverting(op))
{
return GetValueBasedOnType(attributeType, value);
}

else
{
return int.Parse(value);
}
}
catch (Exception e)
{
throw new Exception(string.Format("When trying to parse value for entity {0} and attribute {1}: {2}", sEntityName, sAttributeName, e.Message));
}
return GetConditionExpressionBasedOnAttributeType(attributeType, value, sEntityName, sAttributeName, op);
}
}
}
else
{
var injectedAttributeType = ctx.FindAttributeTypeInInjectedMetadata(sEntityName, sAttributeName);
if (injectedAttributeType != null)
{
return GetConditionExpressionBasedOnAttributeType(injectedAttributeType, value, sEntityName, sAttributeName, op);
}
}

#if FAKE_XRM_EASY_9
if(op == ConditionOperator.ContainValues || op == ConditionOperator.DoesNotContainValues)
Expand Down Expand Up @@ -976,7 +990,7 @@ public static object GetConditionExpressionValueCast(string value, IXrmFakedCont

if (bIsNumeric || bIsDateTime)
{
throw new Exception($"When using arithmetic values in a condition of attribute '{sAttributeName}' of entity '{sEntityName}' in a Fetch a ProxyTypesAssembly must be used in order to know which types to cast values to. If you are using early bound types, please make sure the early bound type was generated for entity '{sEntityName}'");
throw new ArithmeticTypeConversionException(sEntityName, sAttributeName);
}

//Default value
Expand Down
12 changes: 6 additions & 6 deletions src/FakeXrmEasy.Core/FakeXrmEasy.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -102,22 +102,22 @@
</ItemGroup>

<ItemGroup Condition="'$(Configuration)'=='FAKE_XRM_EASY'">
<PackageReference Include="FakeXrmEasy.Abstractions.v2011" Version="[2.5.0-*,3.0)" />
<PackageReference Include="FakeXrmEasy.Abstractions.v2011" Version="[2.6.0-*,3.0)" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'=='FAKE_XRM_EASY_2013'">
<PackageReference Include="FakeXrmEasy.Abstractions.v2013" Version="[2.5.0-*,3.0)" />
<PackageReference Include="FakeXrmEasy.Abstractions.v2013" Version="[2.6.0-*,3.0)" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'=='FAKE_XRM_EASY_2015'">
<PackageReference Include="FakeXrmEasy.Abstractions.v2015" Version="[2.5.0-*,3.0)" />
<PackageReference Include="FakeXrmEasy.Abstractions.v2015" Version="[2.6.0-*,3.0)" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'=='FAKE_XRM_EASY_2016'">
<PackageReference Include="FakeXrmEasy.Abstractions.v2016" Version="[2.5.0-*,3.0)" />
<PackageReference Include="FakeXrmEasy.Abstractions.v2016" Version="[2.6.0-*,3.0)" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'=='FAKE_XRM_EASY_365'">
<PackageReference Include="FakeXrmEasy.Abstractions.v365" Version="[2.5.0-*,3.0)" />
<PackageReference Include="FakeXrmEasy.Abstractions.v365" Version="[2.6.0-*,3.0)" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'=='FAKE_XRM_EASY_9'">
<PackageReference Include="FakeXrmEasy.Abstractions.v9" Version="[2.5.0-*,3.0)" />
<PackageReference Include="FakeXrmEasy.Abstractions.v9" Version="[2.6.0-*,3.0)" />
</ItemGroup>

<Target Name="PreparePackageReleaseNotesFromFile" BeforeTargets="GenerateNuspec">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;

namespace FakeXrmEasy.Core.FileStorage.Db.Exceptions
{
/// <summary>
/// Exception raised when InitializeFiles is called more than once.
/// </summary>
public class AlreadyInitializedFilesException: Exception
{
/// <summary>
/// Default constructor
/// </summary>
public AlreadyInitializedFilesException() : base("InitializeFiles has been called more than once. Always initialize all the files you need in a single call to .InitializeFiles()")
{

}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;

namespace FakeXrmEasy.Core.FileStorage.Db.Exceptions
{
/// <summary>
/// Exception raised when a file is uploaded and its file extension is blocked by the BlockedAttachment settings
/// </summary>
public class BlockedAttachmentException: Exception
{
/// <summary>
/// Default constructor
/// </summary>
internal BlockedAttachmentException(string fileName) : base($"The attachment with file name '{fileName}' is not a valid file extension type")
{

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;

namespace FakeXrmEasy.Core.FileStorage.Db.Exceptions
{
/// <summary>
/// Exception raised when a file is uploaded and its file MIME type is blocked by either the BlockedMimeType or AllowedMimeType settings
/// </summary>
public class BlockedMimeTypeException: Exception
{
/// <summary>
/// Default constructor
/// </summary>
internal BlockedMimeTypeException(string fileName, string mimeType) : base($"The MIME Type '{mimeType}' for file name '{fileName}' is not a valid")
{

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;

namespace FakeXrmEasy.Core.FileStorage.Db.Exceptions
{
/// <summary>
/// Internal exception used for internal testing only thrown when a file could not be added to the InMemoryFileDb
/// </summary>
public class CouldNotAddFileException: Exception
{
/// <summary>
/// Default constructor
/// </summary>
internal CouldNotAddFileException(): base("A file could not be added")
{

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;

namespace FakeXrmEasy.Core.FileStorage.Db.Exceptions
{
/// <summary>
/// Throws an exception when a file could not be committed due to an unknown error
/// </summary>
public class CouldNotCommitFileException: Exception
{
/// <summary>
/// Default constructor
/// </summary>
/// <param name="fileUploadContinuationToken"></param>
internal CouldNotCommitFileException(string fileUploadContinuationToken) : base($"The file associated to continuation token '{fileUploadContinuationToken}' could not be committed due to an unknown error")
{

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;

namespace FakeXrmEasy.Core.FileStorage.Db.Exceptions
{
/// <summary>
/// Exception thrown when a particular file could not be deleted or it doesn't exists
/// </summary>
public class CouldNotDeleteFileException: Exception
{
/// <summary>
/// Default constructor
/// </summary>
/// <param name="fileId"></param>
internal CouldNotDeleteFileException(string fileId) : base($"Could not delete file with Id '{fileId}'")
{

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;

namespace FakeXrmEasy.Core.FileStorage.Db.Exceptions
{
/// <summary>
/// Exception raised when a block id already exists in the current file upload session
/// </summary>
public class DuplicateFileBlockException: Exception
{
/// <summary>
/// Default constructor
/// </summary>
/// <param name="blockId">The block Id that already existed</param>
/// <param name="fileUploadSessionId">The Id of the FileUploadSession where that block existed</param>
internal DuplicateFileBlockException(string blockId, string fileUploadSessionId) : base($"A block was already uploaded with Id {blockId} against the current file continuation token: {fileUploadSessionId}")
{

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;
using Microsoft.Xrm.Sdk;

namespace FakeXrmEasy.Core.FileStorage.Db.Exceptions
{
/// <summary>
/// Exception raised when downloading a file block for a database record and column that doesn't actually have a file against it
/// </summary>
public class FileToDownloadNotFoundException: Exception
{
/// <summary>
/// Default constructor
/// </summary>
/// <param name="entityReference">An entity reference of the record</param>
/// <param name="fileAttributeName">The column where a file was not found</param>
internal FileToDownloadNotFoundException(EntityReference entityReference, string fileAttributeName)
: base($"A file was not found for record with logical name '{entityReference.LogicalName}' and Id '{entityReference.Id.ToString()}' in column '{fileAttributeName}'")
{

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;

namespace FakeXrmEasy.Core.FileStorage.Db.Exceptions
{
/// <summary>
/// Exception thrown when a file continuation token could not be found or invalid, either when initiating a file upload or a file download
/// </summary>
public class FileTokenContinuationNotFoundException: Exception
{
/// <summary>
/// Default constructor
/// </summary>
/// <param name="fileContinuationTokenId">The file continuation token that could not be found</param>
internal FileTokenContinuationNotFoundException(string fileContinuationTokenId)
: base($"The file continuation token with Id '{fileContinuationTokenId}' could not be found or has already been committed")
{

}
}
}
Loading
Loading