diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..9aac13e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,353 @@ +# https://editorconfig.org/ +root=true + +[*] +charset = utf-8 +indent_style = space + +#Eliminar todos los espacios en blanco que preceden a los caracteres de nueva línea +trim_trailing_whitespace = true + +#Asegurarse de que el archivo termine con una nueva línea al guardar +insert_final_newline = true + +[{*.cpp,*.c,*.hpp,*.h,*.cs,*.razor}] +indent_size = 4 +tab_width = 4 + +# XML project files +[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] +indent_size = 4 +tab_width = 4 + +# XML config files +[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] +indent_size = 4 +tab_width = 4 + +[*.json] +indent_size = 4 +tab_width = 4 + +[*.cs] +# Sort using and Import directives with System.* appearing first +dotnet_sort_system_directives_first = true +dotnet_separate_import_directive_groups = false + +# Avoid "this." if not necessary +dotnet_style_qualification_for_field = false:refactoring +dotnet_style_qualification_for_property = false:refactoring +dotnet_style_qualification_for_method = false:refactoring +dotnet_style_qualification_for_event = false:refactoring + +# Use language keywords instead of framework type names for type references +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# Whitespace options +dotnet_style_allow_multiple_blank_lines_experimental = false + +# Non-private static fields are PascalCase +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non_private_static_fields +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style + +dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field +dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected +dotnet_naming_symbols.non_private_static_fields.required_modifiers = static + +dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case + +# Constants are PascalCase +dotnet_naming_rule.constants_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants +dotnet_naming_rule.constants_should_be_pascal_case.style = constant_style + +dotnet_naming_symbols.constants.applicable_kinds = field, local +dotnet_naming_symbols.constants.required_modifiers = const + +dotnet_naming_style.constant_style.capitalization = pascal_case + +# Instance fields are camelCase and start with _ +dotnet_naming_rule.instance_fields_should_be_camel_case.severity = suggestion +dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields +dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style + +dotnet_naming_symbols.instance_fields.applicable_kinds = field + +dotnet_naming_style.instance_field_style.capitalization = camel_case +dotnet_naming_style.instance_field_style.required_prefix = _ + +# Locals and parameters are camelCase +dotnet_naming_rule.locals_should_be_camel_case.severity = suggestion +dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters +dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style + +dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local + +dotnet_naming_style.camel_case_style.capitalization = camel_case + +# Local functions are PascalCase +dotnet_naming_rule.local_functions_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions +dotnet_naming_rule.local_functions_should_be_pascal_case.style = local_function_style + +dotnet_naming_symbols.local_functions.applicable_kinds = local_function + +dotnet_naming_style.local_function_style.capitalization = pascal_case + +# By default, name items with PascalCase +dotnet_naming_rule.members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members +dotnet_naming_rule.members_should_be_pascal_case.style = pascal_case_style + +dotnet_naming_symbols.all_members.applicable_kinds = * + +dotnet_naming_style.pascal_case_style.capitalization = pascal_case + +# RS0016: Only enable if API files are present +dotnet_public_api_analyzer.require_api_files = true + +# Dotnet code style settings: +[*.{cs}] + +# Sort using and Import directives with System.* appearing first +dotnet_sort_system_directives_first = true +dotnet_separate_import_directive_groups = false +# Avoid "this." and "Me." if not necessary +dotnet_style_qualification_for_field = false:refactoring +dotnet_style_qualification_for_property = false:refactoring +dotnet_style_qualification_for_method = false:refactoring +dotnet_style_qualification_for_event = false:refactoring + +# Use language keywords instead of framework type names for type references +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# Suggest more modern language features when available +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion + +# Whitespace options +dotnet_style_allow_multiple_blank_lines_experimental = false + +# Non-private static fields are PascalCase +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non_private_static_fields +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style + +dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field +dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected +dotnet_naming_symbols.non_private_static_fields.required_modifiers = static + +dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case + +# Non-private readonly fields are PascalCase +dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.symbols = non_private_readonly_fields +dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.style = non_private_readonly_field_style + +dotnet_naming_symbols.non_private_readonly_fields.applicable_kinds = field +dotnet_naming_symbols.non_private_readonly_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected +dotnet_naming_symbols.non_private_readonly_fields.required_modifiers = readonly + +dotnet_naming_style.non_private_readonly_field_style.capitalization = pascal_case + +# Constants are PascalCase +dotnet_naming_rule.constants_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants +dotnet_naming_rule.constants_should_be_pascal_case.style = constant_style + +dotnet_naming_symbols.constants.applicable_kinds = field, local +dotnet_naming_symbols.constants.required_modifiers = const + +dotnet_naming_style.constant_style.capitalization = pascal_case + +# Static fields are camelCase and start with s_ +dotnet_naming_rule.static_fields_should_be_camel_case.severity = suggestion +dotnet_naming_rule.static_fields_should_be_camel_case.symbols = static_fields +dotnet_naming_rule.static_fields_should_be_camel_case.style = static_field_style + +dotnet_naming_symbols.static_fields.applicable_kinds = field +dotnet_naming_symbols.static_fields.required_modifiers = static + +dotnet_naming_style.static_field_style.capitalization = camel_case +dotnet_naming_style.static_field_style.required_prefix = s_ + +# Instance fields are camelCase and start with _ +dotnet_naming_rule.instance_fields_should_be_camel_case.severity = suggestion +dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields +dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style + +dotnet_naming_symbols.instance_fields.applicable_kinds = field + +dotnet_naming_style.instance_field_style.capitalization = camel_case +dotnet_naming_style.instance_field_style.required_prefix = _ + +# Locals and parameters are camelCase +dotnet_naming_rule.locals_should_be_camel_case.severity = suggestion +dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters +dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style + +dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local + +dotnet_naming_style.camel_case_style.capitalization = camel_case + +# Local functions are PascalCase +dotnet_naming_rule.local_functions_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions +dotnet_naming_rule.local_functions_should_be_pascal_case.style = local_function_style + +dotnet_naming_symbols.local_functions.applicable_kinds = local_function + +dotnet_naming_style.local_function_style.capitalization = pascal_case + +# By default, name items with PascalCase +dotnet_naming_rule.members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members +dotnet_naming_rule.members_should_be_pascal_case.style = pascal_case_style + +dotnet_naming_symbols.all_members.applicable_kinds = * + +dotnet_naming_style.pascal_case_style.capitalization = pascal_case + +# RS0016: Only enable if API files are present +dotnet_public_api_analyzer.require_api_files = true + +# CSharp code style settings: + +[*.cs] +# Newline settings +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_switch_labels = true +csharp_indent_labels = flush_left + +# Whitespace options +csharp_style_allow_embedded_statements_on_same_line_experimental = false +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = false +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = false + +# Prefer "var" everywhere +csharp_style_var_for_built_in_types = true:suggestion +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = true:suggestion + +# Prefer method-like constructs to have a block body +csharp_style_expression_bodied_methods = false:none +csharp_style_expression_bodied_constructors = false:none +csharp_style_expression_bodied_operators = false:none + +# Prefer property-like constructs to have an expression-body +csharp_style_expression_bodied_properties = true:none +csharp_style_expression_bodied_indexers = true:none +csharp_style_expression_bodied_accessors = true:none + +# Suggest more modern language features when available +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion +csharp_style_prefer_extended_property_pattern = true:suggestion + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = do_not_ignore +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# Blocks are allowed +csharp_prefer_braces = true:silent +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true + +# IDE0060: Remove unused parameter +dotnet_diagnostic.IDE0060.severity = warning + +[src/{Compilers,ExpressionEvaluator,Scripting}/**Test**/*.{cs}] + +# IDE0060: Remove unused parameter +dotnet_diagnostic.IDE0060.severity = none + +[src/{Analyzers,CodeStyle,Features,Workspaces,EditorFeatures,VisualStudio}/**/*.{cs}] + +# IDE0011: Add braces +csharp_prefer_braces = when_multiline:warning +# NOTE: We need the below severity entry for Add Braces due to https://github.com/dotnet/roslyn/issues/44201 +dotnet_diagnostic.IDE0011.severity = warning + +# IDE0040: Add accessibility modifiers +dotnet_diagnostic.IDE0040.severity = warning + +# IDE0052: Remove unread private member +dotnet_diagnostic.IDE0052.severity = warning + +# IDE0059: Unnecessary assignment to a value +dotnet_diagnostic.IDE0059.severity = warning + +# CA1012: Abstract types should not have public constructors +dotnet_diagnostic.CA1012.severity = warning + +# CA1822: Make member static +dotnet_diagnostic.CA1822.severity = warning + +# Prefer "var" everywhere +dotnet_diagnostic.IDE0007.severity = warning +csharp_style_var_for_built_in_types = true:warning +csharp_style_var_when_type_is_apparent = true:warning +csharp_style_var_elsewhere = true:warning + +# csharp_style_allow_embedded_statements_on_same_line_experimental +dotnet_diagnostic.IDE2001.severity = warning + +# csharp_style_allow_blank_lines_between_consecutive_braces_experimental +dotnet_diagnostic.IDE2002.severity = warning + +# csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental +dotnet_diagnostic.IDE2004.severity = warning + +# csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental +dotnet_diagnostic.IDE2005.severity = warning + +# csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental +dotnet_diagnostic.IDE2006.severity = warning + +[src/{VisualStudio}/**/*.{cs}] +# CA1822: Make member static +# There is a risk of accidentally breaking an internal API that partners rely on though IVT. +dotnet_code_quality.CA1822.api_surface = private \ No newline at end of file diff --git a/src/AzureStorageWrapper/AzureStorageWrapper.sln b/AzureStorageWrapper.sln similarity index 55% rename from src/AzureStorageWrapper/AzureStorageWrapper.sln rename to AzureStorageWrapper.sln index 3cffa2b..65125f6 100644 --- a/src/AzureStorageWrapper/AzureStorageWrapper.sln +++ b/AzureStorageWrapper.sln @@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.6.33829.357 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureStorageWrapper", "AzureStorageWrapper\AzureStorageWrapper.csproj", "{7B7A6304-3A42-4BCA-A7F3-61571EFB8D29}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureStorageWrapper", "src\AzureStorageWrapper\AzureStorageWrapper.csproj", "{2589764D-0229-ED26-7A68-14C5BD399C78}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureStorageWrapper.Tests", "AzureStorageWrapper.Tests\AzureStorageWrapper.Tests.csproj", "{31240418-FC87-432D-9D11-848CCE2C0B06}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureStorageWrapper.Tests", "src\AzureStorageWrapper.Tests\AzureStorageWrapper.Tests.csproj", "{AE079CC8-4A2D-DEA4-B0CB-ABEA826CED09}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -13,14 +13,14 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7B7A6304-3A42-4BCA-A7F3-61571EFB8D29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7B7A6304-3A42-4BCA-A7F3-61571EFB8D29}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7B7A6304-3A42-4BCA-A7F3-61571EFB8D29}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7B7A6304-3A42-4BCA-A7F3-61571EFB8D29}.Release|Any CPU.Build.0 = Release|Any CPU - {31240418-FC87-432D-9D11-848CCE2C0B06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {31240418-FC87-432D-9D11-848CCE2C0B06}.Debug|Any CPU.Build.0 = Debug|Any CPU - {31240418-FC87-432D-9D11-848CCE2C0B06}.Release|Any CPU.ActiveCfg = Release|Any CPU - {31240418-FC87-432D-9D11-848CCE2C0B06}.Release|Any CPU.Build.0 = Release|Any CPU + {2589764D-0229-ED26-7A68-14C5BD399C78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2589764D-0229-ED26-7A68-14C5BD399C78}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2589764D-0229-ED26-7A68-14C5BD399C78}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2589764D-0229-ED26-7A68-14C5BD399C78}.Release|Any CPU.Build.0 = Release|Any CPU + {AE079CC8-4A2D-DEA4-B0CB-ABEA826CED09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AE079CC8-4A2D-DEA4-B0CB-ABEA826CED09}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AE079CC8-4A2D-DEA4-B0CB-ABEA826CED09}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AE079CC8-4A2D-DEA4-B0CB-ABEA826CED09}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/FALTA.txt b/FALTA.txt new file mode 100644 index 0000000..4ed538a --- /dev/null +++ b/FALTA.txt @@ -0,0 +1,4 @@ ++ TestUnitario ++ Actualizar Samples +- Actualizar Readme +Vise@2025! \ No newline at end of file diff --git a/README.md b/README.md index 6f175d5..64b1f4f 100644 --- a/README.md +++ b/README.md @@ -11,21 +11,96 @@ 📦 View package on [NuGet Gallery](https://www.nuget.org/packages/AzureStorageWrapper/) 📦 View package on [nuget.info](https://nuget.info/packages/AzureStorageWrapper) +## Supported framework + +* .Net Standard 2.0 +* .Net Standard 2.1 + +## Installation the package +Install the AzureStorageWrapper client library for .NET with NuGet: + +```dotnetcli +dotnet add package AzureStorageWrapper + ``` + +``` nuget +NuGet Install-Package AzureStorageWrapper -Version x.y.z +``` +This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of [Install-Package](https://learn.microsoft.com/es-es/nuget/reference/ps-reference/ps-ref-install-package). + +``` + +``` + For projects that support [PackageReference](https://learn.microsoft.com/es-es/nuget/consume-packages/package-references-in-project-files), copy this XML node into the project file to reference the package. + # Usage ## Dependency injection -To add **AzureStorageWrapper** to dependencies container, just use the method `AddAzureStorageWrapper(...)` +### File configuration +#### local.settings.json (Azure Function) +```json +{ + "IsEncrypted": false, + "Values": { + "AzureWebJobsStorage": "UseDevelopmentStorage=true", + "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", + + //Configuration StorageWrapper + StorageWrapper_ConnectionsString="..." //Is a configuration setting that contains the necessary information to connect to your Azure Storage account. Type: String. Recomended + StorageWrapper_MaxSasUriExpiration="..." //It sets the maximum duration for the Shared Access Signature (SAS) URI of an Azure Storage file. Type: int. Default: 600. Optional + StorageWrapper_DefaultSasUriExpiration="..." //It sets the default duration for the Shared Access Signature (SAS) URI of an Azure Storage file. Type: int. Default: 300. Optional + StorageWrapper_ReateContainerIfNotExists="..." //Determines whether the Azure Storage container should be automatically created if it does not already exist.Type: bool. Defult: true. Optional + StorageWrapper_DefaultContainer="..." // Specifies the default container name to be used for storing blobs. Type: String. Optional + } +} +``` +#### app.settings.json +```json +{ + //Configuration StorageWrapper + //Configuration StorageWrapper + StorageWrapper_ConnectionsString="..." //Is a configuration setting that contains the necessary information to connect to your Azure Storage account. Type: String. Recomended + StorageWrapper_MaxSasUriExpiration="..." //It sets the maximum duration for the Shared Access Signature (SAS) URI of an Azure Storage file. Type: int. Default: 600. Optional + StorageWrapper_DefaultSasUriExpiration="..." //It sets the default duration for the Shared Access Signature (SAS) URI of an Azure Storage file. Type: int. Default: 300. Optional + StorageWrapper_ReateContainerIfNotExists="..." //Determines whether the Azure Storage container should be automatically created if it does not already exist.Type: bool. Defult: true. Optional + StorageWrapper_DefaultContainer="..." // Specifies the default container name to be used for storing blobs. Type: String. Optional +} +``` + +> **Remember** that the variable names are suggested and you can change them according to your needs. + +### Minimal Configuration +To add **AzureStorageWrapper** to dependencies container. + +```csharp +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddAzureStorageWrapper(); +``` +> **Warning:** You must configure the **StorageWrapper_ConnectionString** variable in the configuration file. + +### ConnectionString Configuration +To add **AzureStorageWrapper** to dependencies container, just use the method `AddAzureStorageWrapper(string connectionstring)` ```csharp var builder = WebApplication.CreateBuilder(args); +var connectionString = builder.Configuration["Connection_String"]; +builder.Services.AddAzureStorageWrapper(connectionString); +``` +### Configuration +To add **AzureStorageWrapper** to dependencies container, just use the method `AddAzureStorageWrapper(...)` -builder.Services.AddAzureStorageWrapper(configuration => +```csharp +var builder = WebApplication.CreateBuilder(args); +var connectionString = builder.Configuration["Connection_String"]; +builder.Services.AddAzureStorageWrapper(options => { - configuration.ConnectionString = "azure-storage-connection-string"; - configuration.MaxSasUriExpiration = 600; - configuration.DefaultSasUriExpiration = 300; - configuration.CreateContainerIfNotExists = true; + options.ConnectionString = "azure-storage-connection-string"; + options.MaxSasUriExpiration = 600; + options.DefaultSasUriExpiration = 300; + options.CreateContainerIfNotExists = true; + options.DefaultContainer = "azure-container-name"; }); ``` @@ -34,6 +109,7 @@ These are the *main* properties: - **MaxSasUriExpiration**: You can set a maximum duration value for the Shared Access Signature (SAS) of an Azure Storage file to prevent someone from attempting to generate a token with a longer expiration time. The duration is expressed in seconds. - **DefaultSasUriExpiration**: You can download a file using AzureStorageWrapper without specifying the `ExpiresIn` property. By doing so, this value will be automatically set. The duration is xpressed in seconds - **CreateContainerIfNotExists**: When uploading a file to Azure Storage, you need to specify the container, which may not exist and can be created automatically. You can set it to `true` or `false` based on your requirements. Consider this property if you have automated your infrastructure with an Infrastructure as Code (IaC) mechanism because it affects the state of your infrastructure. +- **DefaultContainer**: Specifies the default container name to be used for storing blobs when no container name is provided during the upload or enumeration operations. Option is designed to simplify the configuration when you are using a single container in your solution. By setting a default container, you avoid the need to specify the container name for every operation, making the code cleaner and reducing the risk of errors. Then you can inject `IAzureStorageWrapper` into your services through constructor: @@ -78,6 +154,26 @@ var command = new UploadBase64() var response = await _azureStorageWrapper.UploadBlobAsync(command); ``` +```csharp +//If the DefaultContainer option is set +var base64 = "SGVsbG8g8J+Zgg=="; + +var file = "hello.md"; +var contentBase64 = base64; + +var response = await _azureStorageWrapper.UploadBlobAsync(file, contentBase64); +``` + +```csharp +var base64 = "SGVsbG8g8J+Zgg=="; + +var file = "hello.md"; +var contentBase64 = base64; +var container = "files"; + +var response = await _azureStorageWrapper.UploadBlobAsync(file, contentBase64,container); +``` + ### Byte [] ```csharp @@ -95,6 +191,26 @@ var command = new UploadBytes() var response = await _azureStorageWrapper.UploadBlobAsync(command); ``` +```csharp +//If the DefaultContainer option is set +var bytes = Convert.FromBase64String("SGVsbG8g8J+Zgg=="); + +var file = "hello.md"; +var contentBytes = bytes; + +var response = await _azureStorageWrapper.UploadBlobAsync(file, contentBytes); +``` + +```csharp +var bytes = Convert.FromBase64String("SGVsbG8g8J+Zgg=="); + +var file = "hello.md"; +var contentBytes = bytes; +var container = "files"; + +var response = await _azureStorageWrapper.UploadBlobAsync(file, contentBytes,container); +``` + ### Stream ```csharp @@ -112,6 +228,26 @@ var command = new UploadStream() var response = await _azureStorageWrapper.UploadBlobAsync(command); ``` +```csharp +//If the DefaultContainer option is set +var stream = new MemoryStream(Convert.FromBase64String("SGVsbG8g8J+Zgg==")); + +var file = "hello.md"; +var contentStream = stream; + +var response = await _azureStorageWrapper.UploadBlobAsync(file, contentStream); +``` + +```csharp +var stream = new MemoryStream(Convert.FromBase64String("SGVsbG8g8J+Zgg==")); + +var file = "hello.md"; +var contentStream = stream; +var container = "files"; + +var response = await _azureStorageWrapper.UploadBlobAsync(file, contentStream,container); +``` + ## Response after upload blobs Regardless of the chosen upload mechanism, you will always receive a `BlobReference` object after uploading a file. @@ -184,13 +320,19 @@ To download a blob reference, you need to specify the `Uri`, which you should ha ```csharp var query = new DownloadBlobReference() { - Uri = "https://accountName.blob.core.windows.net/files/5a19306fc5014a4/hello.md" + Uri = "https://accountName.blob.core.windows.net/files/5a19306fc5014a4/hello.md", ExpiresIn = 60, }; var response = await _azureStorageWrapper.DownloadBlobReferenceAsync(query); ``` +```csharp +var uri = "https://accountName.blob.core.windows.net/files/5a19306fc5014a4/hello.md", + +var response = await _azureStorageWrapper.DownloadBlobReferenceAsync(uri); +``` + The response when *downloading* file reference resembles the response when *uploading* files: ```json @@ -220,6 +362,12 @@ var command = new DeleteBlob() await _azureStorageWrapper.DeleteBlobAsync(command); ``` +```csharp +var uri = "https://accountName.blob.core.windows.net/files/5a19306fc5014a4/hello.md" + +await _azureStorageWrapper.DeleteBlobAsync(uri); +``` + ## Enumerate blobs You can list all blobs in a container by using the method `EnumerateBlobsAsync`. @@ -237,7 +385,17 @@ var query = new EnumerateBlobs() Paginate = false }; -var response = await _azureStorageWrapper.EnumerateAllBlobsAsync(query); +var response = await _azureStorageWrapper.EnumerateBlobsAsync(query); +``` + +```csharp +//If the DefaultContainer option is set +var response = await _azureStorageWrapper.EnumerateBlobsAsync(); +``` + +```csharp +var container = "files"; +var response = await _azureStorageWrapper.EnumerateBlobsAsync(container); ``` ### With pagination @@ -246,13 +404,27 @@ var response = await _azureStorageWrapper.EnumerateAllBlobsAsync(query); var query = new EnumerateBlobs() { Container = "files", - Paginate = true. + Paginate = true, Size = 10, }; var response = await _azureStorageWrapper.EnumerateBlobsAsync(query); ``` + +```csharp +//If the DefaultContainer option is set +var size = 10; +var response = await _azureStorageWrapper.EnumerateBlobsAsync(size); + +``` + +```csharp +var size = 10; +var container = "files"; +var response = await _azureStorageWrapper.EnumerateBlobsAsync(size, container); +``` + Then you can request additional pages by using the `ContinuationToken` property in the next request. ```csharp @@ -276,6 +448,24 @@ var secondQuery = new EnumerateBlobs() var secondResponse = await _azureStorageWrapper.EnumerateBlobsAsync(secondQuery); ``` +# Samples + +| Framework | Type | Samples | +| --- | --- | --- | +| NET Core | Console |[Dependency Injections - Minimal Configuration](./samples/dotnetcore/console/DependencyInjections/minimal-configuration/) | +| NET Core | Console | [Dependency Injections - ConnectionString Configuration](./samples/dotnetcore/console/DependencyInjections/connectionstring-configuration/) | +| NET Core | Console | [Dependency Injections - Configuration](./samples/dotnetcore/console/DependencyInjections/configuration/) | +| NET Core | Console | [Without Dependency Injections](./samples/dotnetcore/console/WithoutDependencyInjections/) | +| NET Core | Azure Function |[Dependency Injections - Minimal Configuration](./samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/) | +| NET Core | Azure Function | [Dependency Injections - ConnectionString Configuration](./samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/) | +| NET Core | Azure Function | [Dependency Injections - Configuration](./samples/dotnetcore/az-function/DependencyInjections/configuration/) | +| NET Core | Azure Function | [Without Dependency Injections](./samples/dotnetcore/az-function/WithoutDependencyInjections/) | +| NET FW | Console |[Dependency Injections - Minimal Configuration](./samples/dotnetfw/console/DependencyInjections/minimal-configuration/) | +| NET FW | Console | [Dependency Injections - ConnectionString Configuration](./samples/dotnetfw/console/DependencyInjections/connectionstring-configuration/) | +| NET FW | Console | [Dependency Injections - Configuration](./samples/dotnetfw/console/DependencyInjections/configuration/) | +| NET FW | Console | [Without Dependency Injections](./samples/dotnetfw/console/WithoutDependencyInjections/) | + + # Contributors / Collaborators These individuals have contributed to the repository through suggestions, error corrections, or by opening issues. Thanks 😊 @@ -291,3 +481,4 @@ If you like the project, you can consider making a donation at [ko-fi.com](https # Support You can contact me via Bluesky [@sergiobarriel.bsky.social](https://bsky.app/profile/sergiobarriel.bsky.social) or Twitter [@sergiobarriel](https://twitter.com/sergiobarriel), or if you have an [issue](https://github.com/sergiobarriel/AzureStorageWrapper/issues), you can open one 🙂 + diff --git a/images/icon.png b/res/images/icon.png similarity index 100% rename from images/icon.png rename to res/images/icon.png diff --git a/images/poster.png b/res/images/poster.png similarity index 100% rename from images/poster.png rename to res/images/poster.png diff --git a/samples/build-all-samples.bat b/samples/build-all-samples.bat new file mode 100644 index 0000000..a531330 --- /dev/null +++ b/samples/build-all-samples.bat @@ -0,0 +1,115 @@ +@echo off + +REM Set the error level to 0 +set ERRORLEVEL=0 +REM Get the directory of the script +set SCRIPT_DIR=%~dp0 + +REM .NET CORE +echo BUILD NETCore - Console - WithoutDependencyInjections +dotnet build "%SCRIPT_DIR%dotnetcore\console\WithoutDependencyInjections\samples.sln" +if %ERRORLEVEL% neq 0 ( + echo Application failed! + exit /b %ERRORLEVEL% +) + +echo. +echo BUILD NETCore - Console - DependencyInjections - minimal-configuration +dotnet build "%SCRIPT_DIR%dotnetcore\console\DependencyInjections\minimal-configuration\samples.sln" +if %ERRORLEVEL% neq 0 ( + echo Application failed! + exit /b %ERRORLEVEL% +) + +echo. +echo BUILD NETCore - Console - DependencyInjections - connectionstring-configuration +dotnet build "%SCRIPT_DIR%dotnetcore\console\DependencyInjections\connectionstring-configuration\samples.sln" +if %ERRORLEVEL% neq 0 ( + echo Application failed! + exit /b %ERRORLEVEL% +) + +echo. +echo BUILD NETCore - Console - DependencyInjections - configuration +dotnet build "%SCRIPT_DIR%dotnetcore\console\DependencyInjections\configuration\samples.sln" +if %ERRORLEVEL% neq 0 ( + echo Application failed! + exit /b %ERRORLEVEL% +) + +echo. +echo. +echo. +echo BUILD NETCore - AZ Function - WithoutDependencyInjections +dotnet build "%SCRIPT_DIR%dotnetcore\az-function\WithoutDependencyInjections\samples.sln" +if %ERRORLEVEL% neq 0 ( + echo Application failed! + exit /b %ERRORLEVEL% +) + +echo. +echo BUILD NETCore - AZ Function - DependencyInjections - minimal-configuration +dotnet build "%SCRIPT_DIR%dotnetcore\az-function\DependencyInjections\minimal-configuration\samples.sln" +if %ERRORLEVEL% neq 0 ( + echo Application failed! + exit /b %ERRORLEVEL% +) + +echo. +echo BUILD NETCore - AZ Function - DependencyInjections - connectionstring-configuration +dotnet build "%SCRIPT_DIR%dotnetcore\az-function\DependencyInjections\connectionstring-configuration\samples.sln" +if %ERRORLEVEL% neq 0 ( + echo Application failed! + exit /b %ERRORLEVEL% +) + +echo. +echo BUILD NETCore - AZ Function - DependencyInjections - configuration +dotnet build "%SCRIPT_DIR%dotnetcore\az-function\DependencyInjections\configuration\samples.sln" +if %ERRORLEVEL% neq 0 ( + echo Application failed! + exit /b %ERRORLEVEL% +) + + +REM .NET FRAMEWORK +echo. +echo. +echo. +echo BUILD NET FW - Console - WithoutDependencyInjections +dotnet build "%SCRIPT_DIR%dotnetfw\console\WithoutDependencyInjections\samples.sln" +if %ERRORLEVEL% neq 0 ( + echo Application failed! + exit /b %ERRORLEVEL% +) + +echo. +echo BUILD NET FW - Console - DependencyInjections - minimal-configuration +dotnet build "%SCRIPT_DIR%dotnetfw\console\DependencyInjections\minimal-configuration\samples.sln" +if %ERRORLEVEL% neq 0 ( + echo Application failed! + exit /b %ERRORLEVEL% +) + +echo. +echo BUILD NET FW - Console - DependencyInjections - connectionstring-configuration +dotnet build "%SCRIPT_DIR%dotnetfw\console\DependencyInjections\connectionstring-configuration\samples.sln" +if %ERRORLEVEL% neq 0 ( + echo Application failed! + exit /b %ERRORLEVEL% +) + +echo. +echo BUILD NET FW - Console - DependencyInjections - configuration +dotnet build "%SCRIPT_DIR%dotnetfw\console\DependencyInjections\configuration\samples.sln" +if %ERRORLEVEL% neq 0 ( + echo Application failed! + exit /b %ERRORLEVEL% +) + + +REM If all projects ran successfully +echo All projects ran successfully! +pause +exit /b 0 + diff --git a/samples/dotnetcore/az-function/DependencyInjections/configuration/.gitignore b/samples/dotnetcore/az-function/DependencyInjections/configuration/.gitignore new file mode 100644 index 0000000..ff5b00c --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/configuration/.gitignore @@ -0,0 +1,264 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# Azure Functions localsettings file +local.settings.json + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +#*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc \ No newline at end of file diff --git a/samples/dotnetcore/az-function/DependencyInjections/configuration/Function1.cs b/samples/dotnetcore/az-function/DependencyInjections/configuration/Function1.cs new file mode 100644 index 0000000..f7f4106 --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/configuration/Function1.cs @@ -0,0 +1,26 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Extensions.Logging; + +namespace samples +{ + public class Function1 + { + private readonly ILogger _logger; + private readonly Samples_All _samplesAll; + public Function1(ILogger logger, Samples_All samplesAll) + { + _logger = logger; + _samplesAll = samplesAll; + } + + [Function("Function1")] + public async Task Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req) + { + await _samplesAll.RunAsync(); + return new OkObjectResult("FIN"); + } + } +} diff --git a/samples/dotnetcore/az-function/DependencyInjections/configuration/Program.cs b/samples/dotnetcore/az-function/DependencyInjections/configuration/Program.cs new file mode 100644 index 0000000..3679fd1 --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/configuration/Program.cs @@ -0,0 +1,21 @@ +using Microsoft.Azure.Functions.Worker.Builder; +using Microsoft.Extensions.Hosting; +using AzureStorageWrapper; +using samples; + +var builder = FunctionsApplication.CreateBuilder(args) + .ConfigureFunctionsWebApplication(); +builder.Services.AddExample_All();//Configuration Example_All + +var connectionString = builder.Configuration["AzureStorageWrapper_ConnectionString"]; +var defaultContainer = builder.Configuration["StorageWrapper_DefaultContainer"]; +builder.Services.AddAzureStorageWrapper(options => +{ + options.ConnectionString = connectionString; + options.MaxSasUriExpiration = 600; + options.DefaultSasUriExpiration = 300; + options.CreateContainerIfNotExists = true; + //options.DefaultContainer= defaultContainer; // The default container used for all storage operations if not specified explicitly. It is optional +});//Configuration AzureStorageWrapper + +builder.Build().Run(); diff --git a/samples/dotnetcore/az-function/DependencyInjections/configuration/Properties/launchSettings.json b/samples/dotnetcore/az-function/DependencyInjections/configuration/Properties/launchSettings.json new file mode 100644 index 0000000..996be21 --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/configuration/Properties/launchSettings.json @@ -0,0 +1,9 @@ +{ + "profiles": { + "samples": { + "commandName": "Project", + "commandLineArgs": "--port 7276", + "launchBrowser": false + } + } +} \ No newline at end of file diff --git a/samples/dotnetcore/az-function/DependencyInjections/configuration/Properties/serviceDependencies.json b/samples/dotnetcore/az-function/DependencyInjections/configuration/Properties/serviceDependencies.json new file mode 100644 index 0000000..df4dcc9 --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/configuration/Properties/serviceDependencies.json @@ -0,0 +1,11 @@ +{ + "dependencies": { + "appInsights1": { + "type": "appInsights" + }, + "storage1": { + "type": "storage", + "connectionId": "AzureWebJobsStorage" + } + } +} \ No newline at end of file diff --git a/samples/dotnetcore/az-function/DependencyInjections/configuration/Properties/serviceDependencies.local.json b/samples/dotnetcore/az-function/DependencyInjections/configuration/Properties/serviceDependencies.local.json new file mode 100644 index 0000000..b804a28 --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/configuration/Properties/serviceDependencies.local.json @@ -0,0 +1,11 @@ +{ + "dependencies": { + "appInsights1": { + "type": "appInsights.sdk" + }, + "storage1": { + "type": "storage.emulator", + "connectionId": "AzureWebJobsStorage" + } + } +} \ No newline at end of file diff --git a/samples/dotnetcore/az-function/DependencyInjections/configuration/host.json b/samples/dotnetcore/az-function/DependencyInjections/configuration/host.json new file mode 100644 index 0000000..ee5cf5f --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/configuration/host.json @@ -0,0 +1,12 @@ +{ + "version": "2.0", + "logging": { + "applicationInsights": { + "samplingSettings": { + "isEnabled": true, + "excludedTypes": "Request" + }, + "enableLiveMetricsFilters": true + } + } +} \ No newline at end of file diff --git a/samples/dotnetcore/az-function/DependencyInjections/configuration/samples.csproj b/samples/dotnetcore/az-function/DependencyInjections/configuration/samples.csproj new file mode 100644 index 0000000..e3231af --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/configuration/samples.csproj @@ -0,0 +1,44 @@ + + + net9.0 + v4 + Exe + enable + enable + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + Never + + + + + + \ No newline at end of file diff --git a/samples/dotnetcore/az-function/DependencyInjections/configuration/samples.sln b/samples/dotnetcore/az-function/DependencyInjections/configuration/samples.sln new file mode 100644 index 0000000..ef958c8 --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/configuration/samples.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35825.156 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "samples", "samples.csproj", "{E4872347-A244-1216-9685-2A128BFF7897}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureStorageWrapper", "..\..\..\..\..\src\AzureStorageWrapper\AzureStorageWrapper.csproj", "{EA9579CA-1424-4E11-53E8-3B6515FF217F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E4872347-A244-1216-9685-2A128BFF7897}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Release|Any CPU.Build.0 = Release|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E12D5190-C961-4C03-82B0-F8EF22646C23} + EndGlobalSection +EndGlobal diff --git a/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/.gitignore b/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/.gitignore new file mode 100644 index 0000000..ff5b00c --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/.gitignore @@ -0,0 +1,264 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# Azure Functions localsettings file +local.settings.json + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +#*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc \ No newline at end of file diff --git a/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/Function1.cs b/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/Function1.cs new file mode 100644 index 0000000..f7f4106 --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/Function1.cs @@ -0,0 +1,26 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Extensions.Logging; + +namespace samples +{ + public class Function1 + { + private readonly ILogger _logger; + private readonly Samples_All _samplesAll; + public Function1(ILogger logger, Samples_All samplesAll) + { + _logger = logger; + _samplesAll = samplesAll; + } + + [Function("Function1")] + public async Task Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req) + { + await _samplesAll.RunAsync(); + return new OkObjectResult("FIN"); + } + } +} diff --git a/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/Program.cs b/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/Program.cs new file mode 100644 index 0000000..fc6e920 --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/Program.cs @@ -0,0 +1,18 @@ +using Microsoft.Azure.Functions.Worker.Builder; +using Microsoft.Extensions.Hosting; +using AzureStorageWrapper; +using samples; + +var builder = FunctionsApplication.CreateBuilder(args) + .ConfigureFunctionsWebApplication(); +builder.Services.AddExample_All();//Configuration Example_All + +var configurationString = builder.Configuration["AzureStorageWrapper_ConnectionString"]; +builder.Services.AddAzureStorageWrapper(configurationString);//Configuration AzureStorageWrapper + +// The default container used for all storage operations if not specified explicitly. It is optional +//var defaultContainer = builder.Configuration["StorageWrapper_DefaultContainer"]; +//builder.Services.AddAzureStorageWrapper(configurationString, defaultContainer);//Configuration AzureStorageWrapper + + +builder.Build().Run(); diff --git a/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/Properties/launchSettings.json b/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/Properties/launchSettings.json new file mode 100644 index 0000000..996be21 --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/Properties/launchSettings.json @@ -0,0 +1,9 @@ +{ + "profiles": { + "samples": { + "commandName": "Project", + "commandLineArgs": "--port 7276", + "launchBrowser": false + } + } +} \ No newline at end of file diff --git a/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/Properties/serviceDependencies.json b/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/Properties/serviceDependencies.json new file mode 100644 index 0000000..df4dcc9 --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/Properties/serviceDependencies.json @@ -0,0 +1,11 @@ +{ + "dependencies": { + "appInsights1": { + "type": "appInsights" + }, + "storage1": { + "type": "storage", + "connectionId": "AzureWebJobsStorage" + } + } +} \ No newline at end of file diff --git a/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/Properties/serviceDependencies.local.json b/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/Properties/serviceDependencies.local.json new file mode 100644 index 0000000..b804a28 --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/Properties/serviceDependencies.local.json @@ -0,0 +1,11 @@ +{ + "dependencies": { + "appInsights1": { + "type": "appInsights.sdk" + }, + "storage1": { + "type": "storage.emulator", + "connectionId": "AzureWebJobsStorage" + } + } +} \ No newline at end of file diff --git a/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/host.json b/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/host.json new file mode 100644 index 0000000..ee5cf5f --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/host.json @@ -0,0 +1,12 @@ +{ + "version": "2.0", + "logging": { + "applicationInsights": { + "samplingSettings": { + "isEnabled": true, + "excludedTypes": "Request" + }, + "enableLiveMetricsFilters": true + } + } +} \ No newline at end of file diff --git a/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/samples.csproj b/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/samples.csproj new file mode 100644 index 0000000..e3231af --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/samples.csproj @@ -0,0 +1,44 @@ + + + net9.0 + v4 + Exe + enable + enable + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + Never + + + + + + \ No newline at end of file diff --git a/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/samples.sln b/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/samples.sln new file mode 100644 index 0000000..ef958c8 --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/connectionstring-configuration/samples.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35825.156 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "samples", "samples.csproj", "{E4872347-A244-1216-9685-2A128BFF7897}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureStorageWrapper", "..\..\..\..\..\src\AzureStorageWrapper\AzureStorageWrapper.csproj", "{EA9579CA-1424-4E11-53E8-3B6515FF217F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E4872347-A244-1216-9685-2A128BFF7897}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Release|Any CPU.Build.0 = Release|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E12D5190-C961-4C03-82B0-F8EF22646C23} + EndGlobalSection +EndGlobal diff --git a/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/.gitignore b/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/.gitignore new file mode 100644 index 0000000..ff5b00c --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/.gitignore @@ -0,0 +1,264 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# Azure Functions localsettings file +local.settings.json + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +#*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc \ No newline at end of file diff --git a/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/Function1.cs b/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/Function1.cs new file mode 100644 index 0000000..f7f4106 --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/Function1.cs @@ -0,0 +1,26 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Extensions.Logging; + +namespace samples +{ + public class Function1 + { + private readonly ILogger _logger; + private readonly Samples_All _samplesAll; + public Function1(ILogger logger, Samples_All samplesAll) + { + _logger = logger; + _samplesAll = samplesAll; + } + + [Function("Function1")] + public async Task Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req) + { + await _samplesAll.RunAsync(); + return new OkObjectResult("FIN"); + } + } +} diff --git a/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/Program.cs b/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/Program.cs new file mode 100644 index 0000000..8fe544e --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/Program.cs @@ -0,0 +1,12 @@ +using Microsoft.Azure.Functions.Worker.Builder; +using Microsoft.Extensions.Hosting; +using AzureStorageWrapper; +using samples; + +var builder = FunctionsApplication.CreateBuilder(args) + .ConfigureFunctionsWebApplication(); +builder.Services.AddExample_All();//Configuration Example_All + +builder.Services.AddAzureStorageWrapper();//Configuration AzureStorageWrapper + +builder.Build().Run(); diff --git a/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/Properties/launchSettings.json b/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/Properties/launchSettings.json new file mode 100644 index 0000000..996be21 --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/Properties/launchSettings.json @@ -0,0 +1,9 @@ +{ + "profiles": { + "samples": { + "commandName": "Project", + "commandLineArgs": "--port 7276", + "launchBrowser": false + } + } +} \ No newline at end of file diff --git a/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/Properties/serviceDependencies.json b/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/Properties/serviceDependencies.json new file mode 100644 index 0000000..df4dcc9 --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/Properties/serviceDependencies.json @@ -0,0 +1,11 @@ +{ + "dependencies": { + "appInsights1": { + "type": "appInsights" + }, + "storage1": { + "type": "storage", + "connectionId": "AzureWebJobsStorage" + } + } +} \ No newline at end of file diff --git a/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/Properties/serviceDependencies.local.json b/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/Properties/serviceDependencies.local.json new file mode 100644 index 0000000..b804a28 --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/Properties/serviceDependencies.local.json @@ -0,0 +1,11 @@ +{ + "dependencies": { + "appInsights1": { + "type": "appInsights.sdk" + }, + "storage1": { + "type": "storage.emulator", + "connectionId": "AzureWebJobsStorage" + } + } +} \ No newline at end of file diff --git a/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/host.json b/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/host.json new file mode 100644 index 0000000..ee5cf5f --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/host.json @@ -0,0 +1,12 @@ +{ + "version": "2.0", + "logging": { + "applicationInsights": { + "samplingSettings": { + "isEnabled": true, + "excludedTypes": "Request" + }, + "enableLiveMetricsFilters": true + } + } +} \ No newline at end of file diff --git a/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/samples.csproj b/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/samples.csproj new file mode 100644 index 0000000..e3231af --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/samples.csproj @@ -0,0 +1,44 @@ + + + net9.0 + v4 + Exe + enable + enable + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + Never + + + + + + \ No newline at end of file diff --git a/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/samples.sln b/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/samples.sln new file mode 100644 index 0000000..ef958c8 --- /dev/null +++ b/samples/dotnetcore/az-function/DependencyInjections/minimal-configuration/samples.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35825.156 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "samples", "samples.csproj", "{E4872347-A244-1216-9685-2A128BFF7897}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureStorageWrapper", "..\..\..\..\..\src\AzureStorageWrapper\AzureStorageWrapper.csproj", "{EA9579CA-1424-4E11-53E8-3B6515FF217F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E4872347-A244-1216-9685-2A128BFF7897}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Release|Any CPU.Build.0 = Release|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E12D5190-C961-4C03-82B0-F8EF22646C23} + EndGlobalSection +EndGlobal diff --git a/samples/dotnetcore/az-function/WithoutDependencyInjections/.gitignore b/samples/dotnetcore/az-function/WithoutDependencyInjections/.gitignore new file mode 100644 index 0000000..ff5b00c --- /dev/null +++ b/samples/dotnetcore/az-function/WithoutDependencyInjections/.gitignore @@ -0,0 +1,264 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# Azure Functions localsettings file +local.settings.json + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +#*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc \ No newline at end of file diff --git a/samples/dotnetcore/az-function/WithoutDependencyInjections/Function1.cs b/samples/dotnetcore/az-function/WithoutDependencyInjections/Function1.cs new file mode 100644 index 0000000..6b29138 --- /dev/null +++ b/samples/dotnetcore/az-function/WithoutDependencyInjections/Function1.cs @@ -0,0 +1,53 @@ +using AzureStorageWrapper.Commands; +using AzureStorageWrapper; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Extensions.Logging; +using samples.Helpers; + +namespace samples +{ + public class Function1 + { + private readonly ILogger _logger; + public Function1(ILogger logger) + { + _logger = logger; + } + + [Function("Function1")] + public async Task Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req) + { + var options = new AzureStorageWrapperOptions + { + ConnectionString = "UseDevelopmentStorage=true", + MaxSasUriExpiration = 600, + DefaultSasUriExpiration = 300, + CreateContainerIfNotExists = true, + }; + var azureStorageWrapper = new AzureStorageWrapper.AzureStorageWrapper(options); + + + #region Upload Blobs In Bytes + ConsoleHelper.Start("Upload in Bytes"); + var bytes = Convert.FromBase64String("SGVsbG8g8J+Zgg=="); + + var command = new UploadBytes() + { + Bytes = bytes, + Container = "files", + Name = "hello", + Extension = "md", + Metadata = new Dictionary() { { "key", "value" } } + }; + + var response = await azureStorageWrapper.UploadBlobAsync(command); + ConsoleHelper.Result(response); + ConsoleHelper.Finalized("Upload in Base64"); + #endregion + + return new OkObjectResult("FIN"); + } + } +} diff --git a/samples/dotnetcore/az-function/WithoutDependencyInjections/Program.cs b/samples/dotnetcore/az-function/WithoutDependencyInjections/Program.cs new file mode 100644 index 0000000..2ef5201 --- /dev/null +++ b/samples/dotnetcore/az-function/WithoutDependencyInjections/Program.cs @@ -0,0 +1,9 @@ +using Microsoft.Azure.Functions.Worker.Builder; +using Microsoft.Extensions.Hosting; +using AzureStorageWrapper; +using samples; + +var builder = FunctionsApplication.CreateBuilder(args) + .ConfigureFunctionsWebApplication(); + +builder.Build().Run(); diff --git a/samples/dotnetcore/az-function/WithoutDependencyInjections/Properties/launchSettings.json b/samples/dotnetcore/az-function/WithoutDependencyInjections/Properties/launchSettings.json new file mode 100644 index 0000000..996be21 --- /dev/null +++ b/samples/dotnetcore/az-function/WithoutDependencyInjections/Properties/launchSettings.json @@ -0,0 +1,9 @@ +{ + "profiles": { + "samples": { + "commandName": "Project", + "commandLineArgs": "--port 7276", + "launchBrowser": false + } + } +} \ No newline at end of file diff --git a/samples/dotnetcore/az-function/WithoutDependencyInjections/Properties/serviceDependencies.json b/samples/dotnetcore/az-function/WithoutDependencyInjections/Properties/serviceDependencies.json new file mode 100644 index 0000000..df4dcc9 --- /dev/null +++ b/samples/dotnetcore/az-function/WithoutDependencyInjections/Properties/serviceDependencies.json @@ -0,0 +1,11 @@ +{ + "dependencies": { + "appInsights1": { + "type": "appInsights" + }, + "storage1": { + "type": "storage", + "connectionId": "AzureWebJobsStorage" + } + } +} \ No newline at end of file diff --git a/samples/dotnetcore/az-function/WithoutDependencyInjections/Properties/serviceDependencies.local.json b/samples/dotnetcore/az-function/WithoutDependencyInjections/Properties/serviceDependencies.local.json new file mode 100644 index 0000000..b804a28 --- /dev/null +++ b/samples/dotnetcore/az-function/WithoutDependencyInjections/Properties/serviceDependencies.local.json @@ -0,0 +1,11 @@ +{ + "dependencies": { + "appInsights1": { + "type": "appInsights.sdk" + }, + "storage1": { + "type": "storage.emulator", + "connectionId": "AzureWebJobsStorage" + } + } +} \ No newline at end of file diff --git a/samples/dotnetcore/az-function/WithoutDependencyInjections/host.json b/samples/dotnetcore/az-function/WithoutDependencyInjections/host.json new file mode 100644 index 0000000..ee5cf5f --- /dev/null +++ b/samples/dotnetcore/az-function/WithoutDependencyInjections/host.json @@ -0,0 +1,12 @@ +{ + "version": "2.0", + "logging": { + "applicationInsights": { + "samplingSettings": { + "isEnabled": true, + "excludedTypes": "Request" + }, + "enableLiveMetricsFilters": true + } + } +} \ No newline at end of file diff --git a/samples/dotnetcore/az-function/WithoutDependencyInjections/samples.csproj b/samples/dotnetcore/az-function/WithoutDependencyInjections/samples.csproj new file mode 100644 index 0000000..8928aae --- /dev/null +++ b/samples/dotnetcore/az-function/WithoutDependencyInjections/samples.csproj @@ -0,0 +1,38 @@ + + + net9.0 + v4 + Exe + enable + enable + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + Never + + + + + + \ No newline at end of file diff --git a/samples/dotnetcore/az-function/WithoutDependencyInjections/samples.sln b/samples/dotnetcore/az-function/WithoutDependencyInjections/samples.sln new file mode 100644 index 0000000..6fa460a --- /dev/null +++ b/samples/dotnetcore/az-function/WithoutDependencyInjections/samples.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35825.156 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "samples", "samples.csproj", "{E4872347-A244-1216-9685-2A128BFF7897}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureStorageWrapper", "..\..\..\..\src\AzureStorageWrapper\AzureStorageWrapper.csproj", "{B73B6239-54A0-7B08-257C-59BFD8269DD3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E4872347-A244-1216-9685-2A128BFF7897}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Release|Any CPU.Build.0 = Release|Any CPU + {B73B6239-54A0-7B08-257C-59BFD8269DD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B73B6239-54A0-7B08-257C-59BFD8269DD3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B73B6239-54A0-7B08-257C-59BFD8269DD3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B73B6239-54A0-7B08-257C-59BFD8269DD3}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E12D5190-C961-4C03-82B0-F8EF22646C23} + EndGlobalSection +EndGlobal diff --git a/samples/dotnetcore/console/DependencyInjections/configuration/Program.cs b/samples/dotnetcore/console/DependencyInjections/configuration/Program.cs new file mode 100644 index 0000000..3a42d6d --- /dev/null +++ b/samples/dotnetcore/console/DependencyInjections/configuration/Program.cs @@ -0,0 +1,37 @@ +using AzureStorageWrapper; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using samples; + + +AzuriteHelper.Start();// Starts the Azurite process by executing the run-azurite.bat file + +var host = Host.CreateDefaultBuilder(args) + .ConfigureAppConfiguration((context, config) => + { + config.AddJsonFile("app.settings.json", optional: false, reloadOnChange: true);// Add app.settings.json to the configuration + + }) + .ConfigureServices((context, services) => { + var connectionString = context.Configuration["StorageWrapper_ConnectionString"];// Set the StorageWrapper_ConnectionString string in the environment variables + services.AddAzureStorageWrapper(options => + { + options.ConnectionString = connectionString; + options.MaxSasUriExpiration = 600; + options.DefaultSasUriExpiration = 300; + options.CreateContainerIfNotExists = true; + //options.DefaultContainer = "files"; // The default container used for all storage operations if not specified explicitly. It is optional + });//Configuration AzureStorageWrapper + + services.AddExample_All();//Configuration Example_All + + }) + .Build(); + +var example_All = host.Services.GetService(); +await example_All.RunAsync();// Run the example_All service + +Console.WriteLine("Press any key to exit"); +Console.ReadKey(); + diff --git a/samples/dotnetcore/console/DependencyInjections/configuration/app.settings.json b/samples/dotnetcore/console/DependencyInjections/configuration/app.settings.json new file mode 100644 index 0000000..698d878 --- /dev/null +++ b/samples/dotnetcore/console/DependencyInjections/configuration/app.settings.json @@ -0,0 +1,3 @@ +{ + "StorageWrapper_ConnectionString": "UseDevelopmentStorage=true" +} diff --git a/samples/dotnetcore/console/DependencyInjections/configuration/samples.csproj b/samples/dotnetcore/console/DependencyInjections/configuration/samples.csproj new file mode 100644 index 0000000..869d4d2 --- /dev/null +++ b/samples/dotnetcore/console/DependencyInjections/configuration/samples.csproj @@ -0,0 +1,45 @@ + + + + Exe + net9.0 + enable + enable + + + + + + + + + + + + + + + + + + + + Always + + + + + + + + + + + + + + + Always + + + diff --git a/samples/dotnetcore/console/DependencyInjections/configuration/samples.sln b/samples/dotnetcore/console/DependencyInjections/configuration/samples.sln new file mode 100644 index 0000000..e7b8f2a --- /dev/null +++ b/samples/dotnetcore/console/DependencyInjections/configuration/samples.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35825.156 d17.13 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "samples", "samples.csproj", "{E4872347-A244-1216-9685-2A128BFF7897}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureStorageWrapper", "..\..\..\..\..\src\AzureStorageWrapper\AzureStorageWrapper.csproj", "{EA9579CA-1424-4E11-53E8-3B6515FF217F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E4872347-A244-1216-9685-2A128BFF7897}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Release|Any CPU.Build.0 = Release|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E535FAFC-112D-4859-B672-97650BE5D995} + EndGlobalSection +EndGlobal diff --git a/samples/dotnetcore/console/DependencyInjections/connectionstring-configuration/Program.cs b/samples/dotnetcore/console/DependencyInjections/connectionstring-configuration/Program.cs new file mode 100644 index 0000000..6e89e1e --- /dev/null +++ b/samples/dotnetcore/console/DependencyInjections/connectionstring-configuration/Program.cs @@ -0,0 +1,34 @@ +using AzureStorageWrapper; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using samples; + + +AzuriteHelper.Start();// Starts the Azurite process by executing the run-azurite.bat file + +var host = Host.CreateDefaultBuilder(args) + .ConfigureAppConfiguration((context, config) => + { + config.AddJsonFile("app.settings.json", optional: false, reloadOnChange: true);// Add app.settings.json to the configuration + + }) + .ConfigureServices((context, services) => { + var connectionString = context.Configuration["StorageWrapper_ConnectionString"];// Get the StorageWrapper_ConnectionString string from the configuration + services.AddAzureStorageWrapper(connectionString);//Configuration AzureStorageWrapper + + // The default container used for all storage operations if not specified explicitly. It is optional + //var defaultContainer = context.Configuration["StorageWrapper_DefaultContainer"]; + //services.AddAzureStorageWrapper(connectionString, defaultContainer);//Configuration AzureStorageWrapper + + services.AddExample_All();//Configuration Example_All + + }) + .Build(); + +var example_All = host.Services.GetService(); +await example_All.RunAsync();// Run the example_All service + +Console.WriteLine("Press any key to exit"); +Console.ReadKey(); + diff --git a/samples/dotnetcore/console/DependencyInjections/connectionstring-configuration/app.settings.json b/samples/dotnetcore/console/DependencyInjections/connectionstring-configuration/app.settings.json new file mode 100644 index 0000000..d30ab34 --- /dev/null +++ b/samples/dotnetcore/console/DependencyInjections/connectionstring-configuration/app.settings.json @@ -0,0 +1,4 @@ +{ + "StorageWrapper_ConnectionString": "UseDevelopmentStorage=true", + "StorageWrapper_DefaultContainer": "files" // The default container used for all storage operations if not specified explicitly. It is optional +} diff --git a/samples/dotnetcore/console/DependencyInjections/connectionstring-configuration/samples.csproj b/samples/dotnetcore/console/DependencyInjections/connectionstring-configuration/samples.csproj new file mode 100644 index 0000000..869d4d2 --- /dev/null +++ b/samples/dotnetcore/console/DependencyInjections/connectionstring-configuration/samples.csproj @@ -0,0 +1,45 @@ + + + + Exe + net9.0 + enable + enable + + + + + + + + + + + + + + + + + + + + Always + + + + + + + + + + + + + + + Always + + + diff --git a/samples/dotnetcore/console/DependencyInjections/connectionstring-configuration/samples.sln b/samples/dotnetcore/console/DependencyInjections/connectionstring-configuration/samples.sln new file mode 100644 index 0000000..2ec5072 --- /dev/null +++ b/samples/dotnetcore/console/DependencyInjections/connectionstring-configuration/samples.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35825.156 d17.13 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "samples", "samples.csproj", "{E4872347-A244-1216-9685-2A128BFF7897}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureStorageWrapper", "..\..\..\..\..\src\AzureStorageWrapper\AzureStorageWrapper.csproj", "{EA9579CA-1424-4E11-53E8-3B6515FF217F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E4872347-A244-1216-9685-2A128BFF7897}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Release|Any CPU.Build.0 = Release|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D8263C58-8E2F-4657-9352-C360ABC107CC} + EndGlobalSection +EndGlobal diff --git a/samples/dotnetcore/console/DependencyInjections/minimal-configuration/Program.cs b/samples/dotnetcore/console/DependencyInjections/minimal-configuration/Program.cs new file mode 100644 index 0000000..3a8abca --- /dev/null +++ b/samples/dotnetcore/console/DependencyInjections/minimal-configuration/Program.cs @@ -0,0 +1,32 @@ +using AzureStorageWrapper; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using samples; + + +AzuriteHelper.Start();// Starts the Azurite process by executing the run-azurite.bat file + +var host = Host.CreateDefaultBuilder(args) + .ConfigureAppConfiguration((context, config) => + { + config.AddJsonFile("app.settings.json", optional: false, reloadOnChange: true);// Add app.settings.json to the configuration + + }) + .ConfigureServices((context, services) => { + Environment.SetEnvironmentVariable("StorageWrapper_ConnectionString", context.Configuration["StorageWrapper_ConnectionString"]);// Set the StorageWrapper_ConnectionString string in the environment variables + // The default container used for all storage operations if not specified explicitly. It is optional + Environment.SetEnvironmentVariable("StorageWrapper_DefaultContainer", context.Configuration["StorageWrapper_DefaultContainer"]); + services.AddAzureStorageWrapper();//Configuration AzureStorageWrapper + + services.AddExample_All();//Configuration Example_All + + }) + .Build(); + +var example_All = host.Services.GetService(); +await example_All.RunAsync();// Run the example_All service + +Console.WriteLine("Press any key to exit"); +Console.ReadKey(); + diff --git a/samples/dotnetcore/console/DependencyInjections/minimal-configuration/app.settings.json b/samples/dotnetcore/console/DependencyInjections/minimal-configuration/app.settings.json new file mode 100644 index 0000000..d30ab34 --- /dev/null +++ b/samples/dotnetcore/console/DependencyInjections/minimal-configuration/app.settings.json @@ -0,0 +1,4 @@ +{ + "StorageWrapper_ConnectionString": "UseDevelopmentStorage=true", + "StorageWrapper_DefaultContainer": "files" // The default container used for all storage operations if not specified explicitly. It is optional +} diff --git a/samples/dotnetcore/console/DependencyInjections/minimal-configuration/samples.csproj b/samples/dotnetcore/console/DependencyInjections/minimal-configuration/samples.csproj new file mode 100644 index 0000000..869d4d2 --- /dev/null +++ b/samples/dotnetcore/console/DependencyInjections/minimal-configuration/samples.csproj @@ -0,0 +1,45 @@ + + + + Exe + net9.0 + enable + enable + + + + + + + + + + + + + + + + + + + + Always + + + + + + + + + + + + + + + Always + + + diff --git a/samples/dotnetcore/console/DependencyInjections/minimal-configuration/samples.sln b/samples/dotnetcore/console/DependencyInjections/minimal-configuration/samples.sln new file mode 100644 index 0000000..84fc3d3 --- /dev/null +++ b/samples/dotnetcore/console/DependencyInjections/minimal-configuration/samples.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35825.156 d17.13 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "samples", "samples.csproj", "{E4872347-A244-1216-9685-2A128BFF7897}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureStorageWrapper", "..\..\..\..\..\src\AzureStorageWrapper\AzureStorageWrapper.csproj", "{EA9579CA-1424-4E11-53E8-3B6515FF217F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E4872347-A244-1216-9685-2A128BFF7897}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Release|Any CPU.Build.0 = Release|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {502EAC3D-7E74-4B8E-90A4-E84AEBD28312} + EndGlobalSection +EndGlobal diff --git a/samples/dotnetcore/console/WithoutDependencyInjections/Program.cs b/samples/dotnetcore/console/WithoutDependencyInjections/Program.cs new file mode 100644 index 0000000..42dc525 --- /dev/null +++ b/samples/dotnetcore/console/WithoutDependencyInjections/Program.cs @@ -0,0 +1,43 @@ +using Microsoft.Extensions.Hosting; +using AzureStorageWrapper; +using samples; +using AzureStorageWrapper.Commands; +using samples.Helpers; + +AzuriteHelper.Start();// Starts the Azurite process by executing the run-azurite.bat file + +var host = Host.CreateDefaultBuilder(args) + .Build(); + +var options = new AzureStorageWrapperOptions +{ + ConnectionString = "UseDevelopmentStorage=true", + MaxSasUriExpiration=600, + DefaultSasUriExpiration = 300, + CreateContainerIfNotExists = true, + //DefaultContainer = "files" // The default container used for all storage operations if not specified explicitly. It is optional +}; +var azureStorageWrapper = new AzureStorageWrapper.AzureStorageWrapper(options); + + +#region Upload Blobs In Bytes +ConsoleHelper.Start("Upload in Bytes"); +var bytes = Convert.FromBase64String("SGVsbG8g8J+Zgg=="); + +var command = new UploadBytes() +{ + Bytes = bytes, + Container = "files", + Name = "hello", + Extension = "md", + Metadata = new Dictionary() { { "key", "value" } } +}; + +var response = await azureStorageWrapper.UploadBlobAsync(command); +ConsoleHelper.Result(response); +ConsoleHelper.Finalized("Upload in Base64"); +#endregion + +Console.WriteLine("Press any key to exit"); +Console.ReadKey(); + diff --git a/samples/dotnetcore/console/WithoutDependencyInjections/samples.csproj b/samples/dotnetcore/console/WithoutDependencyInjections/samples.csproj new file mode 100644 index 0000000..6454214 --- /dev/null +++ b/samples/dotnetcore/console/WithoutDependencyInjections/samples.csproj @@ -0,0 +1,33 @@ + + + + Exe + net9.0 + enable + enable + + + + + + + + + + + + + + Always + + + + + + + + + + + + diff --git a/samples/dotnetcore/console/WithoutDependencyInjections/samples.sln b/samples/dotnetcore/console/WithoutDependencyInjections/samples.sln new file mode 100644 index 0000000..7bf7d40 --- /dev/null +++ b/samples/dotnetcore/console/WithoutDependencyInjections/samples.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35825.156 d17.13 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "samples", "samples.csproj", "{E4872347-A244-1216-9685-2A128BFF7897}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureStorageWrapper", "..\..\..\..\src\AzureStorageWrapper\AzureStorageWrapper.csproj", "{B73B6239-54A0-7B08-257C-59BFD8269DD3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E4872347-A244-1216-9685-2A128BFF7897}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E4872347-A244-1216-9685-2A128BFF7897}.Release|Any CPU.Build.0 = Release|Any CPU + {B73B6239-54A0-7B08-257C-59BFD8269DD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B73B6239-54A0-7B08-257C-59BFD8269DD3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B73B6239-54A0-7B08-257C-59BFD8269DD3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B73B6239-54A0-7B08-257C-59BFD8269DD3}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C0D22797-57A6-4A81-9FA8-B29742B8D3BB} + EndGlobalSection +EndGlobal diff --git a/samples/dotnetfw/console/DependencyInjections/configuration/App.config b/samples/dotnetfw/console/DependencyInjections/configuration/App.config new file mode 100644 index 0000000..865b315 --- /dev/null +++ b/samples/dotnetfw/console/DependencyInjections/configuration/App.config @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/dotnetfw/console/DependencyInjections/configuration/Program.cs b/samples/dotnetfw/console/DependencyInjections/configuration/Program.cs new file mode 100644 index 0000000..8f74ce8 --- /dev/null +++ b/samples/dotnetfw/console/DependencyInjections/configuration/Program.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Specialized; +using System.Configuration; +using System.Threading.Tasks; +using AzureStorageWrapper; +using Microsoft.Extensions.DependencyInjection; + +namespace samples +{ + class Program + { + static async Task Main(string[] args) + { + AzuriteHelper.Start();// Starts the Azurite process by executing the run-azurite.bat file + var serviceProvider = ConfigureServices((configuration, services) => + { + var connectionString = configuration["StorageWrapper_ConnectionString"];// Set the StorageWrapper_ConnectionString string in the environment variables + var defaultContainer = configuration["StorageWrapper_DefaultContainer"];// Set the StorageWrapper_ConnectionString string in the environment variables + services.AddAzureStorageWrapper(options => + { + options.ConnectionString = connectionString; + options.MaxSasUriExpiration = 600; + options.DefaultSasUriExpiration = 300; + options.CreateContainerIfNotExists = true; + //options.DefaultContainer = defaultContainer;// The default container used for all storage operations if not specified explicitly. It is optional + });//Configuration AzureStorageWrapper + + services.AddExample_All();//Configuration Example_All + + }); + + var example_All = serviceProvider.GetService(); + await example_All.RunAsync();// Run the example_All service + + Console.WriteLine("Press any key to exit"); + Console.ReadKey(); + } + + private static ServiceProvider ConfigureServices(Action configurateDelegate) + { + var services = new ServiceCollection(); + configurateDelegate(ConfigurationManager.AppSettings, services); + // Construir el proveedor de servicios + return services.BuildServiceProvider(); + } + } +} diff --git a/samples/dotnetfw/console/DependencyInjections/configuration/Properties/AssemblyInfo.cs b/samples/dotnetfw/console/DependencyInjections/configuration/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..005d673 --- /dev/null +++ b/samples/dotnetfw/console/DependencyInjections/configuration/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("samples")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("samples")] +[assembly: AssemblyCopyright("Copyright © 2025")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("0168626a-763d-4d49-8fda-59f540d56f9d")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/samples/dotnetfw/console/DependencyInjections/configuration/packages.config b/samples/dotnetfw/console/DependencyInjections/configuration/packages.config new file mode 100644 index 0000000..42ebfb2 --- /dev/null +++ b/samples/dotnetfw/console/DependencyInjections/configuration/packages.config @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/dotnetfw/console/DependencyInjections/configuration/samples.csproj b/samples/dotnetfw/console/DependencyInjections/configuration/samples.csproj new file mode 100644 index 0000000..e0d5809 --- /dev/null +++ b/samples/dotnetfw/console/DependencyInjections/configuration/samples.csproj @@ -0,0 +1,211 @@ + + + + + Debug + AnyCPU + {0168626A-763D-4D49-8FDA-59F540D56F9D} + Exe + samples + samples + v4.6.2 + 10.0 + 512 + true + true + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + $(DefineConstants);NETFRAMEWORK + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + $(DefineConstants);NETFRAMEWORK + + + + packages\Azure.Core.1.44.1\lib\net461\Azure.Core.dll + + + packages\Azure.Storage.Blobs.12.23.0\lib\netstandard2.0\Azure.Storage.Blobs.dll + + + packages\Azure.Storage.Common.12.22.0\lib\netstandard2.0\Azure.Storage.Common.dll + + + packages\Ensure.That.10.1.0\lib\net451\Ensure.That.dll + + + packages\Microsoft.Bcl.AsyncInterfaces.9.0.2\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + + + packages\Microsoft.Bcl.Cryptography.9.0.2\lib\net462\Microsoft.Bcl.Cryptography.dll + + + packages\Microsoft.Extensions.DependencyInjection.9.0.2\lib\net462\Microsoft.Extensions.DependencyInjection.dll + + + packages\Microsoft.Extensions.DependencyInjection.Abstractions.9.0.2\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + packages\Microsoft.Extensions.FileProviders.Abstractions.9.0.2\lib\net462\Microsoft.Extensions.FileProviders.Abstractions.dll + + + packages\Microsoft.Extensions.FileProviders.Physical.9.0.2\lib\net462\Microsoft.Extensions.FileProviders.Physical.dll + + + packages\Microsoft.Extensions.FileSystemGlobbing.9.0.2\lib\net462\Microsoft.Extensions.FileSystemGlobbing.dll + + + packages\Microsoft.Extensions.Primitives.9.0.2\lib\net462\Microsoft.Extensions.Primitives.dll + + + packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll + + + + packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + packages\System.ClientModel.1.1.0\lib\netstandard2.0\System.ClientModel.dll + + + + + packages\System.Diagnostics.DiagnosticSource.6.0.1\lib\net461\System.Diagnostics.DiagnosticSource.dll + + + packages\System.Formats.Asn1.9.0.2\lib\net462\System.Formats.Asn1.dll + + + packages\System.IO.Hashing.6.0.0\lib\net461\System.IO.Hashing.dll + + + packages\System.Memory.4.5.5\lib\net461\System.Memory.dll + + + packages\System.Memory.Data.6.0.0\lib\net461\System.Memory.Data.dll + + + packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll + True + True + + + + packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll + True + True + + + + packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll + True + True + + + packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + True + True + + + packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + True + True + + + packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll + True + True + + + packages\System.Security.Cryptography.Xml.9.0.2\lib\net462\System.Security.Cryptography.Xml.dll + + + packages\System.Text.Encodings.Web.6.0.0\lib\net461\System.Text.Encodings.Web.dll + + + packages\System.Text.Json.6.0.10\lib\net461\System.Text.Json.dll + + + packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + + + packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll + + + + + + + + + + AzuriteHelper.cs + + + ConsoleHelper.cs + + + Delete_Blobs.cs + + + Download_Blobs.cs + + + Enumerate_Blobs.cs + + + Samples_All.cs + + + Upload_Blobs.cs + + + Virtual_Folders.cs + + + + + + + run-azurite.bat + Always + + + run-azurite.sh + Always + + + Always + + + + + + {ea9579ca-1424-4e11-53e8-3b6515ff217f} + AzureStorageWrapper + + + + \ No newline at end of file diff --git a/samples/dotnetfw/console/DependencyInjections/configuration/samples.sln b/samples/dotnetfw/console/DependencyInjections/configuration/samples.sln new file mode 100644 index 0000000..76b59c8 --- /dev/null +++ b/samples/dotnetfw/console/DependencyInjections/configuration/samples.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35825.156 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "samples", "samples.csproj", "{0168626A-763D-4D49-8FDA-59F540D56F9D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureStorageWrapper", "..\..\..\..\..\src\AzureStorageWrapper\AzureStorageWrapper.csproj", "{EA9579CA-1424-4E11-53E8-3B6515FF217F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0168626A-763D-4D49-8FDA-59F540D56F9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0168626A-763D-4D49-8FDA-59F540D56F9D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0168626A-763D-4D49-8FDA-59F540D56F9D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0168626A-763D-4D49-8FDA-59F540D56F9D}.Release|Any CPU.Build.0 = Release|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AF4E9CB7-62C0-4DE5-8A07-D8FF9BD9DF45} + EndGlobalSection +EndGlobal diff --git a/samples/dotnetfw/console/DependencyInjections/connectionstring-configuration/App.config b/samples/dotnetfw/console/DependencyInjections/connectionstring-configuration/App.config new file mode 100644 index 0000000..865b315 --- /dev/null +++ b/samples/dotnetfw/console/DependencyInjections/connectionstring-configuration/App.config @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/dotnetfw/console/DependencyInjections/connectionstring-configuration/Program.cs b/samples/dotnetfw/console/DependencyInjections/connectionstring-configuration/Program.cs new file mode 100644 index 0000000..797e8c1 --- /dev/null +++ b/samples/dotnetfw/console/DependencyInjections/connectionstring-configuration/Program.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Specialized; +using System.Configuration; +using System.Threading.Tasks; +using AzureStorageWrapper; +using Microsoft.Extensions.DependencyInjection; + +namespace samples +{ + class Program + { + static async Task Main(string[] args) + { + AzuriteHelper.Start();// Starts the Azurite process by executing the run-azurite.bat file + var serviceProvider = ConfigureServices((configuration, services) => + { + var connectionString = configuration["StorageWrapper_ConnectionString"];// Set the StorageWrapper_ConnectionString string in the environment variables + services.AddAzureStorageWrapper(connectionString);//Configuration AzureStorageWrapper + + // The default container used for all storage operations if not specified explicitly. It is optional + //var defaultContainer = configuration["StorageWrapper_DefaultContainer"];// Set the StorageWrapper_ConnectionString string in the environment variables + //services.AddAzureStorageWrapper(connectionString, defaultContainer);//Configuration AzureStorageWrapper + + services.AddExample_All();//Configuration Example_All + + }); + + var example_All = serviceProvider.GetService(); + await example_All.RunAsync();// Run the example_All service + + Console.WriteLine("Press any key to exit"); + Console.ReadKey(); + } + + private static ServiceProvider ConfigureServices(Action configurateDelegate) + { + var services = new ServiceCollection(); + configurateDelegate(ConfigurationManager.AppSettings, services); + // Construir el proveedor de servicios + return services.BuildServiceProvider(); + } + } +} diff --git a/samples/dotnetfw/console/DependencyInjections/connectionstring-configuration/Properties/AssemblyInfo.cs b/samples/dotnetfw/console/DependencyInjections/connectionstring-configuration/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..005d673 --- /dev/null +++ b/samples/dotnetfw/console/DependencyInjections/connectionstring-configuration/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("samples")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("samples")] +[assembly: AssemblyCopyright("Copyright © 2025")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("0168626a-763d-4d49-8fda-59f540d56f9d")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/samples/dotnetfw/console/DependencyInjections/connectionstring-configuration/packages.config b/samples/dotnetfw/console/DependencyInjections/connectionstring-configuration/packages.config new file mode 100644 index 0000000..42ebfb2 --- /dev/null +++ b/samples/dotnetfw/console/DependencyInjections/connectionstring-configuration/packages.config @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/dotnetfw/console/DependencyInjections/connectionstring-configuration/samples.csproj b/samples/dotnetfw/console/DependencyInjections/connectionstring-configuration/samples.csproj new file mode 100644 index 0000000..e0d5809 --- /dev/null +++ b/samples/dotnetfw/console/DependencyInjections/connectionstring-configuration/samples.csproj @@ -0,0 +1,211 @@ + + + + + Debug + AnyCPU + {0168626A-763D-4D49-8FDA-59F540D56F9D} + Exe + samples + samples + v4.6.2 + 10.0 + 512 + true + true + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + $(DefineConstants);NETFRAMEWORK + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + $(DefineConstants);NETFRAMEWORK + + + + packages\Azure.Core.1.44.1\lib\net461\Azure.Core.dll + + + packages\Azure.Storage.Blobs.12.23.0\lib\netstandard2.0\Azure.Storage.Blobs.dll + + + packages\Azure.Storage.Common.12.22.0\lib\netstandard2.0\Azure.Storage.Common.dll + + + packages\Ensure.That.10.1.0\lib\net451\Ensure.That.dll + + + packages\Microsoft.Bcl.AsyncInterfaces.9.0.2\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + + + packages\Microsoft.Bcl.Cryptography.9.0.2\lib\net462\Microsoft.Bcl.Cryptography.dll + + + packages\Microsoft.Extensions.DependencyInjection.9.0.2\lib\net462\Microsoft.Extensions.DependencyInjection.dll + + + packages\Microsoft.Extensions.DependencyInjection.Abstractions.9.0.2\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + packages\Microsoft.Extensions.FileProviders.Abstractions.9.0.2\lib\net462\Microsoft.Extensions.FileProviders.Abstractions.dll + + + packages\Microsoft.Extensions.FileProviders.Physical.9.0.2\lib\net462\Microsoft.Extensions.FileProviders.Physical.dll + + + packages\Microsoft.Extensions.FileSystemGlobbing.9.0.2\lib\net462\Microsoft.Extensions.FileSystemGlobbing.dll + + + packages\Microsoft.Extensions.Primitives.9.0.2\lib\net462\Microsoft.Extensions.Primitives.dll + + + packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll + + + + packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + packages\System.ClientModel.1.1.0\lib\netstandard2.0\System.ClientModel.dll + + + + + packages\System.Diagnostics.DiagnosticSource.6.0.1\lib\net461\System.Diagnostics.DiagnosticSource.dll + + + packages\System.Formats.Asn1.9.0.2\lib\net462\System.Formats.Asn1.dll + + + packages\System.IO.Hashing.6.0.0\lib\net461\System.IO.Hashing.dll + + + packages\System.Memory.4.5.5\lib\net461\System.Memory.dll + + + packages\System.Memory.Data.6.0.0\lib\net461\System.Memory.Data.dll + + + packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll + True + True + + + + packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll + True + True + + + + packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll + True + True + + + packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + True + True + + + packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + True + True + + + packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll + True + True + + + packages\System.Security.Cryptography.Xml.9.0.2\lib\net462\System.Security.Cryptography.Xml.dll + + + packages\System.Text.Encodings.Web.6.0.0\lib\net461\System.Text.Encodings.Web.dll + + + packages\System.Text.Json.6.0.10\lib\net461\System.Text.Json.dll + + + packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + + + packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll + + + + + + + + + + AzuriteHelper.cs + + + ConsoleHelper.cs + + + Delete_Blobs.cs + + + Download_Blobs.cs + + + Enumerate_Blobs.cs + + + Samples_All.cs + + + Upload_Blobs.cs + + + Virtual_Folders.cs + + + + + + + run-azurite.bat + Always + + + run-azurite.sh + Always + + + Always + + + + + + {ea9579ca-1424-4e11-53e8-3b6515ff217f} + AzureStorageWrapper + + + + \ No newline at end of file diff --git a/samples/dotnetfw/console/DependencyInjections/connectionstring-configuration/samples.sln b/samples/dotnetfw/console/DependencyInjections/connectionstring-configuration/samples.sln new file mode 100644 index 0000000..76b59c8 --- /dev/null +++ b/samples/dotnetfw/console/DependencyInjections/connectionstring-configuration/samples.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35825.156 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "samples", "samples.csproj", "{0168626A-763D-4D49-8FDA-59F540D56F9D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureStorageWrapper", "..\..\..\..\..\src\AzureStorageWrapper\AzureStorageWrapper.csproj", "{EA9579CA-1424-4E11-53E8-3B6515FF217F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0168626A-763D-4D49-8FDA-59F540D56F9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0168626A-763D-4D49-8FDA-59F540D56F9D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0168626A-763D-4D49-8FDA-59F540D56F9D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0168626A-763D-4D49-8FDA-59F540D56F9D}.Release|Any CPU.Build.0 = Release|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AF4E9CB7-62C0-4DE5-8A07-D8FF9BD9DF45} + EndGlobalSection +EndGlobal diff --git a/samples/dotnetfw/console/DependencyInjections/minimal-configuration/App.config b/samples/dotnetfw/console/DependencyInjections/minimal-configuration/App.config new file mode 100644 index 0000000..865b315 --- /dev/null +++ b/samples/dotnetfw/console/DependencyInjections/minimal-configuration/App.config @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/dotnetfw/console/DependencyInjections/minimal-configuration/Program.cs b/samples/dotnetfw/console/DependencyInjections/minimal-configuration/Program.cs new file mode 100644 index 0000000..dfc5d30 --- /dev/null +++ b/samples/dotnetfw/console/DependencyInjections/minimal-configuration/Program.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Specialized; +using System.Configuration; +using System.Runtime.Remoting.Contexts; +using System.Threading.Tasks; +using AzureStorageWrapper; +using Microsoft.Extensions.DependencyInjection; + +namespace samples +{ + class Program + { + static async Task Main(string[] args) + { + AzuriteHelper.Start();// Starts the Azurite process by executing the run-azurite.bat file + var serviceProvider = ConfigureServices((configuration, services) => + { + Environment.SetEnvironmentVariable("StorageWrapper_ConnectionString", configuration["StorageWrapper_ConnectionString"]);// Set the StorageWrapper_ConnectionString string in the environment variables + // The default container used for all storage operations if not specified explicitly. It is optional + Environment.SetEnvironmentVariable("StorageWrapper_DefaultContainer", configuration["StorageWrapper_DefaultContainer"]); + services.AddAzureStorageWrapper();//Configuration AzureStorageWrapper + + services.AddExample_All();//Configuration Example_All + + }); + + var example_All = serviceProvider.GetService(); + await example_All.RunAsync();// Run the example_All service + + Console.WriteLine("Press any key to exit"); + Console.ReadKey(); + } + + private static ServiceProvider ConfigureServices(Action configurateDelegate) + { + var services = new ServiceCollection(); + configurateDelegate(ConfigurationManager.AppSettings, services); + // Construir el proveedor de servicios + return services.BuildServiceProvider(); + } + } +} diff --git a/samples/dotnetfw/console/DependencyInjections/minimal-configuration/Properties/AssemblyInfo.cs b/samples/dotnetfw/console/DependencyInjections/minimal-configuration/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..005d673 --- /dev/null +++ b/samples/dotnetfw/console/DependencyInjections/minimal-configuration/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("samples")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("samples")] +[assembly: AssemblyCopyright("Copyright © 2025")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("0168626a-763d-4d49-8fda-59f540d56f9d")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/samples/dotnetfw/console/DependencyInjections/minimal-configuration/packages.config b/samples/dotnetfw/console/DependencyInjections/minimal-configuration/packages.config new file mode 100644 index 0000000..42ebfb2 --- /dev/null +++ b/samples/dotnetfw/console/DependencyInjections/minimal-configuration/packages.config @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/dotnetfw/console/DependencyInjections/minimal-configuration/samples.csproj b/samples/dotnetfw/console/DependencyInjections/minimal-configuration/samples.csproj new file mode 100644 index 0000000..e0d5809 --- /dev/null +++ b/samples/dotnetfw/console/DependencyInjections/minimal-configuration/samples.csproj @@ -0,0 +1,211 @@ + + + + + Debug + AnyCPU + {0168626A-763D-4D49-8FDA-59F540D56F9D} + Exe + samples + samples + v4.6.2 + 10.0 + 512 + true + true + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + $(DefineConstants);NETFRAMEWORK + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + $(DefineConstants);NETFRAMEWORK + + + + packages\Azure.Core.1.44.1\lib\net461\Azure.Core.dll + + + packages\Azure.Storage.Blobs.12.23.0\lib\netstandard2.0\Azure.Storage.Blobs.dll + + + packages\Azure.Storage.Common.12.22.0\lib\netstandard2.0\Azure.Storage.Common.dll + + + packages\Ensure.That.10.1.0\lib\net451\Ensure.That.dll + + + packages\Microsoft.Bcl.AsyncInterfaces.9.0.2\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + + + packages\Microsoft.Bcl.Cryptography.9.0.2\lib\net462\Microsoft.Bcl.Cryptography.dll + + + packages\Microsoft.Extensions.DependencyInjection.9.0.2\lib\net462\Microsoft.Extensions.DependencyInjection.dll + + + packages\Microsoft.Extensions.DependencyInjection.Abstractions.9.0.2\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + packages\Microsoft.Extensions.FileProviders.Abstractions.9.0.2\lib\net462\Microsoft.Extensions.FileProviders.Abstractions.dll + + + packages\Microsoft.Extensions.FileProviders.Physical.9.0.2\lib\net462\Microsoft.Extensions.FileProviders.Physical.dll + + + packages\Microsoft.Extensions.FileSystemGlobbing.9.0.2\lib\net462\Microsoft.Extensions.FileSystemGlobbing.dll + + + packages\Microsoft.Extensions.Primitives.9.0.2\lib\net462\Microsoft.Extensions.Primitives.dll + + + packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll + + + + packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + packages\System.ClientModel.1.1.0\lib\netstandard2.0\System.ClientModel.dll + + + + + packages\System.Diagnostics.DiagnosticSource.6.0.1\lib\net461\System.Diagnostics.DiagnosticSource.dll + + + packages\System.Formats.Asn1.9.0.2\lib\net462\System.Formats.Asn1.dll + + + packages\System.IO.Hashing.6.0.0\lib\net461\System.IO.Hashing.dll + + + packages\System.Memory.4.5.5\lib\net461\System.Memory.dll + + + packages\System.Memory.Data.6.0.0\lib\net461\System.Memory.Data.dll + + + packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll + True + True + + + + packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll + True + True + + + + packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll + True + True + + + packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + True + True + + + packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + True + True + + + packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll + True + True + + + packages\System.Security.Cryptography.Xml.9.0.2\lib\net462\System.Security.Cryptography.Xml.dll + + + packages\System.Text.Encodings.Web.6.0.0\lib\net461\System.Text.Encodings.Web.dll + + + packages\System.Text.Json.6.0.10\lib\net461\System.Text.Json.dll + + + packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + + + packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll + + + + + + + + + + AzuriteHelper.cs + + + ConsoleHelper.cs + + + Delete_Blobs.cs + + + Download_Blobs.cs + + + Enumerate_Blobs.cs + + + Samples_All.cs + + + Upload_Blobs.cs + + + Virtual_Folders.cs + + + + + + + run-azurite.bat + Always + + + run-azurite.sh + Always + + + Always + + + + + + {ea9579ca-1424-4e11-53e8-3b6515ff217f} + AzureStorageWrapper + + + + \ No newline at end of file diff --git a/samples/dotnetfw/console/DependencyInjections/minimal-configuration/samples.sln b/samples/dotnetfw/console/DependencyInjections/minimal-configuration/samples.sln new file mode 100644 index 0000000..76b59c8 --- /dev/null +++ b/samples/dotnetfw/console/DependencyInjections/minimal-configuration/samples.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35825.156 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "samples", "samples.csproj", "{0168626A-763D-4D49-8FDA-59F540D56F9D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureStorageWrapper", "..\..\..\..\..\src\AzureStorageWrapper\AzureStorageWrapper.csproj", "{EA9579CA-1424-4E11-53E8-3B6515FF217F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0168626A-763D-4D49-8FDA-59F540D56F9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0168626A-763D-4D49-8FDA-59F540D56F9D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0168626A-763D-4D49-8FDA-59F540D56F9D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0168626A-763D-4D49-8FDA-59F540D56F9D}.Release|Any CPU.Build.0 = Release|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AF4E9CB7-62C0-4DE5-8A07-D8FF9BD9DF45} + EndGlobalSection +EndGlobal diff --git a/samples/dotnetfw/console/WithoutDependencyInjections/App.config b/samples/dotnetfw/console/WithoutDependencyInjections/App.config new file mode 100644 index 0000000..61cbe8c --- /dev/null +++ b/samples/dotnetfw/console/WithoutDependencyInjections/App.config @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/dotnetfw/console/WithoutDependencyInjections/Program.cs b/samples/dotnetfw/console/WithoutDependencyInjections/Program.cs new file mode 100644 index 0000000..23e53f7 --- /dev/null +++ b/samples/dotnetfw/console/WithoutDependencyInjections/Program.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using AzureStorageWrapper; +using AzureStorageWrapper.Commands; +using samples.Helpers; + +namespace samples +{ + class Program + { + static async Task Main(string[] args) + { + AzuriteHelper.Start();// Starts the Azurite process by executing the run-azurite.bat file + var options = new AzureStorageWrapperOptions + { + ConnectionString = "UseDevelopmentStorage=true", + MaxSasUriExpiration = 600, + DefaultSasUriExpiration = 300, + CreateContainerIfNotExists = true, + //DefaultContainer ="files" // The default container used for all storage operations if not specified explicitly. It is optional + }; + var azureStorageWrapper = new AzureStorageWrapper.AzureStorageWrapper(options); + + + #region Upload Blobs In Bytes + ConsoleHelper.Start("Upload in Bytes"); + var bytes = Convert.FromBase64String("SGVsbG8g8J+Zgg=="); + + var command = new UploadBytes() + { + Bytes = bytes, + Container = "files", + Name = "hello", + Extension = "md", + Metadata = new Dictionary() { { "key", "value" } } + }; + + var response = await azureStorageWrapper.UploadBlobAsync(command); + ConsoleHelper.Result(response); + ConsoleHelper.Finalized("Upload in Base64"); + #endregion + + Console.WriteLine("Press any key to exit"); + Console.ReadKey(); + } + } +} diff --git a/samples/dotnetfw/console/WithoutDependencyInjections/Properties/AssemblyInfo.cs b/samples/dotnetfw/console/WithoutDependencyInjections/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..005d673 --- /dev/null +++ b/samples/dotnetfw/console/WithoutDependencyInjections/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("samples")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("samples")] +[assembly: AssemblyCopyright("Copyright © 2025")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("0168626a-763d-4d49-8fda-59f540d56f9d")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/samples/dotnetfw/console/WithoutDependencyInjections/packages.config b/samples/dotnetfw/console/WithoutDependencyInjections/packages.config new file mode 100644 index 0000000..42ebfb2 --- /dev/null +++ b/samples/dotnetfw/console/WithoutDependencyInjections/packages.config @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/dotnetfw/console/WithoutDependencyInjections/samples.csproj b/samples/dotnetfw/console/WithoutDependencyInjections/samples.csproj new file mode 100644 index 0000000..3749c2e --- /dev/null +++ b/samples/dotnetfw/console/WithoutDependencyInjections/samples.csproj @@ -0,0 +1,211 @@ + + + + + Debug + AnyCPU + {0168626A-763D-4D49-8FDA-59F540D56F9D} + Exe + samples + samples + v4.6.2 + 10.0 + 512 + true + true + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + $(DefineConstants);NETFRAMEWORK + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + $(DefineConstants);NETFRAMEWORK + + + + packages\Azure.Core.1.44.1\lib\net461\Azure.Core.dll + + + packages\Azure.Storage.Blobs.12.23.0\lib\netstandard2.0\Azure.Storage.Blobs.dll + + + packages\Azure.Storage.Common.12.22.0\lib\netstandard2.0\Azure.Storage.Common.dll + + + packages\Ensure.That.10.1.0\lib\net451\Ensure.That.dll + + + packages\Microsoft.Bcl.AsyncInterfaces.9.0.2\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + + + packages\Microsoft.Bcl.Cryptography.9.0.2\lib\net462\Microsoft.Bcl.Cryptography.dll + + + packages\Microsoft.Extensions.DependencyInjection.9.0.2\lib\net462\Microsoft.Extensions.DependencyInjection.dll + + + packages\Microsoft.Extensions.DependencyInjection.Abstractions.9.0.2\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + packages\Microsoft.Extensions.FileProviders.Abstractions.9.0.2\lib\net462\Microsoft.Extensions.FileProviders.Abstractions.dll + + + packages\Microsoft.Extensions.FileProviders.Physical.9.0.2\lib\net462\Microsoft.Extensions.FileProviders.Physical.dll + + + packages\Microsoft.Extensions.FileSystemGlobbing.9.0.2\lib\net462\Microsoft.Extensions.FileSystemGlobbing.dll + + + packages\Microsoft.Extensions.Primitives.9.0.2\lib\net462\Microsoft.Extensions.Primitives.dll + + + packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll + + + + packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + packages\System.ClientModel.1.1.0\lib\netstandard2.0\System.ClientModel.dll + + + + + packages\System.Diagnostics.DiagnosticSource.6.0.1\lib\net461\System.Diagnostics.DiagnosticSource.dll + + + packages\System.Formats.Asn1.9.0.2\lib\net462\System.Formats.Asn1.dll + + + packages\System.IO.Hashing.6.0.0\lib\net461\System.IO.Hashing.dll + + + packages\System.Memory.4.5.5\lib\net461\System.Memory.dll + + + packages\System.Memory.Data.6.0.0\lib\net461\System.Memory.Data.dll + + + packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll + True + True + + + + packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll + True + True + + + + packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll + True + True + + + packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + True + True + + + packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + True + True + + + packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll + True + True + + + packages\System.Security.Cryptography.Xml.9.0.2\lib\net462\System.Security.Cryptography.Xml.dll + + + packages\System.Text.Encodings.Web.6.0.0\lib\net461\System.Text.Encodings.Web.dll + + + packages\System.Text.Json.6.0.10\lib\net461\System.Text.Json.dll + + + packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + + + packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll + + + + + + + + + + AzuriteHelper.cs + + + ConsoleHelper.cs + + + Delete_Blobs.cs + + + Download_Blobs.cs + + + Enumerate_Blobs.cs + + + Samples_All.cs + + + Upload_Blobs.cs + + + Virtual_Folders.cs + + + + + + + run-azurite.bat + Always + + + run-azurite.sh + Always + + + Always + + + + + + {ea9579ca-1424-4e11-53e8-3b6515ff217f} + AzureStorageWrapper + + + + \ No newline at end of file diff --git a/samples/dotnetfw/console/WithoutDependencyInjections/samples.sln b/samples/dotnetfw/console/WithoutDependencyInjections/samples.sln new file mode 100644 index 0000000..5e1c6b2 --- /dev/null +++ b/samples/dotnetfw/console/WithoutDependencyInjections/samples.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35825.156 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "samples", "samples.csproj", "{0168626A-763D-4D49-8FDA-59F540D56F9D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureStorageWrapper", "..\..\..\..\src\AzureStorageWrapper\AzureStorageWrapper.csproj", "{EA9579CA-1424-4E11-53E8-3B6515FF217F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0168626A-763D-4D49-8FDA-59F540D56F9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0168626A-763D-4D49-8FDA-59F540D56F9D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0168626A-763D-4D49-8FDA-59F540D56F9D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0168626A-763D-4D49-8FDA-59F540D56F9D}.Release|Any CPU.Build.0 = Release|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA9579CA-1424-4E11-53E8-3B6515FF217F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AF4E9CB7-62C0-4DE5-8A07-D8FF9BD9DF45} + EndGlobalSection +EndGlobal diff --git a/samples/sharedcontent/AzuriteHelper.cs b/samples/sharedcontent/AzuriteHelper.cs new file mode 100644 index 0000000..2259fcc --- /dev/null +++ b/samples/sharedcontent/AzuriteHelper.cs @@ -0,0 +1,18 @@ +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Threading; + +namespace samples; + +public static class AzuriteHelper +{ + public static void Start() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + Process.Start($"{Environment.CurrentDirectory}\\run-azurite.bat"); + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + Process.Start($"{Environment.CurrentDirectory}\\run-azurite.sh"); + Thread.Sleep(4000); + } +} diff --git a/samples/sharedcontent/ConsoleHelper.cs b/samples/sharedcontent/ConsoleHelper.cs new file mode 100644 index 0000000..67afa38 --- /dev/null +++ b/samples/sharedcontent/ConsoleHelper.cs @@ -0,0 +1,53 @@ +using System; +using System.Security.Cryptography; +#if NETCOREAPP +using System.Text.Json; +#elif NETFRAMEWORK +using Newtonsoft.Json; +#endif + +namespace samples.Helpers +{ + public static class ConsoleHelper + { + private const ConsoleColor _blockColor = ConsoleColor.Cyan; + private const ConsoleColor _resultColor = ConsoleColor.Green; + private const ConsoleColor _moduleColor = ConsoleColor.Yellow; + private const ConsoleColor _infoColor = ConsoleColor.White; + +#if NET + private static JsonSerializerOptions _jsonSerializerOptions => new JsonSerializerOptions() { WriteIndented = true }; +#elif NETFRAMEWORK + private static JsonSerializerSettings _jsonSerializerSettings => new JsonSerializerSettings { Formatting = Formatting.Indented }; +#endif + + public static void Info(string message) => WriteImpl(message, _infoColor); + public static void Module(string message) => WriteImpl($"\r\n{message}\r\n", _moduleColor); + + public static void Start(string message) => WriteImpl($"\r\n=== {message} ===", _blockColor); + public static void Finalized(string message) => WriteImpl($"=== FIN - {message} ===", _blockColor); + + public static void Result(object value) + { +#if NET + var message = $"Result: {JsonSerializer.Serialize(value, _jsonSerializerOptions)}"; +#elif NETFRAMEWORK + var message = $"Result: {JsonConvert.SerializeObject(value, _jsonSerializerSettings)}"; +#endif + Result(message); + } + public static void Result(string message) => WriteImpl(message, _resultColor); + + + + private static void WriteImpl(string message, ConsoleColor color, bool isLine = true) + { + Console.ForegroundColor = color; + if (isLine) + Console.WriteLine(message); + else + Console.Write(message); + Console.ResetColor(); + } + } +} diff --git a/samples/sharedcontent/Delete_Blobs.cs b/samples/sharedcontent/Delete_Blobs.cs new file mode 100644 index 0000000..9083470 --- /dev/null +++ b/samples/sharedcontent/Delete_Blobs.cs @@ -0,0 +1,47 @@ +using System.Threading.Tasks; +using AzureStorageWrapper; +using AzureStorageWrapper.Commands; +using samples.Helpers; + +namespace samples +{ + public class Delete_Blobs + { + readonly IAzureStorageWrapper _azureStorageWrapper; + public Delete_Blobs(IAzureStorageWrapper azureStorageWrapper) + { + _azureStorageWrapper = azureStorageWrapper; + } + public async Task RunAllAsync() + { + ConsoleHelper.Module("**** DELETE BLOBS ****"); + await DeleteByUriAsync(); + await DeleteByCommandAsync(); + } + + public async Task DeleteByUriAsync() + { + ConsoleHelper.Start("Delete Blobs by Uri"); + var uri = "https://accountName.blob.core.windows.net/files/5a19306fc5014a4/hello.md"; + + await _azureStorageWrapper.DeleteBlobAsync(uri); + + ConsoleHelper.Finalized("Download in Base64"); + ConsoleHelper.Finalized("Delete Blobs by Uri"); + } + + public async Task DeleteByCommandAsync() + { + ConsoleHelper.Start("Delete Blobs by Command"); + var command = new DeleteBlob() + { + Uri = "https://accountName.blob.core.windows.net/files/5a19306fc5014a4/hello.md" + }; + + await _azureStorageWrapper.DeleteBlobAsync(command); + + ConsoleHelper.Finalized("Download in Base64"); + ConsoleHelper.Finalized("Delete Blobs by Command"); + } + } +} diff --git a/samples/sharedcontent/Download_Blobs.cs b/samples/sharedcontent/Download_Blobs.cs new file mode 100644 index 0000000..c5b69f1 --- /dev/null +++ b/samples/sharedcontent/Download_Blobs.cs @@ -0,0 +1,96 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using AzureStorageWrapper; +using AzureStorageWrapper.Commands; +using AzureStorageWrapper.Queries; +using AzureStorageWrapper.Responses; +using samples.Helpers; + +namespace samples +{ + public class Download_Blobs + { + readonly IAzureStorageWrapper _azureStorageWrapper; + public Download_Blobs(IAzureStorageWrapper azureStorageWrapper) + { + _azureStorageWrapper = azureStorageWrapper; + } + public async Task RunAllAsync() + { + ConsoleHelper.Module("**** DOWNLOAD BLOBS ****"); + await DownloadBlobReferencesByUriAsync(); + await DownloadBlobReferencesByCommandAsync(); + await DownloadBlobByUriAsync(); + await DownloadBlobByCommandAsync(); + } + + public async Task DownloadBlobReferencesByUriAsync() + { + var uri = await UploadFileAsync(); + ConsoleHelper.Start("Download Blob References by Uri"); + + var response = await _azureStorageWrapper.DownloadBlobReferenceAsync(uri); + + ConsoleHelper.Result(response); + ConsoleHelper.Finalized("Download Blob References by Uri"); + } + public async Task DownloadBlobReferencesByCommandAsync() + { + var uri = await UploadFileAsync(); + ConsoleHelper.Start("Download Blob References by Command"); + var query = new DownloadBlobReference() + { + Uri = uri, + ExpiresIn = 60 + }; + + var response = await _azureStorageWrapper.DownloadBlobReferenceAsync(query); ConsoleHelper.Result(response); + ConsoleHelper.Result(response); + ConsoleHelper.Finalized("Download Blob References by Command"); + } + + public async Task DownloadBlobByUriAsync() + { + var uri = await UploadFileAsync(); + ConsoleHelper.Start("Download Blob by Uri"); + + var response = await _azureStorageWrapper.DownloadBlobAsync(uri); + + ConsoleHelper.Result(response); + ConsoleHelper.Finalized("Download Blob by Uri"); + } + public async Task DownloadBlobByCommandAsync() + { + var uri = await UploadFileAsync(); + ConsoleHelper.Start("Download Blob by Command"); + var query = new DownloadBlob() + { + Uri = uri, + }; + + var response = await _azureStorageWrapper.DownloadBlobAsync(query); + + ConsoleHelper.Result(response); + ConsoleHelper.Finalized("Download Blob by Command"); + } + + + private async Task UploadFileAsync() + { + var base64 = "SGVsbG8g8J+Zgg=="; + + var uploadBlobCommand = new UploadBase64() + { + Base64 = base64, + Container = "files", + Name = "hello", + Extension = "md", + Metadata = new Dictionary() + {{"hello", "world"}} + }; + + var response = await _azureStorageWrapper.UploadBlobAsync(uploadBlobCommand); + return response.Uri; + } + } +} diff --git a/samples/sharedcontent/Enumerate_Blobs.cs b/samples/sharedcontent/Enumerate_Blobs.cs new file mode 100644 index 0000000..9adaeb2 --- /dev/null +++ b/samples/sharedcontent/Enumerate_Blobs.cs @@ -0,0 +1,104 @@ +using System.Drawing; +using System.Threading.Tasks; +using AzureStorageWrapper; +using AzureStorageWrapper.Queries; +using samples.Helpers; + +namespace samples +{ + public class Enumerate_Blobs + { + readonly IAzureStorageWrapper _azureStorageWrapper; + public Enumerate_Blobs(IAzureStorageWrapper azureStorageWrapper) + { + _azureStorageWrapper = azureStorageWrapper; + } + public async Task RunAllAsync() + { + ConsoleHelper.Module("**** ENUMERATE BLOBS ****"); + await EnumerateWithoutPaginationAsync(); + await EnumerateWithoutPaginationByCommandAsync(); + await EnumerateWithPaginationWithoutContinationTokenAsync(); + await EnumerateWithPaginationWithoutContinationTokenByCommandAsync(); + await EnumerateWithPaginationWithContinationTokenByCommandAsync(); + } + + public async Task EnumerateWithoutPaginationAsync() + { + ConsoleHelper.Start("Enumerate Blobs without Pagination"); + var container = "files"; + + //var response = await _azureStorageWrapper.EnumerateBlobsAsync(); //You will need to set the DefaultContainer option. + var response = await _azureStorageWrapper.EnumerateBlobsAsync(container); + + ConsoleHelper.Result(response); + ConsoleHelper.Finalized("Enumerate Blobs without Pagination"); + } + public async Task EnumerateWithoutPaginationByCommandAsync() + { + ConsoleHelper.Start("Enumerate Blobs without Pagination by Command"); + var query = new EnumerateBlobs() + { + Container = "files", + Paginate = false + }; + + var response = await _azureStorageWrapper.EnumerateBlobsAsync(query); + ConsoleHelper.Result(response); + ConsoleHelper.Finalized("Enumerate Blobs without Pagination by Command"); + } + + public async Task EnumerateWithPaginationWithoutContinationTokenAsync() + { + ConsoleHelper.Start("Enumerate Blobs with Pagination and without ContinationToken"); + var container = "files"; + var size = 10; + + //var response = await _azureStorageWrapper.EnumerateBlobsAsync(size); //You will need to set the DefaultContainer option. + var response = await _azureStorageWrapper.EnumerateBlobsAsync(size, container); + + ConsoleHelper.Result(response); + ConsoleHelper.Finalized("Enumerate Blobs with Pagination and without ContinationToken"); + } + public async Task EnumerateWithPaginationWithoutContinationTokenByCommandAsync() + { + ConsoleHelper.Start("Enumerate Blobs with Pagination and without ContinationToken by Command"); + var query = new EnumerateBlobs() + { + Container = "files", + Paginate = true, + Size = 10, + }; + + var response = await _azureStorageWrapper.EnumerateBlobsAsync(query); + ConsoleHelper.Result(response); + ConsoleHelper.Finalized("Enumerate Blobs with Pagination and without ContinationToken by Command"); + } + + public async Task EnumerateWithPaginationWithContinationTokenByCommandAsync() + { + ConsoleHelper.Start("Enumerate Blobs with Pagination and with ContinationToken"); + var firstQuery = new EnumerateBlobs() + { + Container = "files", + Paginate = true, + Size = 10, + }; + + var firstResponse = await _azureStorageWrapper.EnumerateBlobsAsync(firstQuery); + ConsoleHelper.Result(firstResponse); + + var secondQuery = new EnumerateBlobs() + { + Container = "files", + Paginate = true, + Size = 10, + ContinuationToken = firstResponse.ContinuationToken + }; + + var secondResponse = await _azureStorageWrapper.EnumerateBlobsAsync(secondQuery); + ConsoleHelper.Result(secondResponse); + ConsoleHelper.Finalized("Enumerate Blobs with Pagination and with ContinationToken"); + } + } +} diff --git a/samples/sharedcontent/Samples_All.cs b/samples/sharedcontent/Samples_All.cs new file mode 100644 index 0000000..36dfc2e --- /dev/null +++ b/samples/sharedcontent/Samples_All.cs @@ -0,0 +1,52 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using samples.Helpers; + +namespace samples +{ + public class Samples_All + { + private readonly Upload_Blobs _upload_Blobs; + private readonly Virtual_Folders _virtual_Folders; + private readonly Delete_Blobs _delete_Blobs; + private readonly Download_Blobs _download_Blobs; + private readonly Enumerate_Blobs _enumerate_Blobs; + public Samples_All(Upload_Blobs upload_Blobs, Virtual_Folders virtual_Folders,Delete_Blobs delete_Blobs, + Download_Blobs download_Blobs, Enumerate_Blobs enumerate_Blobs) + { + _upload_Blobs = upload_Blobs; + _virtual_Folders = virtual_Folders; + _delete_Blobs = delete_Blobs; + _download_Blobs = download_Blobs; + _enumerate_Blobs = enumerate_Blobs; + } + + public async Task RunAsync() + { + ConsoleHelper.Info("Samples - All"); + await _upload_Blobs.RunAllAsync(); + await _virtual_Folders.RunAllAsync(); + await _download_Blobs.RunAllAsync(); + await _delete_Blobs.RunAllAsync(); + await _enumerate_Blobs.RunAllAsync(); + ConsoleHelper.Info(""); + ConsoleHelper.Info("FIN - Samples - All"); + } + } + + public static class Example_All_DependencyInjection + { + public static IServiceCollection AddExample_All(this IServiceCollection services) + { + services.AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + ; + return services; + } + } + +} diff --git a/samples/sharedcontent/Upload_Blobs.cs b/samples/sharedcontent/Upload_Blobs.cs new file mode 100644 index 0000000..e8f3a10 --- /dev/null +++ b/samples/sharedcontent/Upload_Blobs.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Threading.Tasks; +using AzureStorageWrapper; +using AzureStorageWrapper.Commands; +using samples.Helpers; +using static System.Net.WebRequestMethods; + +namespace samples +{ + public class Upload_Blobs + { + readonly IAzureStorageWrapper _azureStorageWrapper; + public Upload_Blobs(IAzureStorageWrapper azureStorageWrapper) + { + _azureStorageWrapper = azureStorageWrapper; + } + + public async Task RunAllAsync() + { + ConsoleHelper.Module("**** UPLOAD BLOBS ****"); + await UploadByFileInBase64Async(); + await UploadByCommandInBase64Async(); + await UploadByFileInBytesAsync(); + await UploadByCommandInBytesAsync(); + await UploadByFileInStreamAsync(); + await UploadByCommandInStreamAsync(); + } + + public async Task UploadByFileInBase64Async() + { + ConsoleHelper.Start("Upload by file and content in Base64"); + var base64 = "SGVsbG8g8J+Zgg=="; + var container = "files"; + + //var response = await _azureStorageWrapper.UploadBlobAsync("files.md", base64); //You will need to set the DefaultContainer option. + var response = await _azureStorageWrapper.UploadBlobAsync("files.md", base64, container); + + ConsoleHelper.Result(response); + ConsoleHelper.Finalized("Upload by file and content in Base64"); + } + + public async Task UploadByCommandInBase64Async() + { + ConsoleHelper.Start("Upload by Command in Base64"); + var base64 = "SGVsbG8g8J+Zgg=="; + + var command = new UploadBase64() + { + Base64 = base64, + Container = "files", + Name = "hello", + Extension = "md", + Metadata = new Dictionary() { { "key", "value" } } + }; + + var response = await _azureStorageWrapper.UploadBlobAsync(command); + ConsoleHelper.Result(response); + ConsoleHelper.Finalized("Upload in Base64"); + } + + public async Task UploadByFileInBytesAsync() + { + ConsoleHelper.Start("Upload by file and content in Bytes"); + var bytes = Convert.FromBase64String("SGVsbG8g8J+Zgg=="); + var container = "files"; + + //var response = await _azureStorageWrapper.UploadBlobAsync("files.md", bytes); //You will need to set the DefaultContainer option. + var response = await _azureStorageWrapper.UploadBlobAsync("files.md", bytes, container); + + ConsoleHelper.Result(response); + ConsoleHelper.Finalized("Upload by file and content in Bytes"); + } + + public async Task UploadByCommandInBytesAsync() + { + ConsoleHelper.Start("Upload in Bytes"); + var bytes = Convert.FromBase64String("SGVsbG8g8J+Zgg=="); + + var command = new UploadBytes() + { + Bytes = bytes, + Container = "files", + Name = "hello", + Extension = "md", + Metadata = new Dictionary() { { "key", "value" } } + }; + + var response = await _azureStorageWrapper.UploadBlobAsync(command); + ConsoleHelper.Result(response); + ConsoleHelper.Finalized("Upload in Bytes"); + } + + public async Task UploadByFileInStreamAsync() + { + ConsoleHelper.Start("Upload by file and content in Stream"); + var stream = new MemoryStream(Convert.FromBase64String("SGVsbG8g8J+Zgg==")); + var container = "files"; + + //var response = await _azureStorageWrapper.UploadBlobAsync("files.md", bytes); //You will need to set the DefaultContainer option. + var response = await _azureStorageWrapper.UploadBlobAsync("files.md", stream, container); + + ConsoleHelper.Result(response); + ConsoleHelper.Finalized("Upload by file and content in Stream"); + } + + public async Task UploadByCommandInStreamAsync() + { + ConsoleHelper.Start("Upload by Command in Stream"); + var stream = new MemoryStream(Convert.FromBase64String("SGVsbG8g8J+Zgg==")); + + var command = new UploadStream() + { + Stream = stream, + Container = "files", + Name = "hello", + Extension = "md", + Metadata = new Dictionary() { { "key", "value" } } + }; + + var response = await _azureStorageWrapper.UploadBlobAsync(command); + ConsoleHelper.Result(response); + ConsoleHelper.Finalized("Upload by Command in Stream"); + } + } +} diff --git a/samples/sharedcontent/Virtual_Folders.cs b/samples/sharedcontent/Virtual_Folders.cs new file mode 100644 index 0000000..7e0d942 --- /dev/null +++ b/samples/sharedcontent/Virtual_Folders.cs @@ -0,0 +1,62 @@ +using System; +using System.Threading.Tasks; +using AzureStorageWrapper; +using AzureStorageWrapper.Commands; +using samples.Helpers; + +namespace samples +{ + public class Virtual_Folders + { + readonly IAzureStorageWrapper _azureStorageWrapper; + public Virtual_Folders(IAzureStorageWrapper azureStorageWrapper) + { + _azureStorageWrapper = azureStorageWrapper; + } + + public async Task RunAllAsync() + { + ConsoleHelper.Module("**** VIRTUAL FOLDERS ****"); + await UploadWithVirtualFolderASync(); + await UploadWithoutVirtualFolderASync(); + } + + public async Task UploadWithVirtualFolderASync() + { + ConsoleHelper.Start("Upload With Virtual Folders"); + var base64 = "SGVsbG8g8J+Zgg=="; + + var command = new UploadBase64() + { + Base64 = base64, + Container = "files", + Name = $"{Guid.NewGuid()}", + Extension = "md", + UseVirtualFolder = true// Default: True; + }; + + var response = await _azureStorageWrapper.UploadBlobAsync(command); + ConsoleHelper.Result(response); + ConsoleHelper.Finalized("Upload With Virtual Folders"); + } + public async Task UploadWithoutVirtualFolderASync() + { + ConsoleHelper.Start("Upload Without Virtual Folders"); + var base64 = "SGVsbG8g8J+Zgg=="; + + var command = new UploadBase64() + { + Base64 = base64, + Container = "files", + Name = $"{Guid.NewGuid()}", + Extension = "md", + UseVirtualFolder = false + }; + + var response = await _azureStorageWrapper.UploadBlobAsync(command); + ConsoleHelper.Result(response); + ConsoleHelper.Finalized("Upload Without Virtual Folders"); + } + + } +} diff --git a/samples/sharedcontent/run-azurite.bat b/samples/sharedcontent/run-azurite.bat new file mode 100644 index 0000000..f162d48 --- /dev/null +++ b/samples/sharedcontent/run-azurite.bat @@ -0,0 +1,11 @@ +@echo off + +REM Instructions to run this script: +REM 1. Make sure you have Azurite installed. You can install it using npm: +REM npm install -g azurite +REM 2. Make sure you have the .NET SDK installed and the `dotnet` command available in your PATH. +REM 3. Run the script by double-clicking it or executing it from the command line. + +echo Starting Azurite... +start /B azurite -s -l c:\azurite -d c:\azurite\debug.log +pause diff --git a/samples/sharedcontent/run-azurite.sh b/samples/sharedcontent/run-azurite.sh new file mode 100644 index 0000000..f0939ee --- /dev/null +++ b/samples/sharedcontent/run-azurite.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Instructions to run this script: +# 1. Make sure you have Azurite installed. You can install it using npm: +# npm install -g azurite +# 2. Make sure you have the .NET SDK installed and the `dotnet` command available in your PATH. +# 3. Give execution permissions to this file with the following command: +# chmod +x run-test.sh +# 4. Run the script with the following command: +# ./run-test.sh + +echo "Starting Azurite..." +azurite -s -l /path/to/azurite -d /path/to/azurite/debug.log & + +echo "Running tests..." +dotnet test diff --git a/src/AzureStorageWrapper.Tests/AzureStorageWrapper.Tests.csproj b/src/AzureStorageWrapper.Tests/AzureStorageWrapper.Tests.csproj new file mode 100644 index 0000000..41ba6e3 --- /dev/null +++ b/src/AzureStorageWrapper.Tests/AzureStorageWrapper.Tests.csproj @@ -0,0 +1,30 @@ + + + + net9.0 + latest + enable + enable + false + 4125ba48-a89c-4eba-989b-dab2cbd677c4 + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/BaseShould.cs b/src/AzureStorageWrapper.Tests/Should/BaseShould.cs similarity index 100% rename from src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/BaseShould.cs rename to src/AzureStorageWrapper.Tests/Should/BaseShould.cs diff --git a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Delete/DeleteBlobShould.cs b/src/AzureStorageWrapper.Tests/Should/Delete/DeleteBlobShould.cs similarity index 60% rename from src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Delete/DeleteBlobShould.cs rename to src/AzureStorageWrapper.Tests/Should/Delete/DeleteBlobShould.cs index 5c91ce4..0bf8543 100644 --- a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Delete/DeleteBlobShould.cs +++ b/src/AzureStorageWrapper.Tests/Should/Delete/DeleteBlobShould.cs @@ -1,4 +1,4 @@ -using AzureStorageWrapper.Commands; +using AzureStorageWrapper.Commands; using Xunit; namespace AzureStorageWrapper.Tests.Should.Delete @@ -43,5 +43,32 @@ public async Task DeleteBlob_ShouldDeleteBlob() Assert.False(await PingAsync(response.SasUri)); } + + [Fact] + public async Task DeleteBlob_Uri_ShouldDeleteBlob() + { + var base64 = "SGVsbG8g8J+Zgg=="; + + var uploadCommand = new UploadBase64() + { + Base64 = base64, + Container = "files", + Name = "hello", + Extension = "md", + Metadata = new Dictionary() + {{"hello", "world"}} + }; + + var response = await _azureStorageWrapper.UploadBlobAsync(uploadCommand); + + Assert.NotNull(response); + + Assert.True(await PingAsync(response.SasUri)); + + await _azureStorageWrapper.DeleteBlobAsync(response.Uri); + + Assert.False(await PingAsync(response.SasUri)); + + } } -} \ No newline at end of file +} diff --git a/src/AzureStorageWrapper.Tests/Should/DependencyInjection/DependencyInjectionShould.cs b/src/AzureStorageWrapper.Tests/Should/DependencyInjection/DependencyInjectionShould.cs new file mode 100644 index 0000000..dc65668 --- /dev/null +++ b/src/AzureStorageWrapper.Tests/Should/DependencyInjection/DependencyInjectionShould.cs @@ -0,0 +1,102 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace AzureStorageWrapper.Tests +{ + public class DependencyInjectionTests + { + [Fact] + public void AddAzureStorageWrapper_WithDefaultParameters_ShouldConfigureServices() + { + // Arrange + var services = new ServiceCollection(); + Environment.SetEnvironmentVariable("StorageWrapper_ConnectionString", "DefaultConnectionString"); + Environment.SetEnvironmentVariable("StorageWrapper_DefaultContainer", "DefaultContainer"); + + // Act + services.AddAzureStorageWrapper(); + + // Assert + var serviceProvider = services.BuildServiceProvider(); + var options = serviceProvider.GetService(); + Assert.NotNull(options); + Assert.Equal("DefaultConnectionString", options.ConnectionString); + Assert.Equal("DefaultContainer", options.DefaultContainer); + } + + [Fact] + public void AddAzureStorageWrapper_WithConnectionStringAndContainer_ShouldConfigureServices() + { + // Arrange + var services = new ServiceCollection(); + var connectionString = "TestConnectionString"; + var defaultContainer = "TestContainer"; + + // Act + services.AddAzureStorageWrapper(connectionString, defaultContainer); + + // Assert + var serviceProvider = services.BuildServiceProvider(); + var options = serviceProvider.GetService(); + Assert.NotNull(options); + Assert.Equal(connectionString, options.ConnectionString); + Assert.Equal(defaultContainer, options.DefaultContainer); + } + + [Fact] + public void AddAzureStorageWrapper_WithOptions_ShouldConfigureServices() + { + // Arrange + var services = new ServiceCollection(); + var options = new AzureStorageWrapperOptions + { + ConnectionString = "TestConnectionString", + DefaultContainer = "TestContainer", + MaxSasUriExpiration = 600, + DefaultSasUriExpiration = 300, + CreateContainerIfNotExists = true + }; + + // Act + services.AddAzureStorageWrapper(options); + + // Assert + var serviceProvider = services.BuildServiceProvider(); + var resolvedOptions = serviceProvider.GetService(); + Assert.NotNull(resolvedOptions); + Assert.Equal(options.ConnectionString, resolvedOptions.ConnectionString); + Assert.Equal(options.DefaultContainer, resolvedOptions.DefaultContainer); + Assert.Equal(options.MaxSasUriExpiration, resolvedOptions.MaxSasUriExpiration); + Assert.Equal(options.DefaultSasUriExpiration, resolvedOptions.DefaultSasUriExpiration); + Assert.Equal(options.CreateContainerIfNotExists, resolvedOptions.CreateContainerIfNotExists); + } + + [Fact] + public void AddAzureStorageWrapper_WithOptionsAction_ShouldConfigureServices() + { + // Arrange + var services = new ServiceCollection(); + + // Act + services.AddAzureStorageWrapper(options => + { + options.ConnectionString = "TestConnectionString"; + options.DefaultContainer = "TestContainer"; + options.MaxSasUriExpiration = 600; + options.DefaultSasUriExpiration = 300; + options.CreateContainerIfNotExists = true; + }); + + // Assert + var serviceProvider = services.BuildServiceProvider(); + var options = serviceProvider.GetService(); + Assert.NotNull(options); + Assert.Equal("TestConnectionString", options.ConnectionString); + Assert.Equal("TestContainer", options.DefaultContainer); + Assert.Equal(600, options.MaxSasUriExpiration); + Assert.Equal(300, options.DefaultSasUriExpiration); + Assert.True(options.CreateContainerIfNotExists); + } + } +} diff --git a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Download/DownloadBlobReferenceShould.cs b/src/AzureStorageWrapper.Tests/Should/Download/DownloadBlobReferenceShould.cs similarity index 86% rename from src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Download/DownloadBlobReferenceShould.cs rename to src/AzureStorageWrapper.Tests/Should/Download/DownloadBlobReferenceShould.cs index 612031d..aa61a52 100644 --- a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Download/DownloadBlobReferenceShould.cs +++ b/src/AzureStorageWrapper.Tests/Should/Download/DownloadBlobReferenceShould.cs @@ -1,4 +1,4 @@ -using AzureStorageWrapper.Commands; +using AzureStorageWrapper.Commands; using AzureStorageWrapper.Exceptions; using AzureStorageWrapper.Queries; using AzureStorageWrapper.Tests.Sources; @@ -176,7 +176,34 @@ await Assert.ThrowsAsync(async () => _ = await _azureStorageWrapper.DownloadBlobReferenceAsync(command); }); } - - + + + [Fact] + public async Task DownloadBlobReference_Uri_Should_ReturnReference() + { + // Arrange + + var base64 = "SGVsbG8g8J+Zgg=="; + + var uploadBlobCommand = new UploadBase64() + { + Base64 = base64, + Container = "files", + Name = "hello", + Extension = "md", + Metadata = new Dictionary() + {{"hello", "world"}} + }; + + var uploadBlobResponse = await _azureStorageWrapper.UploadBlobAsync(uploadBlobCommand); + + // Act + var blobReference = await _azureStorageWrapper.DownloadBlobReferenceAsync(uploadBlobResponse.Uri); + + // Assert + Assert.NotNull(blobReference); + Assert.True(await PingAsync(blobReference.SasUri)); + } + } -} \ No newline at end of file +} diff --git a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Download/DownloadBlobStreamShould.cs b/src/AzureStorageWrapper.Tests/Should/Download/DownloadBlobStreamShould.cs similarity index 73% rename from src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Download/DownloadBlobStreamShould.cs rename to src/AzureStorageWrapper.Tests/Should/Download/DownloadBlobStreamShould.cs index c8ebbc3..84a99fe 100644 --- a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Download/DownloadBlobStreamShould.cs +++ b/src/AzureStorageWrapper.Tests/Should/Download/DownloadBlobStreamShould.cs @@ -1,4 +1,5 @@ -using AzureStorageWrapper.Commands; +using Azure; +using AzureStorageWrapper.Commands; using AzureStorageWrapper.Exceptions; using AzureStorageWrapper.Queries; using AzureStorageWrapper.Tests.Sources; @@ -57,8 +58,36 @@ public async Task DownloadBlob_Should_ReturnBlob() Assert.NotNull(response.Stream); Assert.True(response.Stream.Length > 0); } - - + + [Fact] + public async Task DownloadBlob_Uri_Should_ReturnBlob() + { + // Arrange + + var base64 = "SGVsbG8g8J+Zgg=="; + + var uploadBlobCommand = new UploadBase64() + { + Base64 = base64, + Container = "files", + Name = "hello", + Extension = "md", + Metadata = new Dictionary() + {{"hello", "world"}} + }; + + var uploadBlobResponse = await _azureStorageWrapper.UploadBlobAsync(uploadBlobCommand); + + // Act + var response = await _azureStorageWrapper.DownloadBlobAsync(uploadBlobResponse.Uri); + + // Assert + Assert.NotNull(response); + + Assert.NotNull(response.Stream); + Assert.True(response.Stream.Length > 0); + } + // [Fact] // public async Task DownloadBlob_WithInvalidUri_Should_ReturnBlob() // { @@ -81,4 +110,4 @@ public async Task DownloadBlob_Should_ReturnBlob() // }); // } } -} \ No newline at end of file +} diff --git a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Download/DownloadBlobUriVariationsShould.cs b/src/AzureStorageWrapper.Tests/Should/Download/DownloadBlobUriVariationsShould.cs similarity index 98% rename from src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Download/DownloadBlobUriVariationsShould.cs rename to src/AzureStorageWrapper.Tests/Should/Download/DownloadBlobUriVariationsShould.cs index 77785fe..cad03fb 100644 --- a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Download/DownloadBlobUriVariationsShould.cs +++ b/src/AzureStorageWrapper.Tests/Should/Download/DownloadBlobUriVariationsShould.cs @@ -1,4 +1,4 @@ -using AzureStorageWrapper.Commands; +using AzureStorageWrapper.Commands; using AzureStorageWrapper.Queries; using AzureStorageWrapper.Tests.Sources; using Xunit; @@ -84,6 +84,5 @@ public async Task DownloadBlob_WithBlanksFileName_Should_ReturnFileReference() Assert.True(await PingAsync(response.SasUri)); } - } -} \ No newline at end of file +} diff --git a/src/AzureStorageWrapper.Tests/Should/Enumerate/EnumerateBlobsShould.cs b/src/AzureStorageWrapper.Tests/Should/Enumerate/EnumerateBlobsShould.cs new file mode 100644 index 0000000..16b64f7 --- /dev/null +++ b/src/AzureStorageWrapper.Tests/Should/Enumerate/EnumerateBlobsShould.cs @@ -0,0 +1,289 @@ +using System.ComponentModel.DataAnnotations; +using AzureStorageWrapper.Commands; +using AzureStorageWrapper.Exceptions; +using AzureStorageWrapper.Queries; +using Xunit; +using Xunit.Abstractions; + +namespace AzureStorageWrapper.Tests.Should.Enumerate +{ + public class EnumerateBlobsShould : BaseShould + { + private readonly IAzureStorageWrapper _azureStorageWrapper; + private readonly ITestOutputHelper _output; + + public EnumerateBlobsShould(IAzureStorageWrapper azureStorageWrapper, ITestOutputHelper output) + { + _azureStorageWrapper = azureStorageWrapper; + _output = output; + } + + [Fact] + public async Task EnumerateBlobs_WithoutPagination_Should_ReturnAllBlobsFromContainer() + { + var amount = 10; + var container = "without-pagination"; + + await UploadFilesAsync(amount, container); + + var query = new EnumerateBlobs() + { + Container = container, + Paginate = false + }; + + var references = await _azureStorageWrapper.EnumerateBlobsAsync(query); + + _output.WriteLine($"Enumerating {references.References.Count()} references"); + + Assert.True(references.References.Any()); + Assert.True(references.References.Count() >= amount); + + foreach (var reference in references.References) + { + await _azureStorageWrapper.DeleteBlobAsync(new DeleteBlob() { Uri = reference.Uri }); + } + } + + [Fact] + public async Task EnumerateBlobs_WithContinuationToken_ShouldReturnBlobsPageByPage() + { + var amount = 20; + var size = 10; + var container = "pagination"; + + await UploadFilesAsync(amount, container); + + var firstIterationReferences = await _azureStorageWrapper.EnumerateBlobsAsync(new EnumerateBlobs() + { + Container = container, + Paginate = true, + Size = size, + }); + + _output.WriteLine($"Enumerating {firstIterationReferences.References.Count()} references"); + + Assert.True(firstIterationReferences.References.Any()); + + var secondIterationReferences = await _azureStorageWrapper.EnumerateBlobsAsync(new EnumerateBlobs() + { + Container = container, + Paginate = true, + Size = size, + ContinuationToken = firstIterationReferences.ContinuationToken + }); + + _output.WriteLine($"Enumerating {secondIterationReferences.References.Count()} references"); + + Assert.True(secondIterationReferences.References.Any()); + + foreach (var reference in firstIterationReferences.References) + { + await _azureStorageWrapper.DeleteBlobAsync(new DeleteBlob() { Uri = reference.Uri }); + } + + foreach (var reference in secondIterationReferences.References) + { + await _azureStorageWrapper.DeleteBlobAsync(new DeleteBlob() { Uri = reference.Uri }); + } + } + + private async Task UploadFilesAsync(int amount, string container) + { + for (var i = 0; i < amount; i++) + { + await _azureStorageWrapper.UploadBlobAsync(new UploadBase64() + { + Base64 = "SGVsbG8g8J+Zgg==", + Container = container, + Name = "hello", + Extension = "md", + Metadata = new Dictionary() + {{"hello", "world"}} + }); + } + } + + + [Fact] + public async Task EnumerateBlobs_EmptyDefaultContainer_Should_ThrowException() + { + // Arrange + var amount = 10; + var container = "without-pagination"; + + await UploadFilesAsync(amount, container); + + var options = new AzureStorageWrapperOptions + { + ConnectionString = "UseDevelopmentStorage=true", + DefaultContainer = string.Empty, // Set DefaultContainer to empty + MaxSasUriExpiration = 600, + DefaultSasUriExpiration = 300, + CreateContainerIfNotExists = true + }; + var azureStorageWrapper = new AzureStorageWrapper(options); + + // Act and Assert + await Assert.ThrowsAsync(async () => + { + var _ = await azureStorageWrapper.EnumerateBlobsAsync(); + }); + } + [Fact] + public async Task EnumerateBlobs_DefaultContainer_Should_AllBlobsFromContainer() + { + // Arrange + var amount = 10; + var container = Startup.DefaultContainer; + + await UploadFilesAsync(amount, container); + + // Act + var references = await _azureStorageWrapper.EnumerateBlobsAsync(); + + // Assert + _output.WriteLine($"Enumerating {references.References.Count()} references"); + + Assert.True(references.References.Any()); + Assert.True(references.References.Count() >= amount); + + foreach (var reference in references.References) + { + await _azureStorageWrapper.DeleteBlobAsync(new DeleteBlob() { Uri = reference.Uri }); + } + } + [Fact] + public async Task EnumerateBlobs_CustomContainer_Should_AllBlobsFromContainer() + { + // Arrange + var amount = 10; + var container = "without-pagination"; + + await UploadFilesAsync(amount, container); + + // Act + var references = await _azureStorageWrapper.EnumerateBlobsAsync(container); + + // Assert + _output.WriteLine($"Enumerating {references.References.Count()} references"); + + Assert.True(references.References.Any()); + Assert.True(references.References.Count() >= amount); + + foreach (var reference in references.References) + { + await _azureStorageWrapper.DeleteBlobAsync(new DeleteBlob() { Uri = reference.Uri }); + } + } + + + [Fact] + public async Task EnumerateBlobs_PaginateSize_EmptyDefaultContainer_Should_ThrowException() + { + // Arrange + var amount = 20; + var size = 10; + var container = "pagination"; + + await UploadFilesAsync(amount, container); + + var options = new AzureStorageWrapperOptions + { + ConnectionString = "UseDevelopmentStorage=true", + DefaultContainer = string.Empty, // Set DefaultContainer to empty + MaxSasUriExpiration = 600, + DefaultSasUriExpiration = 300, + CreateContainerIfNotExists = true + }; + var azureStorageWrapper = new AzureStorageWrapper(options); + + // Act and Assert + await Assert.ThrowsAsync(async () => + { + var _ = await azureStorageWrapper.EnumerateBlobsAsync(); + }); + } + + [Fact] + public async Task EnumerateBlobs_PaginateSize_DefaultContainer_Should_ReturnBlobsPageByPage() + { + // Arrange + var amount = 20; + var size = 10; + var container = Startup.DefaultContainer; + + await UploadFilesAsync(amount, container); + + // Act + var firstIterationReferences = await _azureStorageWrapper.EnumerateBlobsAsync(size); + + // Assert + _output.WriteLine($"Enumerating {firstIterationReferences.References.Count()} references"); + + Assert.True(firstIterationReferences.References.Any()); + + var secondIterationReferences = await _azureStorageWrapper.EnumerateBlobsAsync(new EnumerateBlobs() + { + Container = container, + Paginate = true, + Size = size, + ContinuationToken = firstIterationReferences.ContinuationToken + }); + + _output.WriteLine($"Enumerating {secondIterationReferences.References.Count()} references"); + + Assert.True(secondIterationReferences.References.Any()); + + foreach (var reference in firstIterationReferences.References) + { + await _azureStorageWrapper.DeleteBlobAsync(new DeleteBlob() { Uri = reference.Uri }); + } + + foreach (var reference in secondIterationReferences.References) + { + await _azureStorageWrapper.DeleteBlobAsync(new DeleteBlob() { Uri = reference.Uri }); + } + } + [Fact] + public async Task EnumerateBlobs_PaginateSize_CustomContainer_Should_ReturnBlobsPageByPage() + { + // Arrange + var amount = 20; + var size = 10; + var container = "without-pagination"; + + await UploadFilesAsync(amount, container); + + // Act + var firstIterationReferences = await _azureStorageWrapper.EnumerateBlobsAsync(size, container); + + // Assert + _output.WriteLine($"Enumerating {firstIterationReferences.References.Count()} references"); + + Assert.True(firstIterationReferences.References.Any()); + + var secondIterationReferences = await _azureStorageWrapper.EnumerateBlobsAsync(new EnumerateBlobs() + { + Container = container, + Paginate = true, + Size = size, + ContinuationToken = firstIterationReferences.ContinuationToken + }); + + _output.WriteLine($"Enumerating {secondIterationReferences.References.Count()} references"); + + Assert.True(secondIterationReferences.References.Any()); + + foreach (var reference in firstIterationReferences.References) + { + await _azureStorageWrapper.DeleteBlobAsync(new DeleteBlob() { Uri = reference.Uri }); + } + + foreach (var reference in secondIterationReferences.References) + { + await _azureStorageWrapper.DeleteBlobAsync(new DeleteBlob() { Uri = reference.Uri }); + } + } + } +} diff --git a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Upload/DiacriticsShould.cs b/src/AzureStorageWrapper.Tests/Should/Upload/DiacriticsShould.cs similarity index 100% rename from src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Upload/DiacriticsShould.cs rename to src/AzureStorageWrapper.Tests/Should/Upload/DiacriticsShould.cs diff --git a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Upload/MetadataShould.cs b/src/AzureStorageWrapper.Tests/Should/Upload/MetadataShould.cs similarity index 100% rename from src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Upload/MetadataShould.cs rename to src/AzureStorageWrapper.Tests/Should/Upload/MetadataShould.cs diff --git a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Upload/UploadBase64ImageShould.cs b/src/AzureStorageWrapper.Tests/Should/Upload/UploadBase64ImageShould.cs similarity index 100% rename from src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Upload/UploadBase64ImageShould.cs rename to src/AzureStorageWrapper.Tests/Should/Upload/UploadBase64ImageShould.cs diff --git a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Upload/UploadBase64Should.cs b/src/AzureStorageWrapper.Tests/Should/Upload/UploadBase64Should.cs similarity index 67% rename from src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Upload/UploadBase64Should.cs rename to src/AzureStorageWrapper.Tests/Should/Upload/UploadBase64Should.cs index 501fb18..6b970c7 100644 --- a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Upload/UploadBase64Should.cs +++ b/src/AzureStorageWrapper.Tests/Should/Upload/UploadBase64Should.cs @@ -1,4 +1,5 @@ -using AzureStorageWrapper.Commands; +using Azure; +using AzureStorageWrapper.Commands; using AzureStorageWrapper.Exceptions; using Xunit; @@ -146,5 +147,63 @@ public async Task UploadBlob_WithBlankSpacesInName_Should_UploadBlob() Assert.True(await PingAsync(response.SasUri)); } + + + [Fact] + public async Task UploadBlobBase64_File_Content_EmptyDefaultContainer_Should_ThrowException() + { + var base64 = string.Empty; + // Arrange + var options = new AzureStorageWrapperOptions + { + ConnectionString = "UseDevelopmentStorage=true", + DefaultContainer = string.Empty, // Set DefaultContainer to empty + MaxSasUriExpiration = 600, + DefaultSasUriExpiration = 300, + CreateContainerIfNotExists = true + }; + var azureStorageWrapper = new AzureStorageWrapper(options); + var file = "hello.md"; + var contentBase64 = base64; + + // Act and Assert + await Assert.ThrowsAsync(async () => + { + _ = await azureStorageWrapper.UploadBlobAsync(file, contentBase64); + }); + } + [Fact] + public async Task UploadBlobBase64_File_Content_DefaultContainer_Should_UploadBlob() + { + var base64 = "SGVsbG8g8J+Zgg=="; + + // Arrange + var file = "hello.md"; + var contentBase64 = base64; + + // Act and Assert + var response = await _azureStorageWrapper.UploadBlobAsync(file, contentBase64); + + // Assert + Assert.NotNull(response); + Assert.True(await PingAsync(response.SasUri)); + } + [Fact] + public async Task UploadBlobBase64_File_Content_CustomContainer_Should_UploadBlob() + { + var base64 = "SGVsbG8g8J+Zgg=="; + + // Arrange + var file = "hello.md"; + var contentBase64 = base64; + var container = "files"; + + // Act and Assert + var response = await _azureStorageWrapper.UploadBlobAsync(file, contentBase64, container); + + // Assert + Assert.NotNull(response); + Assert.True(await PingAsync(response.SasUri)); + } } -} \ No newline at end of file +} diff --git a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Upload/UploadBytesShould.cs b/src/AzureStorageWrapper.Tests/Should/Upload/UploadBytesShould.cs similarity index 56% rename from src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Upload/UploadBytesShould.cs rename to src/AzureStorageWrapper.Tests/Should/Upload/UploadBytesShould.cs index 859a653..228882d 100644 --- a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Upload/UploadBytesShould.cs +++ b/src/AzureStorageWrapper.Tests/Should/Upload/UploadBytesShould.cs @@ -1,4 +1,4 @@ -using AzureStorageWrapper.Commands; +using AzureStorageWrapper.Commands; using AzureStorageWrapper.Exceptions; using Xunit; @@ -92,5 +92,62 @@ await Assert.ThrowsAsync(async () => }); } + + [Fact] + public async Task UploadBlobBytes_File_Content_EmptyDefaultContainer_Should_ThrowException() + { + var bytes = Convert.FromBase64String("SGVsbG8g8J+Zgg=="); + // Arrange + var options = new AzureStorageWrapperOptions + { + ConnectionString = "UseDevelopmentStorage=true", + DefaultContainer = string.Empty, // Set DefaultContainer to empty + MaxSasUriExpiration = 600, + DefaultSasUriExpiration = 300, + CreateContainerIfNotExists = true + }; + var azureStorageWrapper = new AzureStorageWrapper(options); + var file = "hello.md"; + var contentBytes = bytes; + + // Act and Assert + await Assert.ThrowsAsync(async () => + { + _ = await azureStorageWrapper.UploadBlobAsync(file, contentBytes); + }); + } + [Fact] + public async Task UploadBlobBytes_File_Content_DefaultContainer_Should_UploadBlob() + { + var bytes = Convert.FromBase64String("SGVsbG8g8J+Zgg=="); + + // Arrange + var file = "hello.md"; + var contentBytes = bytes; + + // Act and Assert + var response = await _azureStorageWrapper.UploadBlobAsync(file, contentBytes); + + // Assert + Assert.NotNull(response); + Assert.True(await PingAsync(response.SasUri)); + } + [Fact] + public async Task UploadBlobBytes_File_Content_CustomContainer_Should_UploadBlob() + { + var bytes = Convert.FromBase64String("SGVsbG8g8J+Zgg=="); + + // Arrange + var file = "hello.md"; + var contentBytes = bytes; + var container = "files"; + + // Act and Assert + var response = await _azureStorageWrapper.UploadBlobAsync(file, contentBytes, container); + + // Assert + Assert.NotNull(response); + Assert.True(await PingAsync(response.SasUri)); + } } -} \ No newline at end of file +} diff --git a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Upload/UploadInVirtualFolderShould.cs b/src/AzureStorageWrapper.Tests/Should/Upload/UploadInVirtualFolderShould.cs similarity index 100% rename from src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Upload/UploadInVirtualFolderShould.cs rename to src/AzureStorageWrapper.Tests/Should/Upload/UploadInVirtualFolderShould.cs diff --git a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Upload/UploadStreamShould.cs b/src/AzureStorageWrapper.Tests/Should/Upload/UploadStreamShould.cs similarity index 56% rename from src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Upload/UploadStreamShould.cs rename to src/AzureStorageWrapper.Tests/Should/Upload/UploadStreamShould.cs index 93d7cb6..55cb4f2 100644 --- a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Upload/UploadStreamShould.cs +++ b/src/AzureStorageWrapper.Tests/Should/Upload/UploadStreamShould.cs @@ -1,4 +1,4 @@ -using AzureStorageWrapper.Commands; +using AzureStorageWrapper.Commands; using AzureStorageWrapper.Exceptions; using Xunit; @@ -90,8 +90,64 @@ await Assert.ThrowsAsync(async () => _ = await _azureStorageWrapper.UploadBlobAsync(command); }); } - - + + [Fact] + public async Task UploadBlobStream_File_Content_EmptyDefaultContainer_Should_ThrowException() + { + var stream = new MemoryStream(Convert.FromBase64String("SGVsbG8g8J+Zgg==")); + + // Arrange + var options = new AzureStorageWrapperOptions + { + ConnectionString = "UseDevelopmentStorage=true", + DefaultContainer = string.Empty, // Set DefaultContainer to empty + MaxSasUriExpiration = 600, + DefaultSasUriExpiration = 300, + CreateContainerIfNotExists = true + }; + var azureStorageWrapper = new AzureStorageWrapper(options); + var file = "hello.md"; + var contentStream = stream; + + // Act and Assert + await Assert.ThrowsAsync(async () => + { + _ = await azureStorageWrapper.UploadBlobAsync(file, contentStream); + }); + } + [Fact] + public async Task UploadBlobStream_File_Content_DefaultContainer_Should_UploadBlob() + { + var stream = new MemoryStream(Convert.FromBase64String("SGVsbG8g8J+Zgg==")); + + // Arrange + var file = "hello.md"; + var contentStream = stream; + + // Act and Assert + var response = await _azureStorageWrapper.UploadBlobAsync(file, contentStream); + + // Assert + Assert.NotNull(response); + Assert.True(await PingAsync(response.SasUri)); + } + [Fact] + public async Task UploadBlobStream_File_Content_CustomContainer_Should_UploadBlob() + { + var stream = new MemoryStream(Convert.FromBase64String("SGVsbG8g8J+Zgg==")); + + // Arrange + var file = "hello.md"; + var contentStream = stream; + var container = "files"; + + // Act and Assert + var response = await _azureStorageWrapper.UploadBlobAsync(file, contentStream, container); + + // Assert + Assert.NotNull(response); + Assert.True(await PingAsync(response.SasUri)); + } } -} \ No newline at end of file +} diff --git a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Sources/Images.cs b/src/AzureStorageWrapper.Tests/Sources/Images.cs similarity index 100% rename from src/AzureStorageWrapper/AzureStorageWrapper.Tests/Sources/Images.cs rename to src/AzureStorageWrapper.Tests/Sources/Images.cs diff --git a/src/AzureStorageWrapper.Tests/Startup.cs b/src/AzureStorageWrapper.Tests/Startup.cs new file mode 100644 index 0000000..6af90cd --- /dev/null +++ b/src/AzureStorageWrapper.Tests/Startup.cs @@ -0,0 +1,21 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +namespace AzureStorageWrapper.Tests +{ + public class Startup + { + public const string DefaultContainer = "default-files"; + public void ConfigureServices(IServiceCollection serviceCollection) + { + serviceCollection.AddAzureStorageWrapper(options => + { + options.ConnectionString = "UseDevelopmentStorage=true"; + options.MaxSasUriExpiration = 360; + options.DefaultSasUriExpiration = 360; + options.CreateContainerIfNotExists = true; + options.DefaultContainer = DefaultContainer; + }); + } + } +} diff --git a/src/AzureStorageWrapper.Tests/run-test.bat b/src/AzureStorageWrapper.Tests/run-test.bat new file mode 100644 index 0000000..0e1e40b --- /dev/null +++ b/src/AzureStorageWrapper.Tests/run-test.bat @@ -0,0 +1,18 @@ +@echo off + +REM Instructions to run this script: +REM 1. Make sure you have Azurite installed. You can install it using npm: +REM npm install -g azurite +REM 2. Make sure you have the .NET SDK installed and the `dotnet` command available in your PATH. +REM 3. Run the script by double-clicking it or executing it from the command line. + +echo Starting Azurite... +start /B azurite -s -l c:\azurite -d c:\azurite\debug.log + +REM Wait for a few seconds to ensure Azurite has started +timeout /t 5 /nobreak > NUL + +echo Running tests... +dotnet test + +pause diff --git a/src/AzureStorageWrapper.Tests/run-test.sh b/src/AzureStorageWrapper.Tests/run-test.sh new file mode 100644 index 0000000..f0939ee --- /dev/null +++ b/src/AzureStorageWrapper.Tests/run-test.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Instructions to run this script: +# 1. Make sure you have Azurite installed. You can install it using npm: +# npm install -g azurite +# 2. Make sure you have the .NET SDK installed and the `dotnet` command available in your PATH. +# 3. Give execution permissions to this file with the following command: +# chmod +x run-test.sh +# 4. Run the script with the following command: +# ./run-test.sh + +echo "Starting Azurite..." +azurite -s -l /path/to/azurite -d /path/to/azurite/debug.log & + +echo "Running tests..." +dotnet test diff --git a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/AzureStorageWrapper.Tests.csproj b/src/AzureStorageWrapper/AzureStorageWrapper.Tests/AzureStorageWrapper.Tests.csproj deleted file mode 100644 index 7a60451..0000000 --- a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/AzureStorageWrapper.Tests.csproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - net8.0 - enable - enable - 4125ba48-a89c-4eba-989b-dab2cbd677c4 - - - - - - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - diff --git a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Enumerate/EnumerateBlobsShould.cs b/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Enumerate/EnumerateBlobsShould.cs deleted file mode 100644 index 039837f..0000000 --- a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Should/Enumerate/EnumerateBlobsShould.cs +++ /dev/null @@ -1,105 +0,0 @@ -using AzureStorageWrapper.Commands; -using AzureStorageWrapper.Queries; -using Xunit; -using Xunit.Abstractions; - -namespace AzureStorageWrapper.Tests.Should.Enumerate -{ - public class EnumerateBlobsShould : BaseShould - { - private readonly IAzureStorageWrapper _azureStorageWrapper; - private readonly ITestOutputHelper _output; - - public EnumerateBlobsShould(IAzureStorageWrapper azureStorageWrapper, ITestOutputHelper output) - { - _azureStorageWrapper = azureStorageWrapper; - _output = output; - } - - [Fact] - public async Task EnumerateBlobs_WithoutPagination_Should_ReturnAllBlobsFromContainer() - { - var amount = 10; - var container = "without-pagination"; - - await UploadFilesAsync(amount, container); - - var query = new EnumerateBlobs() - { - Container = container, - Paginate = false - }; - - var references = await _azureStorageWrapper.EnumerateBlobsAsync(query); - - _output.WriteLine($"Enumerating {references.References.Count()} references"); - - Assert.True(references.References.Any()); - Assert.True(references.References.Count() >= amount); - - foreach (var reference in references.References) - { - await _azureStorageWrapper.DeleteBlobAsync(new DeleteBlob() { Uri = reference.Uri }); - } - } - - [Fact] - public async Task EnumerateBlobs_WithContinuationToken_ShouldReturnBlobsPageByPage() - { - var amount = 20; - var size = 10; - var container = "pagination"; - - await UploadFilesAsync(amount, container); - - var firstIterationReferences = await _azureStorageWrapper.EnumerateBlobsAsync(new EnumerateBlobs() - { - Container = container, - Paginate = true, - Size = size, - }); - - _output.WriteLine($"Enumerating {firstIterationReferences.References.Count()} references"); - - Assert.True(firstIterationReferences.References.Any()); - - var secondIterationReferences = await _azureStorageWrapper.EnumerateBlobsAsync(new EnumerateBlobs() - { - Container = container, - Paginate = true, - Size = size, - ContinuationToken = firstIterationReferences.ContinuationToken - }); - - _output.WriteLine($"Enumerating {secondIterationReferences.References.Count()} references"); - - Assert.True(secondIterationReferences.References.Any()); - - foreach (var reference in firstIterationReferences.References) - { - await _azureStorageWrapper.DeleteBlobAsync(new DeleteBlob() { Uri = reference.Uri }); - } - - foreach (var reference in secondIterationReferences.References) - { - await _azureStorageWrapper.DeleteBlobAsync(new DeleteBlob() { Uri = reference.Uri }); - } - } - - private async Task UploadFilesAsync(int amount, string container) - { - for (var i = 0; i < amount; i++) - { - await _azureStorageWrapper.UploadBlobAsync(new UploadBase64() - { - Base64 = "SGVsbG8g8J+Zgg==", - Container = container, - Name = "hello", - Extension = "md", - Metadata = new Dictionary() - {{"hello", "world"}} - }); - } - } - } -} \ No newline at end of file diff --git a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Startup.cs b/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Startup.cs deleted file mode 100644 index 3c4c40b..0000000 --- a/src/AzureStorageWrapper/AzureStorageWrapper.Tests/Startup.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; - -namespace AzureStorageWrapper.Tests -{ - public class Startup - { - public void ConfigureServices(IServiceCollection serviceCollection) - { - serviceCollection.AddAzureStorageWrapper(configuration => - { - configuration.ConnectionString = "UseDevelopmentStorage=true"; - configuration.MaxSasUriExpiration = 360; - configuration.DefaultSasUriExpiration = 360; - configuration.CreateContainerIfNotExists = true; - }); - } - } -} diff --git a/src/AzureStorageWrapper/AzureStorageWrapper/AzureStorageWrapper.cs b/src/AzureStorageWrapper/AzureStorageWrapper.cs similarity index 52% rename from src/AzureStorageWrapper/AzureStorageWrapper/AzureStorageWrapper.cs rename to src/AzureStorageWrapper/AzureStorageWrapper.cs index e2215e2..a11b15a 100644 --- a/src/AzureStorageWrapper/AzureStorageWrapper/AzureStorageWrapper.cs +++ b/src/AzureStorageWrapper/AzureStorageWrapper.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -10,50 +10,92 @@ using Azure.Storage.Blobs; using Azure.Storage.Sas; using AzureStorageWrapper.Commands; -using AzureStorageWrapper.Exceptions; +using AzureStorageWrapper.Extensions; using AzureStorageWrapper.Queries; using AzureStorageWrapper.Responses; +using EnsureThat; namespace AzureStorageWrapper { + /// + /// Provides methods to interact with Azure Storage. + /// public class AzureStorageWrapper : AzureStorageWrapperBase, IAzureStorageWrapper { - private readonly AzureStorageWrapperConfiguration _configuration; + private readonly AzureStorageWrapperOptions _options; - public AzureStorageWrapper(AzureStorageWrapperConfiguration configuration) + /// + /// Initializes a new instance of the class. + /// + /// The options for configuring the Azure Storage Wrapper. + public AzureStorageWrapper(AzureStorageWrapperOptions options) + => _options = options; + + #region UploadBlobs + + /// + public async Task UploadBlobAsync(string file, Stream content, string container = null) + => await UploadBlobImplAsync(file, new UploadStream { Stream = content, Container = container }); + + /// + public async Task UploadBlobAsync(string file, byte[] content, string container = null) + => await UploadBlobImplAsync(file, new UploadBytes { Bytes = content, Container = container }); + + /// + public async Task UploadBlobAsync(string file, string contentBase64, string container = null) + => await UploadBlobImplAsync(file, new UploadBase64 { Base64 = contentBase64, Container = container }); + + /// + /// Implements the logic for uploading a blob. + /// + /// The type of the upload command. + /// The name of the file. + /// The upload command. + /// A task that represents the asynchronous operation. The task result contains the blob reference. + private async Task UploadBlobImplAsync(string file, T command) where T : UploadBlob { - _configuration = configuration; + if (string.IsNullOrEmpty(command.Container)) + { + Ensure.String.IsNotNullOrEmptySW(_options.DefaultContainer); + command.Container = _options.DefaultContainer; + } + + command.Name = Path.GetFileNameWithoutExtension(file); + command.Extension = Path.GetExtension(file); + command.UseVirtualFolder = false; + + return await UploadBlobAsync(command); } + /// public async Task UploadBlobAsync(UploadBlob command) { command.Validate(); - - var container = new BlobContainerClient(_configuration.ConnectionString, command.Container); - + + var container = new BlobContainerClient(_options.ConnectionString, command.Container); + if (!await container.ExistsAsync()) { - if (_configuration.CreateContainerIfNotExists) await container.CreateIfNotExistsAsync(); - - else throw new AzureStorageWrapperException($"container {command.Container} doesn't exists!"); + Ensure.Bool.IsNotExistContainer(_options.CreateContainerIfNotExists, command.Container); + await container.CreateIfNotExistsAsync(); } var blobName = command.UseVirtualFolder ? $"{GetRandomId()}/{command.Name}.{command.Extension}" : $"{command.Name}.{command.Extension}"; - + var blob = container.GetBlobClient(blobName); - + await blob.UploadAsync(command.GetContent(), overwrite: true); var sanitizedDictionary = SanitizeDictionary(command.Metadata); - + await blob.SetMetadataAsync(sanitizedDictionary); var sasUri = await GetSasUriAsync(new GetSasUri() { Uri = blob.Uri.AbsoluteUri, - ExpiresIn = _configuration.DefaultSasUriExpiration, + ExpiresIn = _options.DefaultSasUriExpiration, }); var blobReference = new BlobReference() @@ -64,25 +106,32 @@ public async Task UploadBlobAsync(UploadBlob command) Uri = blob.Uri.AbsoluteUri, SasUri = sasUri, Metadata = sanitizedDictionary, - SasExpires = DateTime.UtcNow.AddSeconds(_configuration.DefaultSasUriExpiration) + SasExpires = DateTime.UtcNow.AddSeconds(_options.DefaultSasUriExpiration) }; return blobReference; - } - + #endregion + + #region DownloadBlobs + + /// + public async Task DownloadBlobReferenceAsync(string uri) + => await DownloadBlobReferenceAsync(new DownloadBlobReference { Uri = uri }); + + /// public async Task DownloadBlobReferenceAsync(DownloadBlobReference command) { - command.Validate(_configuration); + command.Validate(_options); var blob = new BlobClient(new Uri(command.Uri)); - - var container = new BlobContainerClient(_configuration.ConnectionString, blob.BlobContainerName); - + + var container = new BlobContainerClient(_options.ConnectionString, blob.BlobContainerName); + var blobClient = container.GetBlobClient(blob.Name); var blobProperties = await blobClient.GetPropertiesAsync(); - + return new BlobReference() { Container = blobClient.BlobContainerName, @@ -93,14 +142,19 @@ public async Task DownloadBlobReferenceAsync(DownloadBlobReferenc { Uri = command.Uri, ExpiresIn = command.ExpiresIn <= 0 - ? _configuration.DefaultSasUriExpiration + ? _options.DefaultSasUriExpiration : command.ExpiresIn, }), SasExpires = DateTime.MaxValue, Metadata = blobProperties.Value.Metadata, }; } - + + /// + public async Task DownloadBlobAsync(string uri) + => await DownloadBlobAsync(new DownloadBlob { Uri = uri }); + + /// public async Task DownloadBlobAsync(DownloadBlob command) { command.Validate(); @@ -108,54 +162,82 @@ public async Task DownloadBlobAsync(DownloadBlob command) var sasUri = await GetSasUriAsync(new GetSasUri() { Uri = command.Uri, - ExpiresIn = _configuration.DefaultSasUriExpiration, + ExpiresIn = _options.DefaultSasUriExpiration, }); - + using (var httpClient = new HttpClient()) { var response = await httpClient.GetAsync(sasUri); - if (!response.IsSuccessStatusCode) - { - throw new AzureStorageWrapperException($"something went wrong when downloading blob {command.Uri}"); - } + Ensure.Bool.IsTrue(response.IsSuccessStatusCode, $"something went wrong when downloading blob {command.Uri}"); var stream = await response.Content.ReadAsStreamAsync(); - + return new Blob() { Stream = stream }; } } - + #endregion + + #region DeleteBlobs + + /// + public async Task DeleteBlobAsync(string uri) + => await DeleteBlobAsync(new DeleteBlob { Uri = uri }); + + /// public async Task DeleteBlobAsync(DeleteBlob command) { command.Validate(); var blob = new BlobClient(new Uri(command.Uri)); - - var container = new BlobContainerClient(_configuration.ConnectionString, blob.BlobContainerName); - + + var container = new BlobContainerClient(_options.ConnectionString, blob.BlobContainerName); + var blobClient = container.GetBlobClient(blob.Name); await blobClient.DeleteIfExistsAsync(); } - + #endregion + + #region EnumerateBlobs + + /// + public async Task EnumerateBlobsAsync(int paginateSize, string container = null) + => await EnumerateImplBlobsAsync(new EnumerateBlobs { Container = container, Paginate = true, Size = paginateSize }); + + /// + public async Task EnumerateBlobsAsync(string container = null) + => await EnumerateImplBlobsAsync(new EnumerateBlobs { Container = container, Paginate = false }); + + private async Task EnumerateImplBlobsAsync(EnumerateBlobs command) + { + if (string.IsNullOrEmpty(command.Container)) + { + Ensure.String.IsNotNullOrEmptySW(_options.DefaultContainer); + command.Container = _options.DefaultContainer; + } + + return await EnumerateBlobsAsync(command); + } + + /// public async Task EnumerateBlobsAsync(EnumerateBlobs command) { command.Validate(); - - var container = new BlobContainerClient(_configuration.ConnectionString, command.Container); + + var container = new BlobContainerClient(_options.ConnectionString, command.Container); var segment = container .GetBlobsAsync() .AsPages(command.Paginate ? command.ContinuationToken : null, command.Paginate ? command.Size : (int?)null); - + var enumerator = segment.GetAsyncEnumerator(); - + var references = new List(); - + while (await enumerator.MoveNextAsync()) { var page = enumerator.Current; @@ -165,12 +247,12 @@ public async Task EnumerateBlobsAsync(EnumerateBlobs co var blobReference = await DownloadBlobReferenceAsync(new DownloadBlobReference() { Uri = $"{container.Uri}/{item.Name}", - ExpiresIn = _configuration.DefaultSasUriExpiration + ExpiresIn = _options.DefaultSasUriExpiration }); references.Add(blobReference); } - + await enumerator.DisposeAsync(); return new BlobReferenceCollection() @@ -182,16 +264,21 @@ public async Task EnumerateBlobsAsync(EnumerateBlobs co return new BlobReferenceCollection(); } - - + #endregion + + /// + /// Generates a SAS URI for a blob. + /// + /// The SAS URI command. + /// A task that represents the asynchronous operation. The task result contains the SAS URI. private async Task GetSasUriAsync(GetSasUri command) { - command.Validate(_configuration); + command.Validate(_options); var blob = new BlobClient(new Uri(command.Uri)); - - var container = new BlobContainerClient(_configuration.ConnectionString, blob.BlobContainerName); - + + var container = new BlobContainerClient(_options.ConnectionString, blob.BlobContainerName); + var blobClient = container.GetBlobClient(blob.Name); if (!await blobClient.ExistsAsync()) return null; @@ -200,7 +287,12 @@ private async Task GetSasUriAsync(GetSasUri command) return blobSasUri.AbsoluteUri; } - + + /// + /// Sanitizes a dictionary by removing diacritics and replacing invalid characters. + /// + /// The metadata dictionary to sanitize. + /// The sanitized dictionary. private static Dictionary SanitizeDictionary(Dictionary metadata) { return metadata.ToDictionary(item => SanitizeKey(item.Key), item => SanitizeValue(item.Value)); @@ -208,41 +300,39 @@ private static Dictionary SanitizeDictionary(Dictionary - + True \ - + True \ - + True \ @@ -35,6 +35,7 @@ + diff --git a/src/AzureStorageWrapper/AzureStorageWrapper/Commands/DeleteBlob.cs b/src/AzureStorageWrapper/AzureStorageWrapper/Commands/DeleteBlob.cs deleted file mode 100644 index aeeb9f5..0000000 --- a/src/AzureStorageWrapper/AzureStorageWrapper/Commands/DeleteBlob.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using AzureStorageWrapper.Exceptions; - -namespace AzureStorageWrapper.Commands -{ - public class DeleteBlob - { - public string Uri { get; set; } - - internal void Validate() - { - if (string.IsNullOrEmpty(Uri)) - throw new AzureStorageWrapperException($"{nameof(Uri)} is empty!"); - - if(!System.Uri.TryCreate(Uri, UriKind.Absolute, out var @_)) - throw new AzureStorageWrapperException($"{nameof(Uri)} is not a valid absolute URI!"); - } - } -} \ No newline at end of file diff --git a/src/AzureStorageWrapper/AzureStorageWrapper/Commands/UploadBytes.cs b/src/AzureStorageWrapper/AzureStorageWrapper/Commands/UploadBytes.cs deleted file mode 100644 index 1a9925a..0000000 --- a/src/AzureStorageWrapper/AzureStorageWrapper/Commands/UploadBytes.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.IO; -using AzureStorageWrapper.Exceptions; - -namespace AzureStorageWrapper.Commands -{ - public class UploadBytes : UploadBlob - { - public byte[] Bytes { get; set; } - - public override Stream GetContent() - { - if (Bytes.Length == 0) throw new AzureStorageWrapperException($"{nameof(Bytes)} length is 0"); - - return new MemoryStream(Bytes); - } - } -} \ No newline at end of file diff --git a/src/AzureStorageWrapper/AzureStorageWrapper/Commands/UploadStream.cs b/src/AzureStorageWrapper/AzureStorageWrapper/Commands/UploadStream.cs deleted file mode 100644 index e1f838b..0000000 --- a/src/AzureStorageWrapper/AzureStorageWrapper/Commands/UploadStream.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.IO; -using AzureStorageWrapper.Exceptions; - -namespace AzureStorageWrapper.Commands -{ - public class UploadStream : UploadBlob - { - public Stream Stream { get; set; } - - public override Stream GetContent() - { - if (Stream.Length == 0) throw new AzureStorageWrapperException($"{nameof(Stream)} length is 0"); - - return Stream; - } - } -} \ No newline at end of file diff --git a/src/AzureStorageWrapper/AzureStorageWrapper/DependencyInjectionExtension.cs b/src/AzureStorageWrapper/AzureStorageWrapper/DependencyInjectionExtension.cs deleted file mode 100644 index 9c00675..0000000 --- a/src/AzureStorageWrapper/AzureStorageWrapper/DependencyInjectionExtension.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using Microsoft.Extensions.DependencyInjection; - -namespace AzureStorageWrapper -{ - public static class DependencyInjectionExtension - { - public static void AddAzureStorageWrapper(this IServiceCollection serviceCollection, AzureStorageWrapperConfiguration configuration) - { - serviceCollection.AddSingleton(configuration); - - serviceCollection.AddSingleton(); - } - - public static void AddAzureStorageWrapper(this IServiceCollection serviceCollection, Action configurationAction) - { - var configuration = new AzureStorageWrapperConfiguration(); - - configurationAction(configuration); - - serviceCollection.AddSingleton(configuration); - - serviceCollection.AddSingleton(); - } - } -} diff --git a/src/AzureStorageWrapper/AzureStorageWrapper/IAzureStorageWrapper.cs b/src/AzureStorageWrapper/AzureStorageWrapper/IAzureStorageWrapper.cs deleted file mode 100644 index 425c6d6..0000000 --- a/src/AzureStorageWrapper/AzureStorageWrapper/IAzureStorageWrapper.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using AzureStorageWrapper.Commands; -using AzureStorageWrapper.Queries; -using AzureStorageWrapper.Responses; - -namespace AzureStorageWrapper -{ - public interface IAzureStorageWrapper - { - /// - /// Upload blob (base64, stream or bytes) to an Azure Storage container - /// - /// - /// - Task UploadBlobAsync(UploadBlob command); - - /// - /// Download SAS Uri for a blob - /// - /// - /// - Task DownloadBlobReferenceAsync(DownloadBlobReference command); - - /// - /// Download blob - /// - /// - /// - Task DownloadBlobAsync(DownloadBlob command); - - /// - /// Delete blob from Azure Storage container - /// - /// - /// - Task DeleteBlobAsync(DeleteBlob command); - - /// - /// Enumerate and paginate blobs inside an Azure Storage container - /// - /// - Task EnumerateBlobsAsync(EnumerateBlobs command); - } -} \ No newline at end of file diff --git a/src/AzureStorageWrapper/AzureStorageWrapper/Queries/DownloadBlob.cs b/src/AzureStorageWrapper/AzureStorageWrapper/Queries/DownloadBlob.cs deleted file mode 100644 index 4995520..0000000 --- a/src/AzureStorageWrapper/AzureStorageWrapper/Queries/DownloadBlob.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using AzureStorageWrapper.Exceptions; - -namespace AzureStorageWrapper.Queries -{ - public class DownloadBlob - { - public string Uri { get; set; } - - internal void Validate() - { - if (string.IsNullOrEmpty(Uri)) - throw new AzureStorageWrapperException($"{nameof(Uri)} is empty!"); - - if(!System.Uri.TryCreate(Uri, UriKind.Absolute, out var @_)) - throw new AzureStorageWrapperException($"{nameof(Uri)} is not a valid absolute URI!"); - } - } -} \ No newline at end of file diff --git a/src/AzureStorageWrapper/AzureStorageWrapper/Queries/DownloadBlobReference.cs b/src/AzureStorageWrapper/AzureStorageWrapper/Queries/DownloadBlobReference.cs deleted file mode 100644 index fd28e3b..0000000 --- a/src/AzureStorageWrapper/AzureStorageWrapper/Queries/DownloadBlobReference.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using AzureStorageWrapper.Exceptions; - -namespace AzureStorageWrapper.Queries -{ - public class DownloadBlobReference - { - public string Uri { get; set; } - public int ExpiresIn { get; set; } - - internal void Validate(AzureStorageWrapperConfiguration configuration) - { - if (string.IsNullOrEmpty(Uri)) - throw new AzureStorageWrapperException($"{nameof(Uri)} is empty!"); - - if(!System.Uri.TryCreate(Uri, UriKind.Absolute, out var @_)) - throw new AzureStorageWrapperException($"{nameof(Uri)} is not a valid absolute URI!"); - - if (ExpiresIn > configuration.MaxSasUriExpiration) - throw new AzureStorageWrapperException($"{nameof(ExpiresIn)} should be lower than {configuration.MaxSasUriExpiration}"); - } - } -} \ No newline at end of file diff --git a/src/AzureStorageWrapper/AzureStorageWrapper/Queries/EnumerateBlobs.cs b/src/AzureStorageWrapper/AzureStorageWrapper/Queries/EnumerateBlobs.cs deleted file mode 100644 index a0c803a..0000000 --- a/src/AzureStorageWrapper/AzureStorageWrapper/Queries/EnumerateBlobs.cs +++ /dev/null @@ -1,24 +0,0 @@ -using AzureStorageWrapper.Exceptions; - -namespace AzureStorageWrapper.Queries -{ - public class EnumerateBlobs - { - public string Container { get; set; } - public bool Paginate { get; set; } - public int Size { get; set; } - public string ContinuationToken { get; set; } - - internal void Validate() - { - if (string.IsNullOrEmpty(Container)) - throw new AzureStorageWrapperException($"{nameof(Container)} is empty!"); - - if (Paginate && Size <= 0) - throw new AzureStorageWrapperException($"{nameof(Size)} should be greater than zero when {nameof(Paginate)} is true."); - - if(!Paginate && !string.IsNullOrEmpty(ContinuationToken)) - throw new AzureStorageWrapperException($"{nameof(ContinuationToken)} should be empty when {nameof(Paginate)} is false."); - } - } -} \ No newline at end of file diff --git a/src/AzureStorageWrapper/AzureStorageWrapper/Queries/GetSasUri.cs b/src/AzureStorageWrapper/AzureStorageWrapper/Queries/GetSasUri.cs deleted file mode 100644 index 7e0b2de..0000000 --- a/src/AzureStorageWrapper/AzureStorageWrapper/Queries/GetSasUri.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using AzureStorageWrapper.Exceptions; - -namespace AzureStorageWrapper.Queries -{ - internal class GetSasUri - { - public string Uri { get; set; } - public int ExpiresIn { get; set; } - - internal void Validate(AzureStorageWrapperConfiguration configuration) - { - if (string.IsNullOrEmpty(Uri)) - throw new AzureStorageWrapperException($"{nameof(Uri)} is empty!"); - - if(!System.Uri.TryCreate(Uri, UriKind.Absolute, out var @_)) - throw new AzureStorageWrapperException($"{nameof(Uri)} is not a valid absolute URI!"); - - if (ExpiresIn > configuration.MaxSasUriExpiration) - throw new AzureStorageWrapperException($"{nameof(ExpiresIn)} should be lower than {configuration.MaxSasUriExpiration}"); - } - } -} \ No newline at end of file diff --git a/src/AzureStorageWrapper/AzureStorageWrapper/AzureStorageWrapperBase.cs b/src/AzureStorageWrapper/AzureStorageWrapperBase.cs similarity index 100% rename from src/AzureStorageWrapper/AzureStorageWrapper/AzureStorageWrapperBase.cs rename to src/AzureStorageWrapper/AzureStorageWrapperBase.cs diff --git a/src/AzureStorageWrapper/AzureStorageWrapper/AzureStorageWrapperConfiguration.cs b/src/AzureStorageWrapper/AzureStorageWrapperOptions.cs similarity index 55% rename from src/AzureStorageWrapper/AzureStorageWrapper/AzureStorageWrapperConfiguration.cs rename to src/AzureStorageWrapper/AzureStorageWrapperOptions.cs index e9d3526..bf6b135 100644 --- a/src/AzureStorageWrapper/AzureStorageWrapper/AzureStorageWrapperConfiguration.cs +++ b/src/AzureStorageWrapper/AzureStorageWrapperOptions.cs @@ -1,15 +1,26 @@ -using AzureStorageWrapper.Exceptions; +using AzureStorageWrapper.Exceptions; namespace AzureStorageWrapper { - public class AzureStorageWrapperConfiguration + /// + /// Options for configuring the Azure Storage Wrapper. + /// + public class AzureStorageWrapperOptions { - public AzureStorageWrapperConfiguration() + /// + /// Initializes a new instance of the class. + /// + public AzureStorageWrapperOptions() { MaxSasUriExpiration = int.MaxValue; } private string _connectionString { get; set; } + + /// + /// Gets or sets the connection string for the Azure Storage account. + /// + /// Thrown when the connection string is empty. public string ConnectionString { get => _connectionString; @@ -22,7 +33,18 @@ public string ConnectionString } } + /// + /// Gets or sets the default container name. + /// + /// Thrown when the default container name is empty. + public string DefaultContainer { get; set; } + private int _maxSasUriExpiration; + + /// + /// Gets or sets the maximum SAS URI expiration time in seconds. + /// + /// Thrown when the value is less than zero. public int MaxSasUriExpiration { get => _maxSasUriExpiration; @@ -39,6 +61,11 @@ public int MaxSasUriExpiration } private int _defaultSasUriExpiration; + + /// + /// Gets or sets the default SAS URI expiration time in seconds. + /// + /// Thrown when the value is less than zero or greater than . public int DefaultSasUriExpiration { get => _defaultSasUriExpiration; @@ -46,22 +73,26 @@ public int DefaultSasUriExpiration { if (value < 0) throw new AzureStorageWrapperException($"{nameof(DefaultSasUriExpiration)} should be greater than zero"); - + if (value == 0) _defaultSasUriExpiration = 360; if (value > MaxSasUriExpiration) throw new AzureStorageWrapperException($"{nameof(DefaultSasUriExpiration)} should be lower than {nameof(MaxSasUriExpiration)}"); - + _defaultSasUriExpiration = value; } } - + private bool _createContainerIfNotExists; + + /// + /// Gets or sets a value indicating whether to create the container if it does not exist. + /// public bool CreateContainerIfNotExists { get => _createContainerIfNotExists; set => _createContainerIfNotExists = value; } } -} \ No newline at end of file +} diff --git a/src/AzureStorageWrapper/Commands/DeleteBlob.cs b/src/AzureStorageWrapper/Commands/DeleteBlob.cs new file mode 100644 index 0000000..581eb0b --- /dev/null +++ b/src/AzureStorageWrapper/Commands/DeleteBlob.cs @@ -0,0 +1,21 @@ +using AzureStorageWrapper.Extensions; +using EnsureThat; + +namespace AzureStorageWrapper.Commands +{ + /// + /// Represents a command to delete a blob. + /// + public class DeleteBlob + { + /// + /// Gets or sets the URI of the blob to be deleted. + /// + public string Uri { get; set; } + + /// + /// Validates the URI of the blob. + /// + internal void Validate() => Ensure.String.IsNotUri(Uri); + } +} diff --git a/src/AzureStorageWrapper/AzureStorageWrapper/Commands/UploadBase64.cs b/src/AzureStorageWrapper/Commands/UploadBase64.cs similarity index 94% rename from src/AzureStorageWrapper/AzureStorageWrapper/Commands/UploadBase64.cs rename to src/AzureStorageWrapper/Commands/UploadBase64.cs index 12b3fbc..db6a710 100644 --- a/src/AzureStorageWrapper/AzureStorageWrapper/Commands/UploadBase64.cs +++ b/src/AzureStorageWrapper/Commands/UploadBase64.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Text.RegularExpressions; using AzureStorageWrapper.Exceptions; @@ -22,10 +22,10 @@ public override Stream GetContent() var bytes = Convert.FromBase64String(Base64); return new MemoryStream(bytes); } - catch (Exception _) + catch (Exception) { throw new AzureStorageWrapperException("Invalid base64 string"); } } } -} \ No newline at end of file +} diff --git a/src/AzureStorageWrapper/AzureStorageWrapper/Commands/UploadBlob.cs b/src/AzureStorageWrapper/Commands/UploadBlob.cs similarity index 65% rename from src/AzureStorageWrapper/AzureStorageWrapper/Commands/UploadBlob.cs rename to src/AzureStorageWrapper/Commands/UploadBlob.cs index bd347ea..e5da916 100644 --- a/src/AzureStorageWrapper/AzureStorageWrapper/Commands/UploadBlob.cs +++ b/src/AzureStorageWrapper/Commands/UploadBlob.cs @@ -1,7 +1,9 @@ -using System; +using System; using System.Collections.Generic; +using System.ComponentModel; using System.IO; -using AzureStorageWrapper.Exceptions; +using AzureStorageWrapper.Extensions; +using EnsureThat; namespace AzureStorageWrapper.Commands { @@ -28,14 +30,9 @@ protected UploadBlob() internal void Validate() { - if (string.IsNullOrEmpty(Container)) - throw new AzureStorageWrapperException($"{nameof(Container)} is empty!"); - - if (string.IsNullOrEmpty(Name)) - throw new AzureStorageWrapperException($"{nameof(Name)} is empty!"); - - if (string.IsNullOrEmpty(Extension)) - throw new AzureStorageWrapperException($"{nameof(Extension)} is empty!"); + Ensure.String.IsNotNullOrEmptySW(Container); + Ensure.String.IsNotNullOrEmptySW(Name); + Ensure.String.IsNotNullOrEmptySW(Extension); } } } diff --git a/src/AzureStorageWrapper/Commands/UploadBytes.cs b/src/AzureStorageWrapper/Commands/UploadBytes.cs new file mode 100644 index 0000000..6e78796 --- /dev/null +++ b/src/AzureStorageWrapper/Commands/UploadBytes.cs @@ -0,0 +1,17 @@ +using System.IO; +using AzureStorageWrapper.Extensions; +using EnsureThat; + +namespace AzureStorageWrapper.Commands +{ + public class UploadBytes : UploadBlob + { + public byte[] Bytes { get; set; } + + public override Stream GetContent() + { + Ensure.Any.IsNotZero(Bytes); + return new MemoryStream(Bytes); + } + } +} diff --git a/src/AzureStorageWrapper/Commands/UploadStream.cs b/src/AzureStorageWrapper/Commands/UploadStream.cs new file mode 100644 index 0000000..d64079a --- /dev/null +++ b/src/AzureStorageWrapper/Commands/UploadStream.cs @@ -0,0 +1,13 @@ +using System.IO; +using AzureStorageWrapper.Extensions; +using EnsureThat; + +namespace AzureStorageWrapper.Commands +{ + public class UploadStream : UploadBlob + { + public Stream Stream { get; set; } + + public override Stream GetContent() => Ensure.Any.IsNotZero(Stream); + } +} diff --git a/src/AzureStorageWrapper/DependencyInjection.cs b/src/AzureStorageWrapper/DependencyInjection.cs new file mode 100644 index 0000000..749f72c --- /dev/null +++ b/src/AzureStorageWrapper/DependencyInjection.cs @@ -0,0 +1,36 @@ +using System; +using Microsoft.Extensions.DependencyInjection; + +namespace AzureStorageWrapper +{ + public static class DependencyInjection + { + public static IServiceCollection AddAzureStorageWrapper(this IServiceCollection serviceCollection) + => AddAzureStorageWrapper(serviceCollection, Environment.GetEnvironmentVariable("StorageWrapper_ConnectionString"), Environment.GetEnvironmentVariable("StorageWrapper_DefaultContainer")); + + public static IServiceCollection AddAzureStorageWrapper(this IServiceCollection serviceCollection, string connectionstring,string defaultContainer=null) + => serviceCollection.AddAzureStorageWrapper(new AzureStorageWrapperOptions + { + ConnectionString = connectionstring, + MaxSasUriExpiration = 600, + DefaultSasUriExpiration = 300, + CreateContainerIfNotExists = true, + DefaultContainer = defaultContainer + }); + + public static IServiceCollection AddAzureStorageWrapper(this IServiceCollection serviceCollection, AzureStorageWrapperOptions options) + => serviceCollection.AddSingleton(options) + .AddSingleton() + ; + + public static IServiceCollection AddAzureStorageWrapper(this IServiceCollection serviceCollection, Action optionsAction) + { + var options = new AzureStorageWrapperOptions(); + + optionsAction(options); + + return serviceCollection.AddSingleton(options) + .AddSingleton(); + } + } +} diff --git a/src/AzureStorageWrapper/AzureStorageWrapper/Exceptions/AzureStorageWrapperException.cs b/src/AzureStorageWrapper/Exceptions/AzureStorageWrapperException.cs similarity index 74% rename from src/AzureStorageWrapper/AzureStorageWrapper/Exceptions/AzureStorageWrapperException.cs rename to src/AzureStorageWrapper/Exceptions/AzureStorageWrapperException.cs index c21f492..3d92cb1 100644 --- a/src/AzureStorageWrapper/AzureStorageWrapper/Exceptions/AzureStorageWrapperException.cs +++ b/src/AzureStorageWrapper/Exceptions/AzureStorageWrapperException.cs @@ -1,12 +1,9 @@ -using System; +using System; namespace AzureStorageWrapper.Exceptions { public class AzureStorageWrapperException : Exception { - public AzureStorageWrapperException(string message) : base(message) - { - - } + public AzureStorageWrapperException(string message) : base(message) { } } } diff --git a/src/AzureStorageWrapper/Extensions/EnsureThatExtension.cs b/src/AzureStorageWrapper/Extensions/EnsureThatExtension.cs new file mode 100644 index 0000000..28a6483 --- /dev/null +++ b/src/AzureStorageWrapper/Extensions/EnsureThatExtension.cs @@ -0,0 +1,55 @@ +using System; +using System.IO; +using System.Runtime.CompilerServices; +using AzureStorageWrapper.Exceptions; +using EnsureThat; +using EnsureThat.Enforcers; + +namespace AzureStorageWrapper.Extensions +{ + public static class EnsureThatExtension + { + public static string IsNotNullOrEmptySW(this StringArg _, string value, [CallerMemberName] string paramName = null) + => Ensure.String.IsNotNullOrEmpty(value, paramName, opts => opts.WithException(new AzureStorageWrapperException($"{paramName} is empty!"))); + + public static string IsNotUri(this StringArg _, string value, [CallerMemberName] string paramName = null) + { + IsNotNullOrEmptySW(_, value, paramName); + return Uri.TryCreate(value, UriKind.Absolute, out var @__) + ? value + : throw new AzureStorageWrapperException($"{paramName} is not a valid absolute URI!"); + } + + + public static long IsLteSW(this ComparableArg _, long value, long limit, [CallerMemberName] string paramName = null) + => Ensure.Comparable.IsLte(value, limit, paramName, opts => opts.WithException(new AzureStorageWrapperException($"{paramName} should be lower than {limit}"))); + + + public static Stream IsNotZero(this AnyArg _, Stream value, [CallerMemberName] string paramName = null) + => value.Length > 0 + ? value + : throw new AzureStorageWrapperException($"{paramName} length is 0"); + public static byte[] IsNotZero(this AnyArg _, byte[] value, [CallerMemberName] string paramName = null) + => value.Length > 0 + ? value + : throw new AzureStorageWrapperException($"{paramName} length is 0"); + + + public static bool IsPaginateValid(this BoolArg _, bool paginate, int size, [CallerMemberName] string paramName = null) + { + if (paginate && size <= 0) + throw new AzureStorageWrapperException($"{nameof(size)} should be greater than zero when {nameof(paginate)} is true."); + return true; + } + public static bool IsPaginateValid(this BoolArg _, bool paginate, string ContinuationToken, [CallerMemberName] string paramName = null) + { + if (!paginate && !string.IsNullOrEmpty(ContinuationToken)) + throw new AzureStorageWrapperException($"{nameof(ContinuationToken)} should be greater than zero when {nameof(paginate)} is true."); + return true; + } + public static bool IsNotExistContainer(this BoolArg _, bool value,string container, [CallerMemberName] string paramName = null) + => Ensure.Bool.IsTrue(value, paramName, opts => opts.WithException(new AzureStorageWrapperException($"container {container} doesn't exists!"))); + public static bool IsTrue(this BoolArg _, bool value,string message) + => Ensure.Bool.IsTrue(value, null, opts => opts.WithException(new AzureStorageWrapperException(message))); + } +} diff --git a/src/AzureStorageWrapper/IAzureStorageWrapper.cs b/src/AzureStorageWrapper/IAzureStorageWrapper.cs new file mode 100644 index 0000000..dc8abfa --- /dev/null +++ b/src/AzureStorageWrapper/IAzureStorageWrapper.cs @@ -0,0 +1,112 @@ +using System.IO; +using System.Threading.Tasks; +using AzureStorageWrapper.Commands; +using AzureStorageWrapper.Queries; +using AzureStorageWrapper.Responses; + +namespace AzureStorageWrapper +{ + /// + /// Interface for Azure Storage Wrapper. + /// + public interface IAzureStorageWrapper + { + /// + /// Uploads a blob to an Azure Storage container. + /// + /// The name of the file. + /// The content of the file as a stream. + /// The name of the container. Optional. + /// A task that represents the asynchronous operation. The task result contains the blob reference. + Task UploadBlobAsync(string file, Stream content, string container = null); + + /// + /// Uploads a blob to an Azure Storage container. + /// + /// The name of the file. + /// The content of the file as a byte array. + /// The name of the container. Optional. + /// A task that represents the asynchronous operation. The task result contains the blob reference. + Task UploadBlobAsync(string file, byte[] content, string container = null); + + /// + /// Uploads a blob to an Azure Storage container. + /// + /// The name of the file. + /// The content of the file as a Base64 string. + /// The name of the container. Optional. + /// A task that represents the asynchronous operation. The task result contains the blob reference. + Task UploadBlobAsync(string file, string contentBase64, string container = null); + + /// + /// Uploads a blob (base64, stream, or bytes) to an Azure Storage container. + /// + /// The upload command. + /// A task that represents the asynchronous operation. The task result contains the blob reference. + Task UploadBlobAsync(UploadBlob command); + + /// + /// Downloads a blob reference from an Azure Storage container. + /// + /// The URI of the blob. + /// A task that represents the asynchronous operation. The task result contains the blob reference. + Task DownloadBlobReferenceAsync(string uri); + + /// + /// Downloads a SAS URI for a blob. + /// + /// The download command. + /// A task that represents the asynchronous operation. The task result contains the blob reference. + Task DownloadBlobReferenceAsync(DownloadBlobReference command); + + /// + /// Downloads a blob from an Azure Storage container. + /// + /// The URI of the blob. + /// A task that represents the asynchronous operation. The task result contains the blob. + Task DownloadBlobAsync(string uri); + + /// + /// Downloads a blob from an Azure Storage container. + /// + /// The download command. + /// A task that represents the asynchronous operation. The task result contains the blob. + Task DownloadBlobAsync(DownloadBlob command); + + /// + /// Deletes a blob from an Azure Storage container. + /// + /// The URI of the blob. + /// A task that represents the asynchronous operation. + Task DeleteBlobAsync(string uri); + + /// + /// Deletes a blob from an Azure Storage container. + /// + /// The delete command. + /// A task that represents the asynchronous operation. + Task DeleteBlobAsync(DeleteBlob command); + + /// + /// Enumerates blobs inside an Azure Storage container. + /// + /// The size of the pagination. + /// The name of the container. Optional. + /// A task that represents the asynchronous operation. The task result contains the blob reference collection. + Task EnumerateBlobsAsync(int paginateSize, string container = null); + + /// + /// Enumerates blobs inside an Azure Storage container. + /// + /// The name of the container. Optional. + /// A task that represents the asynchronous operation. The task result contains the blob reference collection. + Task EnumerateBlobsAsync(string container = null); + + /// + /// Enumerates and paginates blobs inside an Azure Storage container. + /// + /// The enumerate command. + /// A task that represents the asynchronous operation. The task result contains the blob reference collection. + Task EnumerateBlobsAsync(EnumerateBlobs command); + } +} diff --git a/src/AzureStorageWrapper/Queries/DownloadBlob.cs b/src/AzureStorageWrapper/Queries/DownloadBlob.cs new file mode 100644 index 0000000..7da3f38 --- /dev/null +++ b/src/AzureStorageWrapper/Queries/DownloadBlob.cs @@ -0,0 +1,12 @@ +using AzureStorageWrapper.Extensions; +using EnsureThat; + +namespace AzureStorageWrapper.Queries +{ + public class DownloadBlob + { + public string Uri { get; set; } + + internal void Validate() => Ensure.String.IsNotUri(Uri); + } +} diff --git a/src/AzureStorageWrapper/Queries/DownloadBlobReference.cs b/src/AzureStorageWrapper/Queries/DownloadBlobReference.cs new file mode 100644 index 0000000..bdade3c --- /dev/null +++ b/src/AzureStorageWrapper/Queries/DownloadBlobReference.cs @@ -0,0 +1,17 @@ +using AzureStorageWrapper.Extensions; +using EnsureThat; + +namespace AzureStorageWrapper.Queries +{ + public class DownloadBlobReference + { + public string Uri { get; set; } + public int ExpiresIn { get; set; } + + internal void Validate(AzureStorageWrapperOptions option) + { + Ensure.String.IsNotUri(Uri); + Ensure.Comparable.IsLteSW(ExpiresIn, option.MaxSasUriExpiration); + } + } +} diff --git a/src/AzureStorageWrapper/Queries/EnumerateBlobs.cs b/src/AzureStorageWrapper/Queries/EnumerateBlobs.cs new file mode 100644 index 0000000..da3774a --- /dev/null +++ b/src/AzureStorageWrapper/Queries/EnumerateBlobs.cs @@ -0,0 +1,20 @@ +using AzureStorageWrapper.Extensions; +using EnsureThat; + +namespace AzureStorageWrapper.Queries +{ + public class EnumerateBlobs + { + public string Container { get; set; } + public bool Paginate { get; set; } + public int Size { get; set; } + public string ContinuationToken { get; set; } + + internal void Validate() + { + Ensure.String.IsNotNullOrEmptySW(Container); + Ensure.Bool.IsPaginateValid(Paginate, Size); + Ensure.Bool.IsPaginateValid(Paginate, ContinuationToken); + } + } +} diff --git a/src/AzureStorageWrapper/Queries/GetSasUri.cs b/src/AzureStorageWrapper/Queries/GetSasUri.cs new file mode 100644 index 0000000..99a38f7 --- /dev/null +++ b/src/AzureStorageWrapper/Queries/GetSasUri.cs @@ -0,0 +1,17 @@ +using AzureStorageWrapper.Extensions; +using EnsureThat; + +namespace AzureStorageWrapper.Queries +{ + internal class GetSasUri + { + public string Uri { get; set; } + public int ExpiresIn { get; set; } + + internal void Validate(AzureStorageWrapperOptions configuration) + { + Ensure.String.IsNotUri(Uri); + Ensure.Comparable.IsLteSW(ExpiresIn, configuration.MaxSasUriExpiration); + } + } +} diff --git a/src/AzureStorageWrapper/AzureStorageWrapper/Responses/Blob.cs b/src/AzureStorageWrapper/Responses/Blob.cs similarity index 100% rename from src/AzureStorageWrapper/AzureStorageWrapper/Responses/Blob.cs rename to src/AzureStorageWrapper/Responses/Blob.cs diff --git a/src/AzureStorageWrapper/AzureStorageWrapper/Responses/BlobReference.cs b/src/AzureStorageWrapper/Responses/BlobReference.cs similarity index 100% rename from src/AzureStorageWrapper/AzureStorageWrapper/Responses/BlobReference.cs rename to src/AzureStorageWrapper/Responses/BlobReference.cs diff --git a/src/AzureStorageWrapper/AzureStorageWrapper/Responses/BlobReferenceCollection.cs b/src/AzureStorageWrapper/Responses/BlobReferenceCollection.cs similarity index 79% rename from src/AzureStorageWrapper/AzureStorageWrapper/Responses/BlobReferenceCollection.cs rename to src/AzureStorageWrapper/Responses/BlobReferenceCollection.cs index 8d2b289..4469f1f 100644 --- a/src/AzureStorageWrapper/AzureStorageWrapper/Responses/BlobReferenceCollection.cs +++ b/src/AzureStorageWrapper/Responses/BlobReferenceCollection.cs @@ -5,11 +5,9 @@ namespace AzureStorageWrapper.Responses public class BlobReferenceCollection { public BlobReferenceCollection() - { - References = new List(); - } + => References = new List(); public IEnumerable References { get; set; } public string ContinuationToken { get; set; } } -} \ No newline at end of file +}