├── .gitattributes ├── umbraco-marketplace-readme-umbraco.storageproviders.azureblob.md ├── umbraco-marketplace-readme-umbraco.storageproviders.azureblob.imagesharp.md ├── icon.png ├── global.json ├── examples ├── Directory.Packages.props ├── Umbraco.StorageProviders.AzureBlob.TestSite │ ├── Views │ │ ├── Person.cshtml │ │ ├── Partials │ │ │ ├── Components │ │ │ │ └── LatestBlogPosts │ │ │ │ │ ├── NoContent.cshtml │ │ │ │ │ └── Default.cshtml │ │ │ ├── CategoryLinks.cshtml │ │ │ ├── blockgrid │ │ │ │ ├── Components │ │ │ │ │ ├── umbBlockGridDemoHeadlineBlock.cshtml │ │ │ │ │ ├── umbBlockGridDemoRichTextBlock.cshtml │ │ │ │ │ ├── umbBlockGridDemoTwoColumnLayoutBlock.cshtml │ │ │ │ │ ├── latestBlogposts.cshtml │ │ │ │ │ └── umbBlockGridDemoImageBlock.cshtml │ │ │ │ ├── default.cshtml │ │ │ │ ├── areas.cshtml │ │ │ │ ├── area.cshtml │ │ │ │ └── items.cshtml │ │ │ ├── SectionHeader.cshtml │ │ │ ├── blocklist │ │ │ │ ├── Components │ │ │ │ │ └── feature.cshtml │ │ │ │ └── default.cshtml │ │ │ ├── singleblock │ │ │ │ └── default.cshtml │ │ │ ├── Navigation │ │ │ │ ├── TopNavigation.cshtml │ │ │ │ └── SubNavigation.cshtml │ │ │ └── ContactForm.cshtml │ │ ├── _ViewImports.cshtml │ │ ├── Blog.cshtml │ │ ├── Contact.cshtml │ │ ├── ContentPage.cshtml │ │ ├── Blogpost.cshtml │ │ ├── Home.cshtml │ │ ├── Product.cshtml │ │ ├── Products.cshtml │ │ ├── People.cshtml │ │ └── _Master.cshtml │ ├── wwwroot │ │ ├── favicon.ico │ │ ├── scripts │ │ │ └── umbraco-starterkit-app.js │ │ └── css │ │ │ └── umbraco-starterkit-blockgrid.css │ ├── Properties │ │ ├── serviceDependencies.json │ │ ├── serviceDependencies.local.json │ │ └── launchSettings.json │ ├── .gitignore │ ├── Program.cs │ ├── appsettings.Development.json │ ├── appsettings.json │ ├── Umbraco.StorageProviders.AzureBlob.TestSite.csproj │ ├── AzureBlobFileSystemComposer.cs │ └── umbraco │ │ └── models │ │ ├── Folder.generated.cs │ │ ├── UmbBlockGridDemoTwoColumnLayoutBlock.generated.cs │ │ ├── Member.generated.cs │ │ ├── UmbBlockGridDemoHeadlineBlock.generated.cs │ │ ├── UmbBlockGridDemoImageBlock.generated.cs │ │ ├── UmbBlockGridDemoRichTextBlock.generated.cs │ │ ├── Feature.generated.cs │ │ ├── LatestBlogposts.generated.cs │ │ ├── File.generated.cs │ │ ├── UmbracoMediaAudio.generated.cs │ │ ├── UmbracoMediaVideo.generated.cs │ │ ├── UmbracoMediaArticle.generated.cs │ │ ├── UmbracoMediaVectorGraphics.generated.cs │ │ ├── Image.generated.cs │ │ ├── ContentBase.generated.cs │ │ ├── ContentPage.generated.cs │ │ ├── Product.generated.cs │ │ ├── People.generated.cs │ │ ├── Blogpost.generated.cs │ │ ├── Blog.generated.cs │ │ ├── Products.generated.cs │ │ ├── NavigationBase.generated.cs │ │ └── Contact.generated.cs └── Directory.Build.props ├── src ├── Umbraco.StorageProviders │ ├── buildTransitive │ │ └── Umbraco.StorageProviders.props │ ├── Umbraco.StorageProviders.csproj │ ├── CdnMediaUrlProviderOptions.cs │ ├── appsettings-schema.Umbraco.StorageProviders.json │ ├── CdnMediaUrlProvider.cs │ └── DependencyInjection │ │ └── CdnMediaUrlProviderExtensions.cs ├── Umbraco.StorageProviders.AzureBlob │ ├── buildTransitive │ │ └── Umbraco.StorageProviders.AzureBlob.props │ ├── IO │ │ ├── IAzureBlobFileSystemProvider.cs │ │ ├── IAzureBlobFileSystem.cs │ │ ├── AzureBlobFileSystemOptions.cs │ │ ├── AzureBlobFileSystemProvider.cs │ │ └── AzureBlobFileSystemOptionsExtensions.cs │ ├── Umbraco.StorageProviders.AzureBlob.csproj │ ├── AzureBlobPrefixInfo.cs │ ├── AzureBlobDirectoryContents.cs │ ├── appsettings-schema.Umbraco.StorageProviders.AzureBlob.json │ ├── AzureBlobItemInfo.cs │ ├── AzureBlobFileProvider.cs │ └── DependencyInjection │ │ ├── AzureBlobMediaFileSystemExtensions.cs │ │ └── AzureBlobFileSystemExtensions.cs └── Umbraco.StorageProviders.AzureBlob.ImageSharp │ ├── Umbraco.StorageProviders.AzureBlob.ImageSharp.csproj │ ├── DependencyInjection │ └── AddAzureBlobImageSharpCacheExtensions.cs │ └── AzureBlobFileSystemImageCache.cs ├── version.json ├── icon.svg ├── umbraco-marketplace-readme-umbraco.storageproviders.md ├── NuGet.config ├── umbraco-marketplace-umbraco.storageproviders.azureblob.imagesharp.json ├── Directory.Packages.props ├── LICENSE ├── umbraco-marketplace-umbraco.storageproviders.azureblob.json ├── umbraco-marketplace-umbraco.storageproviders.json ├── azure-pipelines.yml ├── Directory.Build.props └── .globalconfig /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /umbraco-marketplace-readme-umbraco.storageproviders.azureblob.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /umbraco-marketplace-readme-umbraco.storageproviders.azureblob.imagesharp.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umbraco/Umbraco.StorageProviders/HEAD/icon.png -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "10.0.100", 4 | "rollForward": "latestFeature" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/Directory.Packages.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | false 4 | 5 | 6 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Person.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Master.cshtml"; 3 | } 4 |

Nothing to see, but we could make a lesson to display a person

-------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umbraco/Umbraco.StorageProviders/HEAD/examples/Umbraco.StorageProviders.AzureBlob.TestSite/wwwroot/favicon.ico -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Partials/Components/LatestBlogPosts/NoContent.cshtml: -------------------------------------------------------------------------------- 1 |
2 |

There are no posts at this time, try again later.

3 |
4 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Properties/serviceDependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "storage1": { 4 | "type": "storage", 5 | "connectionId": "Media" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Partials/CategoryLinks.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | @foreach (var category in Model) 3 | { 4 | 5 | @category 6 | 7 | } 8 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Properties/serviceDependencies.local.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "storage1": { 4 | "secretStore": null, 5 | "type": "storage.emulator", 6 | "connectionId": "Media" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /examples/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | false 4 | false 5 | false 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Partials/blockgrid/Components/umbBlockGridDemoHeadlineBlock.cshtml: -------------------------------------------------------------------------------- 1 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 2 | 3 |

@Model.Content.Value("headline")

4 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Partials/blockgrid/Components/umbBlockGridDemoRichTextBlock.cshtml: -------------------------------------------------------------------------------- 1 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 2 | 3 |
4 | @Model.Content.Value("richText") 5 |
6 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Partials/blockgrid/Components/umbBlockGridDemoTwoColumnLayoutBlock.cshtml: -------------------------------------------------------------------------------- 1 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 2 | 3 |
4 | @await Html.GetBlockGridItemAreasHtmlAsync(Model) 5 |
6 | -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders/buildTransitive/Umbraco.StorageProviders.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using Umbraco.Extensions 2 | @using Umbraco.Cms.Web.Common.PublishedModels 3 | @using Umbraco.Cms.Web.Common.Views 4 | @using Umbraco.Cms.Core.Models.PublishedContent 5 | @using Microsoft.AspNetCore.Html 6 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders.AzureBlob/buildTransitive/Umbraco.StorageProviders.AzureBlob.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Partials/SectionHeader.cshtml: -------------------------------------------------------------------------------- 1 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 2 |
3 |
4 |

@Model.Value("PageTitle", Model.Name)

5 |
6 |
7 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Partials/blocklist/Components/feature.cshtml: -------------------------------------------------------------------------------- 1 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage>; 2 | @using ContentModels = Umbraco.Cms.Web.Common.PublishedModels; 3 | @{ 4 | var feature = Model.Content; 5 | } 6 | 7 |
8 |

@feature.FeatureName

9 |
@feature.FeatureDetails
10 |
-------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Partials/blockgrid/Components/latestBlogposts.cshtml: -------------------------------------------------------------------------------- 1 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage>; 2 | @using ContentModels = Umbraco.Cms.Web.Common.PublishedModels; 3 | 4 | @await Component.InvokeAsync("LatestBlogPosts", 5 | new { numberOfPosts = Model.Content.NumberOfPosts, startNodeKey = Model.Content.StartNode?.Key ?? Guid.Empty }) 6 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Partials/singleblock/default.cshtml: -------------------------------------------------------------------------------- 1 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 2 | @{ 3 | if (Model.ContentKey == Guid.Empty) { return; } 4 | var data = Model.Content; 5 | } 6 | @await Html.PartialAsync( 7 | Html.SingleBlockPartialWithFallback("singleBlock/Components/" + data.ContentType.Alias, 8 | "blocklist/Components/" + data.ContentType.Alias ) 9 | , Model) 10 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Partials/blockgrid/default.cshtml: -------------------------------------------------------------------------------- 1 | @using Umbraco.Extensions 2 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 3 | @{ 4 | if (Model?.Any() != true) { return; } 5 | var gridColumns = Model.GridColumns?.ToString() ?? "12"; 6 | } 7 | 8 |
9 | @await Html.GetBlockGridItemsHtmlAsync(Model) 10 |
11 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Partials/blocklist/default.cshtml: -------------------------------------------------------------------------------- 1 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 2 | @{ 3 | if (Model?.Any() != true) { return; } 4 | } 5 |
6 | @foreach (var block in Model) 7 | { 8 | if (block?.ContentKey == null) { continue; } 9 | var data = block.Content; 10 | 11 | @await Html.PartialAsync("blocklist/Components/" + data.ContentType.Alias, block) 12 | } 13 |
14 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Partials/blockgrid/Components/umbBlockGridDemoImageBlock.cshtml: -------------------------------------------------------------------------------- 1 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 2 | @{ 3 | var typedMediaPickerSingle = Model.Content.Value("image"); 4 | if (typedMediaPickerSingle != null) 5 | { 6 | 7 | } else { 8 |

Missing image

9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Blog.cshtml: -------------------------------------------------------------------------------- 1 | @using ContentModels = Umbraco.Cms.Web.Common.PublishedModels 2 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 3 | @{ 4 | Layout = "_Master.cshtml"; 5 | } 6 | 7 | 8 | 9 |
10 | 11 |
12 | @await Component.InvokeAsync("LatestBlogPosts", 13 | new { numberOfPosts = Model.HowManyPostsShouldBeShown, startNodeKey = Model.Key }) 14 |
15 | 16 |
-------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Partials/blockgrid/areas.cshtml: -------------------------------------------------------------------------------- 1 | @using Umbraco.Extensions 2 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 3 | @{ 4 | if (Model?.Areas.Any() != true) { return; } 5 | } 6 | 7 |
9 | @foreach (var area in Model.Areas) 10 | { 11 | @await Html.GetBlockGridItemAreaHtmlAsync(area) 12 | } 13 |
14 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Partials/blockgrid/area.cshtml: -------------------------------------------------------------------------------- 1 | @using Umbraco.Extensions 2 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 3 | 4 |
9 | @await Html.GetBlockGridItemsHtmlAsync(Model) 10 |
11 | -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders.AzureBlob/IO/IAzureBlobFileSystemProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Umbraco.StorageProviders.AzureBlob.IO; 2 | 3 | /// 4 | /// The Azure Blob file system provider. 5 | /// 6 | public interface IAzureBlobFileSystemProvider 7 | { 8 | /// 9 | /// Get the file system by its . 10 | /// 11 | /// The name of the . 12 | /// 13 | /// The . 14 | /// 15 | IAzureBlobFileSystem GetFileSystem(string name); 16 | } 17 | -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders.AzureBlob/IO/IAzureBlobFileSystem.cs: -------------------------------------------------------------------------------- 1 | using Azure.Storage.Blobs; 2 | using Umbraco.Cms.Core.IO; 3 | 4 | namespace Umbraco.StorageProviders.AzureBlob.IO; 5 | 6 | /// 7 | /// Represents an Azure Blob Storage file system. 8 | /// 9 | public interface IAzureBlobFileSystem : IFileSystem 10 | { 11 | /// 12 | /// Get the . 13 | /// 14 | /// The relative path to the blob. 15 | /// 16 | /// A . 17 | /// 18 | BlobClient GetBlobClient(string path); 19 | } 20 | -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders/Umbraco.StorageProviders.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Umbraco Storage Providers 4 | Shared storage providers infrastructure for Umbraco CMS 5 | umbraco-marketplace umbraco storage cdn 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/main/src/NerdBank.GitVersioning/version.schema.json", 3 | "version": "17.0.0", 4 | "assemblyVersion": { 5 | "precision": "build" 6 | }, 7 | "gitCommitIdShortFixedLength": 7, 8 | "nuGetPackageVersion": { 9 | "semVer": 2.0 10 | }, 11 | "publicReleaseRefSpec": [ 12 | "^refs/heads/main$", 13 | "^refs/tags/release-" 14 | ], 15 | "cloudBuild": { 16 | "buildNumber": { 17 | "enabled": true 18 | } 19 | }, 20 | "release": { 21 | "tagName": "release-{version}", 22 | "branchName": "release/{version}", 23 | "versionIncrement": "build" 24 | } 25 | } -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/.gitignore: -------------------------------------------------------------------------------- 1 | ## 2 | ## Umbraco CMS 3 | ## 4 | 5 | # JSON schema files for appsettings.json 6 | appsettings-schema.json 7 | appsettings-schema.*.json 8 | 9 | # JSON schema file for umbraco-package.json 10 | umbraco-package-schema.json 11 | 12 | # Packages created from the backoffice (package.xml/package.zip) 13 | /umbraco/Data/CreatedPackages/ 14 | 15 | # Temp folder containing Examine indexes, NuCache, MediaCache, etc. 16 | /umbraco/Data/TEMP/ 17 | 18 | # SQLite database files 19 | /umbraco/Data/*.sqlite.db 20 | /umbraco/Data/*.sqlite.db-shm 21 | /umbraco/Data/*.sqlite.db-wal 22 | 23 | # Log files 24 | /umbraco/Logs/ 25 | 26 | # Media files 27 | /wwwroot/media/ 28 | -------------------------------------------------------------------------------- /icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Partials/Navigation/TopNavigation.cshtml: -------------------------------------------------------------------------------- 1 | @using Umbraco.Cms.Core.Models.PublishedContent 2 | @using Umbraco.Cms.Core.Routing 3 | @using Umbraco.Extensions 4 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 5 | @{ 6 | var site = Model.Root(); 7 | var selection = site.Children.Where(x => x.IsVisible()); 8 | } 9 | 10 | @site.Name 11 | @foreach (var item in selection) 12 | { 13 | @item.Name 14 | } -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Partials/Navigation/SubNavigation.cshtml: -------------------------------------------------------------------------------- 1 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 2 | @using Umbraco.Cms.Core.Models.PublishedContent 3 | @using Umbraco.Cms.Core.Routing 4 | @using Umbraco.Extensions 5 | 6 | @inject IPublishedValueFallback PublishedValueFallback 7 | @inject IPublishedUrlProvider PublishedUrlProvider 8 | @{ 9 | var siteSection = Model.AncestorOrSelf(2); 10 | var selection = siteSection.Children.Where(x => x.IsVisible(PublishedValueFallback)); 11 | } 12 | 13 | @foreach (var item in selection) 14 | { 15 | @item.Name 16 | } -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders.AzureBlob.ImageSharp/Umbraco.StorageProviders.AzureBlob.ImageSharp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Umbraco Storage Providers - Azure Blob Storage - ImageSharp 4 | Adds ImageSharp support using the Azure Blob Storage provider for Umbraco CMS. 5 | umbraco-marketplace umbraco azure blob storage imagesharp 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Program.cs: -------------------------------------------------------------------------------- 1 | WebApplicationBuilder builder = WebApplication.CreateBuilder(args); 2 | 3 | #if DEBUG 4 | builder.Configuration.AddJsonFile("appsettings.Local.json", optional: true, reloadOnChange: true); 5 | #endif 6 | 7 | builder.CreateUmbracoBuilder() 8 | .AddBackOffice() 9 | .AddWebsite() 10 | .AddDeliveryApi() 11 | .AddComposers() 12 | .Build(); 13 | 14 | WebApplication app = builder.Build(); 15 | 16 | await app.BootUmbracoAsync(); 17 | 18 | app.UseHttpsRedirection(); 19 | 20 | app.UseUmbraco() 21 | .WithMiddleware(u => 22 | { 23 | u.UseBackOffice(); 24 | u.UseWebsite(); 25 | }) 26 | .WithEndpoints(u => 27 | { 28 | u.UseBackOfficeEndpoints(); 29 | u.UseWebsiteEndpoints(); 30 | }); 31 | 32 | await app.RunAsync(); 33 | -------------------------------------------------------------------------------- /umbraco-marketplace-readme-umbraco.storageproviders.md: -------------------------------------------------------------------------------- 1 | **Umbraco Storage Providers** is a set of Umbraco packages that extend the core functionality of the CMS to configure custom CDN media URLs and replace the default physical file storage with Azure Blob Storage. 2 | 3 | The following packages are available and all require code changes and configuration (follow the instructions provided in the documentation): 4 | - `Umbraco.StorageProviders` - Contains shared storage providers infrastructure, like a CDN media URL provider. 5 | - `Umbraco.StorageProviders.AzureBlob` - The Azure Blob Storage provider has an implementation of the Umbraco `IFileSystem` that connects to an Azure Blob Storage container. 6 | - `Umbraco.StorageProviders.AzureBlob.ImageSharp` - Adds ImageSharp support for storing the image cache to a pre-configured Azure Blob Storage provider. 7 | -------------------------------------------------------------------------------- /NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "appsettings-schema.json", 3 | "Serilog": { 4 | "MinimumLevel": { 5 | "Default": "Information" 6 | }, 7 | "WriteTo": [ 8 | { 9 | "Name": "Async", 10 | "Args": { 11 | "configure": [ 12 | { 13 | "Name": "Console" 14 | } 15 | ] 16 | } 17 | } 18 | ] 19 | }, 20 | "Umbraco": { 21 | "CMS": { 22 | "Runtime": { 23 | "Mode": "Development" 24 | }, 25 | "ModelsBuilder": { 26 | "ModelsMode": "SourceCodeAuto" 27 | }, 28 | "Hosting": { 29 | "Debug": true 30 | }, 31 | "RuntimeMinification": { 32 | "UseInMemoryCache": true, 33 | "CacheBuster": "Timestamp" 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders.AzureBlob/Umbraco.StorageProviders.AzureBlob.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Umbraco Storage Providers - Azure Blob Storage 4 | Azure Blob Storage provider for Umbraco CMS. 5 | umbraco-marketplace umbraco azure blob storage 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @using Umbraco.SampleSite.Models 2 | @using ContentModels = Umbraco.Cms.Web.Common.PublishedModels 3 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 4 | @{ 5 | Layout = "_Master.cshtml"; 6 | } 7 | 8 | 9 |
10 |
11 |
12 |
13 |

@Model.MapHeader

14 | @Model.MapCoordinates 15 |
16 |
17 |

@Model.ContactFormHeader

18 | @Model.ContactIntro 19 | 20 |
21 |
22 |
23 |
-------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/ContentPage.cshtml: -------------------------------------------------------------------------------- 1 | @using ContentModels = Umbraco.Cms.Web.Common.PublishedModels 2 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 3 | @{ 4 | Layout = "_Master.cshtml"; 5 | } 6 | 7 | 8 | 9 |
10 | 11 |
12 | 13 |
14 | 17 |
18 | 19 |
20 |
21 | @await Html.GetBlockGridHtmlAsync(Model, "bodyText") 22 |
23 |
24 |
25 | 26 |
27 | 28 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:39676", 8 | "sslPort": 44333 9 | } 10 | }, 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development" 17 | } 18 | }, 19 | "Umbraco.Web.UI": { 20 | "commandName": "Project", 21 | "dotnetRunMessages": true, 22 | "launchBrowser": true, 23 | "applicationUrl": "https://localhost:44333;http://localhost:39676", 24 | "environmentVariables": { 25 | "ASPNETCORE_ENVIRONMENT": "Development" 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders/CdnMediaUrlProviderOptions.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Umbraco.StorageProviders; 4 | 5 | /// 6 | /// The CDN media URL provider options. 7 | /// 8 | public sealed class CdnMediaUrlProviderOptions 9 | { 10 | /// 11 | /// Gets or sets the CDN media root URL. 12 | /// 13 | /// 14 | /// The CDN media root URL. 15 | /// 16 | [Required] 17 | public required Uri Url { get; set; } 18 | 19 | /// 20 | /// Gets or sets a value indicating whether to remove the from the path, defaults to true. 21 | /// 22 | /// 23 | /// true if the media path needs to be removed from the path; otherwise, false. 24 | /// 25 | public bool RemoveMediaFromPath { get; set; } = true; 26 | } 27 | -------------------------------------------------------------------------------- /umbraco-marketplace-umbraco.storageproviders.azureblob.imagesharp.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://marketplace.umbraco.com/umbraco-marketplace-schema.json", 3 | "AuthorDetails": { 4 | "Url": "https://umbraco.com/", 5 | "ImageUrl": "https://github.com/umbraco.png", 6 | "SyncContributorsFromRepository": true 7 | }, 8 | "Category": "Developer Tools", 9 | "Title": "Umbraco Azure Blob Storage Provider for ImageSharp", 10 | "Description": "Adds ImageSharp support for storing the image cache to a pre-configured Azure Blob Storage provider.", 11 | "DocumentationUrl": "https://github.com/umbraco/Umbraco.StorageProviders#umbracostorageprovidersazureblobimagesharp", 12 | "IssueTrackerUrl": "https://github.com/umbraco/Umbraco.StorageProviders/issues", 13 | "IsSubPackageOf": "Umbraco.StorageProviders.AzureBlob", 14 | "LicenseTypes": [ 15 | "Free" 16 | ], 17 | "PackageType": "Package", 18 | "Tags": [ 19 | "azure", 20 | "blob", 21 | "storage", 22 | "imagesharp" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Blogpost.cshtml: -------------------------------------------------------------------------------- 1 | @using ContentModels = Umbraco.Cms.Web.Common.PublishedModels 2 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 3 | @{ 4 | Layout = "_Master.cshtml"; 5 | } 6 | 7 | 8 |
9 |
10 |
11 |
12 | @Model.CreateDate.ToShortDateString() 13 | 14 | 15 | 16 |
17 |

@Model.Excerpt

18 | @await Html.GetBlockGridHtmlAsync(Model, "bodyText") 19 | 20 |
21 |
22 |
23 | 24 | -------------------------------------------------------------------------------- /Directory.Packages.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | [17.0.0, 18) 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Umbraco HQ 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /umbraco-marketplace-umbraco.storageproviders.azureblob.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://marketplace.umbraco.com/umbraco-marketplace-schema.json", 3 | "AuthorDetails": { 4 | "Url": "https://umbraco.com/", 5 | "ImageUrl": "https://github.com/umbraco.png", 6 | "SyncContributorsFromRepository": true 7 | }, 8 | "Category": "Developer Tools", 9 | "Title": "Umbraco Azure Blob Storage Provider", 10 | "Description": "The Azure Blob Storage provider has an implementation of the Umbraco IFileSystem that connects to an Azure Blob Storage container.", 11 | "DocumentationUrl": "https://github.com/umbraco/Umbraco.StorageProviders#umbracostorageprovidersazureblob", 12 | "IssueTrackerUrl": "https://github.com/umbraco/Umbraco.StorageProviders/issues", 13 | "IsSubPackageOf": "Umbraco.StorageProviders", 14 | "LicenseTypes": [ 15 | "Free" 16 | ], 17 | "PackageType": "Package", 18 | "RelatedPackages": [ 19 | { 20 | "PackageId": "Umbraco.StorageProviders.AzureBlob.ImageSharp", 21 | "Description": "Adds ImageSharp support for storing the image cache to a pre-configured Azure Blob Storage provider." 22 | } 23 | ], 24 | "Tags": [ 25 | "azure", 26 | "blob", 27 | "storage" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Partials/ContactForm.cshtml: -------------------------------------------------------------------------------- 1 | @using Umbraco.SampleSite.Controllers 2 | @model Umbraco.SampleSite.Models.ContactFormViewModel 3 | @{ 4 | var message = TempData["Message"]?.ToString(); 5 | } 6 | 7 |
8 | @using (Html.BeginUmbracoForm(nameof(ContactFormController.Submit))) 9 | { 10 |
11 | @Html.TextBoxFor(m => m.Name, new {@class="form-control", placeholder = Html.DisplayNameFor(m => m.Name)}) 12 | @Html.ValidationMessageFor(m => m.Name) 13 |
14 |
15 | @Html.TextBoxFor(m => m.Email, new {@class="form-control", placeholder = Html.DisplayNameFor(m => m.Email)}) 16 | @Html.ValidationMessageFor(m => m.Email) 17 |
18 |
19 | @Html.TextAreaFor(m => m.Message, new {@class="form-control", placeholder = Html.DisplayNameFor(m => m.Message)}) 20 | @Html.ValidationMessageFor(m => m.Message) 21 |
22 | 23 | @if (!string.IsNullOrEmpty(message)) 24 | { 25 | @message 26 | } 27 | } 28 |
29 | -------------------------------------------------------------------------------- /umbraco-marketplace-umbraco.storageproviders.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://marketplace.umbraco.com/umbraco-marketplace-schema.json", 3 | "AuthorDetails": { 4 | "Url": "https://umbraco.com/", 5 | "ImageUrl": "https://github.com/umbraco.png", 6 | "SyncContributorsFromRepository": true 7 | }, 8 | "Category": "Developer Tools", 9 | "Title": "Umbraco Storage Providers", 10 | "Description": "Storage Providers is an extension from Umbraco that provides a CDN media provider and can replace the default physical file storage.", 11 | "DocumentationUrl": "https://github.com/umbraco/Umbraco.StorageProviders#umbracostorageproviders", 12 | "IssueTrackerUrl": "https://github.com/umbraco/Umbraco.StorageProviders/issues", 13 | "LicenseTypes": [ 14 | "Free" 15 | ], 16 | "PackageType": "Package", 17 | "RelatedPackages": [ 18 | { 19 | "GroupTitle": "Azure Blob Storage", 20 | "PackageId": "Umbraco.StorageProviders.AzureBlob", 21 | "Description": "The Azure Blob Storage provider has an implementation of the Umbraco IFileSystem that connects to an Azure Blob Storage container." 22 | }, 23 | { 24 | "GroupTitle": "Azure Blob Storage", 25 | "PackageId": "Umbraco.StorageProviders.AzureBlob.ImageSharp", 26 | "Description": "Adds ImageSharp support for storing the image cache to a pre-configured Azure Blob Storage provider." 27 | } 28 | ], 29 | "Tags": [ 30 | "storage", 31 | "cdn" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Home.cshtml: -------------------------------------------------------------------------------- 1 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 2 | @{ 3 | Layout = "_Master.cshtml"; 4 | var backgroundImage = Model.HeroBackgroundImage != null ? Model.HeroBackgroundImage.Url() : String.Empty; 5 | } 6 |
8 |
9 |

@Model.HeroHeader

10 |

@Model.HeroDescription

11 | @if (Model.HeroCtalink != null) 12 | { 13 | 14 | @Model.HeroCtacaption 15 | 16 | } 17 |
18 |
19 | 20 |
21 | @await Html.GetBlockGridHtmlAsync(Model.BodyText) 22 |
23 | 24 |
25 | 26 |
27 |
28 | 29 |
30 |

@Model.FooterHeader

31 |

@Model.FooterDescription

32 | 33 | 34 | @Model.FooterCtacaption 35 | 36 |
37 | 38 |
39 |
40 | 41 |
-------------------------------------------------------------------------------- /src/Umbraco.StorageProviders.AzureBlob/AzureBlobPrefixInfo.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.FileProviders; 2 | 3 | namespace Umbraco.StorageProviders.AzureBlob; 4 | 5 | /// 6 | /// Represents an Azure Blob Storage prefix. 7 | /// 8 | /// 9 | public sealed class AzureBlobPrefixInfo : IFileInfo 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// The prefix. 15 | /// is null. 16 | public AzureBlobPrefixInfo(string prefix) 17 | { 18 | ArgumentNullException.ThrowIfNull(prefix); 19 | 20 | Name = ParseName(prefix); 21 | } 22 | 23 | /// 24 | public bool Exists => true; 25 | 26 | /// 27 | public bool IsDirectory => true; 28 | 29 | /// 30 | public DateTimeOffset LastModified => default; 31 | 32 | /// 33 | public long Length => -1; 34 | 35 | /// 36 | public string Name { get; } 37 | 38 | /// 39 | public string? PhysicalPath => null; 40 | 41 | /// 42 | public Stream CreateReadStream() => throw new InvalidOperationException(); 43 | 44 | private static string ParseName(string prefix) 45 | { 46 | var name = prefix.TrimEnd('/'); 47 | 48 | return name[(name.LastIndexOf('/') + 1)..]; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Partials/blockgrid/items.cshtml: -------------------------------------------------------------------------------- 1 | @using Umbraco.Cms.Core.Models.Blocks 2 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage> 3 | @{ 4 | if (Model?.Any() != true) { return; } 5 | } 6 | 7 |
8 | @foreach (var item in Model) 9 | { 10 | 11 |
19 | @{ 20 | var partialViewName = "blockgrid/Components/" + item.Content.ContentType.Alias; 21 | try 22 | { 23 | @await Html.PartialAsync(partialViewName, item) 24 | } 25 | catch (InvalidOperationException) 26 | { 27 |

28 | Could not render component of type: @(item.Content.ContentType.Alias) 29 |
30 | This likely happened because the partial view @partialViewName could not be found. 31 |

32 | } 33 | } 34 |
35 | } 36 |
37 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Product.cshtml: -------------------------------------------------------------------------------- 1 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 2 | @{ 3 | Layout = "_Master.cshtml"; 4 | var defaultCurrency = Model.Parent().DefaultCurrency; 5 | } 6 | 7 | 8 | 9 |
10 |
11 |
12 |
13 |
14 | @Model.ProductName image 15 |
16 |
17 |
18 |

@Model.ProductName

19 |
@defaultCurrency @Model.Price.ToString("F")
20 |
@Model.Description
21 |
22 | 23 |
24 |
25 | @await Html.GetBlockListHtmlAsync(Model, "features") 26 |
27 |
28 |
29 |
30 |
31 | 32 |
33 |
34 | 35 | @await Html.GetBlockGridHtmlAsync(Model, "bodyText") 36 |
37 |
-------------------------------------------------------------------------------- /src/Umbraco.StorageProviders/appsettings-schema.Umbraco.StorageProviders.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "title": "UmbracoStorageProvidersSchema", 4 | "type": "object", 5 | "properties": { 6 | "Umbraco": { 7 | "$ref": "#/definitions/UmbracoDefinition" 8 | } 9 | }, 10 | "definitions": { 11 | "UmbracoDefinition": { 12 | "type": "object", 13 | "description": "Configuration container for all Umbraco products.", 14 | "properties": { 15 | "Storage": { 16 | "$ref": "#/definitions/UmbracoStorageProvidersDefinition" 17 | } 18 | } 19 | }, 20 | "UmbracoStorageProvidersDefinition": { 21 | "type": "object", 22 | "description": "Configuration of Umbraco Storage Providers.", 23 | "properties": { 24 | "Cdn": { 25 | "$ref": "#/definitions/CdnMediaUrlProviderOptions" 26 | } 27 | } 28 | }, 29 | "CdnMediaUrlProviderOptions": { 30 | "type": "object", 31 | "description": "The CDN media URL provider options.", 32 | "required": [ 33 | "Url" 34 | ], 35 | "properties": { 36 | "Url": { 37 | "type": "string", 38 | "description": "Gets or sets the CDN media root URL.", 39 | "format": "uri", 40 | "minLength": 1 41 | }, 42 | "RemoveMediaFromPath": { 43 | "type": "boolean", 44 | "description": "Gets or sets a value indicating whether to remove the UmbracoMediaPath from the path, defaults to true.", 45 | "default": true 46 | } 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "appsettings-schema.json", 3 | "Serilog": { 4 | "MinimumLevel": { 5 | "Default": "Information", 6 | "Override": { 7 | "Microsoft": "Warning", 8 | "Microsoft.Hosting.Lifetime": "Information", 9 | "System": "Warning" 10 | } 11 | } 12 | }, 13 | "ConnectionStrings": { 14 | "umbracoDbDSN": "Data Source=|DataDirectory|/Umbraco-17.sqlite.db;Cache=Shared;Foreign Keys=True;Pooling=True", 15 | "umbracoDbDSN_ProviderName": "Microsoft.Data.Sqlite" 16 | }, 17 | "Umbraco": { 18 | "CMS": { 19 | "Global": { 20 | "Id": "00000000-0000-0000-0000-000000000042" 21 | }, 22 | "Content": { 23 | "AllowEditInvariantFromNonDefault": true, 24 | "ContentVersionCleanupPolicy": { 25 | "EnableCleanup": true 26 | } 27 | }, 28 | "Unattended": { 29 | "InstallUnattended": true, 30 | "UnattendedUserName": "Administrator", 31 | "UnattendedUserEmail": "admin@example.com", 32 | "UnattendedUserPassword": "1234567890", 33 | "UpgradeUnattended": true 34 | }, 35 | "ModelsBuilder": { 36 | "ModelsMode": "Nothing" 37 | }, 38 | "Runtime": { 39 | "Mode": "Production" 40 | }, 41 | "Security": { 42 | "AllowConcurrentLogins": false 43 | } 44 | }, 45 | "Storage": { 46 | "AzureBlob": { 47 | "Media": { 48 | "ConnectionString": "UseDevelopmentStorage=true", 49 | "ContainerName": "umbraco-storageproviders-17" 50 | } 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Products.cshtml: -------------------------------------------------------------------------------- 1 | @using Umbraco.Cms.Web.Common.PublishedModels; 2 | @using Umbraco.Extensions 3 | @using ContentModels = Umbraco.Cms.Web.Common.PublishedModels; 4 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 5 | @{ 6 | Layout = "_Master.cshtml"; 7 | } 8 | 9 | 10 | 11 |
12 | 13 |
14 | 15 | 16 | 25 |
26 | @if (Model.FeaturedProducts != null) 27 | { 28 | foreach (Product product in Model.FeaturedProducts) 29 | { 30 | 31 |
32 |
@product.ProductName
33 |
@Model.DefaultCurrency @product.Price.ToString("F")
34 |
35 |
36 | } 37 | } 38 |
39 |
40 | 41 |
-------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Umbraco.StorageProviders.AzureBlob.TestSite.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net10.0 4 | enable 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | true 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders.AzureBlob/IO/AzureBlobFileSystemOptions.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Azure.Storage.Blobs; 3 | 4 | namespace Umbraco.StorageProviders.AzureBlob.IO; 5 | 6 | /// 7 | /// The Azure Blob File System options. 8 | /// 9 | public sealed class AzureBlobFileSystemOptions 10 | { 11 | /// 12 | /// The media filesystem name. 13 | /// 14 | public const string MediaFileSystemName = "Media"; 15 | 16 | /// 17 | /// Gets or sets the storage account connection string. 18 | /// 19 | [Required] 20 | public required string ConnectionString { get; set; } 21 | 22 | /// 23 | /// Gets or sets the container name. 24 | /// 25 | [Required] 26 | public required string ContainerName { get; set; } 27 | 28 | /// 29 | /// Gets or sets the root path of the container. 30 | /// 31 | public string? ContainerRootPath { get; set; } 32 | 33 | /// 34 | /// Gets or sets the virtual path. 35 | /// 36 | [Required] 37 | public required string VirtualPath { get; set; } 38 | 39 | /// 40 | /// Gets or sets the Azure Blob Container client factory. 41 | /// 42 | /// 43 | /// The Azure Blob Container client factory. 44 | /// 45 | internal Func BlobContainerClientFactory { get; set; } = DefaultBlobContainerClientFactory; 46 | 47 | /// 48 | /// Gets the default Azure Blob Container client factory. 49 | /// 50 | /// 51 | /// The default Azure Blob Container client factory. 52 | /// 53 | internal static Func DefaultBlobContainerClientFactory => options => new BlobContainerClient(options.ConnectionString, options.ContainerName); 54 | } 55 | -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders.AzureBlob/AzureBlobDirectoryContents.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using Azure.Storage.Blobs; 3 | using Azure.Storage.Blobs.Models; 4 | using Microsoft.Extensions.FileProviders; 5 | 6 | namespace Umbraco.StorageProviders.AzureBlob; 7 | 8 | /// 9 | /// Represents a virtual hierarchy of Azure Blob Storage blobs. 10 | /// 11 | /// 12 | public sealed class AzureBlobDirectoryContents : IDirectoryContents 13 | { 14 | private readonly BlobContainerClient _containerClient; 15 | private readonly IReadOnlyCollection _items; 16 | 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | /// The container client. 21 | /// The items. 22 | /// is null. 23 | /// is null. 24 | public AzureBlobDirectoryContents(BlobContainerClient containerClient, IReadOnlyCollection items) 25 | { 26 | _containerClient = containerClient ?? throw new ArgumentNullException(nameof(containerClient)); 27 | _items = items ?? throw new ArgumentNullException(nameof(items)); 28 | 29 | Exists = items.Count > 0; 30 | } 31 | 32 | /// 33 | public bool Exists { get; } 34 | 35 | /// 36 | public IEnumerator GetEnumerator() 37 | => _items.Select(x => x.IsPrefix 38 | ? new AzureBlobPrefixInfo(x.Prefix) 39 | : new AzureBlobItemInfo(_containerClient.GetBlobClient(x.Blob.Name), x.Blob.Properties)).GetEnumerator(); 40 | 41 | /// 42 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 43 | } 44 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/Partials/Components/LatestBlogPosts/Default.cshtml: -------------------------------------------------------------------------------- 1 | @using Umbraco.Cms.Core.Models.PublishedContent 2 | @model Umbraco.SampleSite.Models.LatestBlogPostsViewModel; 3 | 4 |
5 | @foreach (IPublishedContent post in Model.BlogPosts) 6 | { 7 | 8 |
9 | @post.CreateDate.ToShortDateString() 10 | 11 | 12 | 13 |
14 |

@post.Value("pageTitle")

15 |
@post.Value("excerpt")
16 |
17 | } 18 | 19 | @if (Model.BlogPosts.Count() < Model.Total) 20 | { 21 | 47 | } 48 |
49 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | branches: 3 | include: 4 | - '*' 5 | tags: 6 | include: 7 | - release-* 8 | 9 | parameters: 10 | - name: cache_nuget 11 | displayName: Cache NuGet packages 12 | type: boolean 13 | default: false 14 | 15 | variables: 16 | solution: Umbraco.StorageProviders.sln 17 | buildConfiguration: Release 18 | DOTNET_NOLOGO: true 19 | DOTNET_GENERATE_ASPNET_CERTIFICATE: false 20 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true 21 | DOTNET_CLI_TELEMETRY_OPTOUT: true 22 | 23 | stages: 24 | - stage: Build 25 | variables: 26 | NUGET_PACKAGES: $(Pipeline.Workspace)/.nuget/packages 27 | jobs: 28 | - job: Build 29 | pool: 30 | vmImage: 'ubuntu-latest' 31 | steps: 32 | # Checkout source (avoid shallow clone to calculate version height) 33 | - checkout: self 34 | fetchDepth: 0 35 | 36 | # Setup build environment 37 | - task: UseDotNet@2 38 | displayName: Use .NET SDK from global.json 39 | inputs: 40 | useGlobalJson: true 41 | 42 | # Cache and restore NuGet packages 43 | - task: Cache@2 44 | condition: ${{ parameters.cache_nuget }} 45 | displayName: Cache NuGet packages 46 | inputs: 47 | key: 'nuget | "$(Agent.OS)" | **/packages.lock.json, !**/bin/**, !**/obj/**' 48 | restoreKeys: | 49 | nuget | "$(Agent.OS)" 50 | nuget 51 | path: $(NUGET_PACKAGES) 52 | 53 | - script: dotnet restore $(solution) --locked-mode 54 | displayName: Restore NuGet packages 55 | 56 | # Build 57 | - script: dotnet build $(solution) --configuration $(buildConfiguration) --no-restore -p:ContinuousIntegrationBuild=true 58 | displayName: Run dotnet build 59 | 60 | # Pack 61 | - script: dotnet pack $(solution) --configuration $(buildConfiguration) --no-build --output $(Build.ArtifactStagingDirectory)/nupkg 62 | displayName: Run dotnet pack 63 | 64 | # Publish 65 | - task: PublishPipelineArtifact@1 66 | displayName: Publish NuGet packages 67 | inputs: 68 | targetPath: $(Build.ArtifactStagingDirectory)/nupkg 69 | artifactName: nupkg 70 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/AzureBlobFileSystemComposer.cs: -------------------------------------------------------------------------------- 1 | using Azure.Core; 2 | using Azure.Storage.Blobs; 3 | using Microsoft.Extensions.Options; 4 | using Umbraco.Cms.Core.Composing; 5 | using Umbraco.Cms.Core.Events; 6 | using Umbraco.Cms.Core.Notifications; 7 | using Umbraco.StorageProviders.AzureBlob.IO; 8 | 9 | namespace Umbraco.StorageProviders.AzureBlob.TestSite; 10 | 11 | internal sealed class AzureBlobFileSystemComposer : IComposer 12 | { 13 | private static readonly BlobClientOptions _blobClientOptions = new BlobClientOptions 14 | { 15 | Retry = { 16 | Mode = RetryMode.Exponential, 17 | MaxRetries = 3 18 | } 19 | }; 20 | 21 | public void Compose(IUmbracoBuilder builder) 22 | => builder 23 | // Add using default options (overly verbose, but shows how to revert back to the default) 24 | .AddAzureBlobMediaFileSystem(options => options.CreateBlobContainerClientUsingDefault()) 25 | // Add using options 26 | .AddAzureBlobMediaFileSystem(options => options.CreateBlobContainerClientUsingOptions(_blobClientOptions)) 27 | // If the connection string is parsed to a URI, use the delegate to create a BlobContainerClient 28 | .AddAzureBlobMediaFileSystem(options => options.TryCreateBlobContainerClientUsingUri(uri => new BlobContainerClient(uri, _blobClientOptions))) 29 | // Add the ImageSharp IImageCache implementation using the default media file system and "cache" container root path 30 | .AddAzureBlobImageSharpCache() 31 | // Add notification handler to create the media file system on install if it doesn't exist 32 | .AddNotificationHandler(); 33 | 34 | private sealed class AzureBlobMediaFileSystemCreateIfNotExistsHandler : INotificationHandler 35 | { 36 | private readonly AzureBlobFileSystemOptions _options; 37 | 38 | public AzureBlobMediaFileSystemCreateIfNotExistsHandler(IOptionsMonitor options) 39 | => _options = options.Get(AzureBlobFileSystemOptions.MediaFileSystemName); 40 | 41 | public void Handle(UnattendedInstallNotification notification) 42 | => AzureBlobFileSystem.CreateIfNotExists(_options); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/wwwroot/scripts/umbraco-starterkit-app.js: -------------------------------------------------------------------------------- 1 | !function e(o, r, n) { 2 | function a(l, t) { 3 | if (!r[l]) { 4 | if (!o[l]) { 5 | var s = "function" == typeof require && require; 6 | if (!t && s) return s(l, !0); 7 | if (i) return i(l, !0); 8 | var c = new Error("Cannot find module '" + l + "'"); 9 | throw c.code = "MODULE_NOT_FOUND", c 10 | } 11 | var d = r[l] = { exports: {} }; 12 | o[l][0].call(d.exports, 13 | function(e) { 14 | var r = o[l][1][e]; 15 | return a(r ? r : e) 16 | }, 17 | d, 18 | d.exports, 19 | e, 20 | o, 21 | r, 22 | n) 23 | } 24 | return r[l].exports 25 | } 26 | 27 | for (var i = "function" == typeof require && require, l = 0; l < n.length; l++) a(n[l]); 28 | return a 29 | }({ 30 | 1: [ 31 | function(e, o, r) { 32 | !function() { 33 | "use strict"; 34 | $(document).ready(function() { 35 | $(window).bind("scroll", 36 | function() { 37 | var e = 150; 38 | $(window).scrollTop() > e 39 | ? $(".header").addClass("header--fixed") 40 | : $(".header").removeClass("header--fixed") 41 | }), $(".mobile-nav-handler").click(function(e) { 42 | $(".mobile-nav").toggleClass("mobile-nav--open"), $(".header").toggleClass("header--hide"), 43 | $("body").toggleClass("no-scroll"), $("#toggle-nav").toggleClass("active") 44 | }), $(".nav-link").click(function(e) { 45 | $(".mobile-nav").removeClass("mobile-nav--open"), $(".header").removeClass("header--hide"), 46 | $("body").removeClass("no-scroll"), $("#toggle-nav").removeClass("active") 47 | }) 48 | }) 49 | }() 50 | }, {} 51 | ] 52 | }, 53 | {}, 54 | [1]); -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/People.cshtml: -------------------------------------------------------------------------------- 1 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 2 | @{ 3 | Layout = "_Master.cshtml"; 4 | } 5 | @{ 6 | void SocialLink(string content, string service) 7 | { 8 | if (!string.IsNullOrEmpty(content)) 9 | { 10 | ; //semicolon needed otherwise cannot be resolved 11 | @service 12 | } 13 | } 14 | } 15 | 16 | 17 | 18 |
19 | 20 |
21 | 22 | 31 |
32 | @foreach (Person person in Model.Children()) 33 | { 34 | 35 |
36 |
37 |
38 |

@person.Name

39 | @if (!string.IsNullOrEmpty(person.Email)) 40 | { 41 | 42 | } 43 |
44 | @{ SocialLink(person.FacebookUsername, "Facebook"); } 45 | @{ SocialLink(person.TwitterUsername, "Twitter"); } 46 | @{ SocialLink(person.LinkedInUsername, "LinkedIn"); } 47 | @{ SocialLink(person.InstagramUsername, "Instagram"); } 48 |
49 |
50 |
51 | } 52 |
53 |
54 | 55 |
-------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/wwwroot/css/umbraco-starterkit-blockgrid.css: -------------------------------------------------------------------------------- 1 | .umb-block-grid__layout-container { 2 | position: relative; 3 | display: grid; 4 | grid-template-columns: repeat(var(--umb-block-grid--grid-columns, 1), minmax(0, 1fr)); 5 | grid-auto-flow: row; 6 | grid-auto-rows: minmax(50px, -webkit-min-content); 7 | grid-auto-rows: minmax(50px, min-content); 8 | 9 | -moz-column-gap: var(--umb-block-grid--column-gap, 0); 10 | 11 | column-gap: var(--umb-block-grid--column-gap, 0); 12 | row-gap: var(--umb-block-grid--row-gap, 0); 13 | } 14 | .umb-block-grid__layout-item { 15 | position: relative; 16 | /* For small devices we scale columnSpan by three, to make everything bigger than 1/3 take full width: */ 17 | grid-column-end: span min(calc(var(--umb-block-grid--item-column-span, 1) * 3), var(--umb-block-grid--grid-columns)); 18 | grid-row: span var(--umb-block-grid--item-row-span, 1); 19 | } 20 | .umb-block-grid__layout-item[data-force-left] { 21 | grid-column-start: 1; 22 | } 23 | .umb-block-grid__layout-item[data-force-right] { 24 | grid-column-start: calc(1 + var(--umb-block-grid--grid-columns) - var(--umb-block-grid--item-column-span)); 25 | } 26 | 27 | 28 | .umb-block-grid__area-container, .umb-block-grid__block--view::part(area-container) { 29 | position: relative; 30 | display: grid; 31 | grid-template-columns: repeat(var(--umb-block-grid--area-grid-columns, var(--umb-block-grid--grid-columns, 1)), minmax(0, 1fr)); 32 | grid-auto-flow: row; 33 | grid-auto-rows: minmax(50px, -webkit-min-content); 34 | grid-auto-rows: minmax(50px, min-content); 35 | 36 | -moz-column-gap: var(--umb-block-grid--areas-column-gap, 0); 37 | 38 | column-gap: var(--umb-block-grid--areas-column-gap, 0); 39 | row-gap: var(--umb-block-grid--areas-row-gap, 0); 40 | } 41 | .umb-block-grid__area { 42 | position: relative; 43 | /* For small devices we scale columnSpan by three, to make everything bigger than 1/3 take full width: */ 44 | grid-column-end: span min(calc(var(--umb-block-grid--item-column-span, 1) * 3), var(--umb-block-grid--grid-columns)); 45 | grid-row: span var(--umb-block-grid--area-row-span, 1); 46 | } 47 | 48 | @media (min-width:1024px) { 49 | .umb-block-grid__layout-item { 50 | grid-column-end: span var(--umb-block-grid--item-column-span, 1); 51 | } 52 | .umb-block-grid__area { 53 | grid-column-end: span var(--umb-block-grid--area-column-span, 1); 54 | } 55 | } -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/Folder.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// Folder 22 | [PublishedModel("Folder")] 23 | public partial class Folder : PublishedContentModel 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "Folder"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Media; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public Folder(IPublishedContent content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | net10.0 4 | Umbraco HQ 5 | Umbraco 6 | Copyright © Umbraco $([System.DateTime]::Today.ToString('yyyy')) 7 | Umbraco Storage Providers 8 | https://github.com/umbraco/Umbraco.StorageProviders 9 | https://github.com/umbraco/Umbraco.StorageProviders/raw/develop/icon.png 10 | icon.png 11 | MIT 12 | en-US 13 | enable 14 | enable 15 | Nullable 16 | true 17 | All 18 | false 19 | 20 | 21 | 22 | 23 | true 24 | true 25 | snupkg 26 | 27 | 28 | 29 | 30 | false 31 | 32 | 17.0.0 33 | true 34 | true 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | $(MSBuildThisFileDirectory) 43 | 44 | 45 | 46 | 47 | 48 | <_ProjectReferencesWithVersions Condition="'%(ProjectVersion)' != ''"> 49 | [%(ProjectVersion), $([MSBuild]::Add($([System.Text.RegularExpressions.Regex]::Match('%(ProjectVersion)', '^\d+').Value), 1))) 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders.AzureBlob/appsettings-schema.Umbraco.StorageProviders.AzureBlob.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "title": "UmbracoStorageProvidersSchema", 4 | "type": "object", 5 | "properties": { 6 | "Umbraco": { 7 | "$ref": "#/definitions/UmbracoDefinition" 8 | } 9 | }, 10 | "definitions": { 11 | "UmbracoDefinition": { 12 | "type": "object", 13 | "description": "Configuration container for all Umbraco products.", 14 | "properties": { 15 | "Storage": { 16 | "$ref": "#/definitions/UmbracoStorageProvidersDefinition" 17 | } 18 | } 19 | }, 20 | "UmbracoStorageProvidersDefinition": { 21 | "type": "object", 22 | "description": "Configuration of Umbraco Storage Providers.", 23 | "properties": { 24 | "AzureBlob": { 25 | "$ref": "#/definitions/UmbracoStorageProvidersAzureBlobDefinition" 26 | } 27 | } 28 | }, 29 | "UmbracoStorageProvidersAzureBlobDefinition": { 30 | "type": "object", 31 | "description": "Configuration of Umbraco Storage Providers - Azure Blob Storage.", 32 | "properties": { 33 | "Media": { 34 | "$ref": "#/definitions/AzureBlobFileSystemOptions" 35 | } 36 | }, 37 | "patternProperties": { 38 | "^(?!Media$).*": { 39 | "allOf": [ 40 | { 41 | "$ref": "#/definitions/AzureBlobFileSystemOptions" 42 | }, 43 | { 44 | "type": "object", 45 | "required": [ 46 | "VirtualPath" 47 | ] 48 | } 49 | ] 50 | } 51 | } 52 | }, 53 | "AzureBlobFileSystemOptions": { 54 | "type": "object", 55 | "description": "The Azure Blob File System options.", 56 | "required": [ 57 | "ConnectionString", 58 | "ContainerName" 59 | ], 60 | "properties": { 61 | "ConnectionString": { 62 | "type": "string", 63 | "description": "Gets or sets the storage account connection string.", 64 | "minLength": 1 65 | }, 66 | "ContainerName": { 67 | "type": "string", 68 | "description": "Gets or sets the container name.", 69 | "minLength": 1 70 | }, 71 | "ContainerRootPath": { 72 | "type": [ 73 | "null", 74 | "string" 75 | ], 76 | "description": "Gets or sets the root path of the container." 77 | }, 78 | "VirtualPath": { 79 | "type": "string", 80 | "description": "Gets or sets the virtual path.", 81 | "minLength": 1 82 | } 83 | } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders.AzureBlob/IO/AzureBlobFileSystemProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Concurrent; 2 | using Microsoft.AspNetCore.StaticFiles; 3 | using Microsoft.Extensions.Options; 4 | using Umbraco.Cms.Core.Hosting; 5 | using Umbraco.Cms.Core.IO; 6 | 7 | namespace Umbraco.StorageProviders.AzureBlob.IO; 8 | 9 | /// 10 | public sealed class AzureBlobFileSystemProvider : IAzureBlobFileSystemProvider 11 | { 12 | private readonly ConcurrentDictionary _fileSystems = new(); 13 | private readonly IOptionsMonitor _optionsMonitor; 14 | private readonly IHostingEnvironment _hostingEnvironment; 15 | private readonly IIOHelper _ioHelper; 16 | private readonly FileExtensionContentTypeProvider _fileExtensionContentTypeProvider; 17 | 18 | /// 19 | /// Initializes a new instance of the class. 20 | /// 21 | /// The options monitor. 22 | /// The hosting environment. 23 | /// The IO helper. 24 | /// is null. 25 | /// is null. 26 | /// is null. 27 | public AzureBlobFileSystemProvider(IOptionsMonitor optionsMonitor, IHostingEnvironment hostingEnvironment, IIOHelper ioHelper) 28 | { 29 | _optionsMonitor = optionsMonitor ?? throw new ArgumentNullException(nameof(optionsMonitor)); 30 | _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment)); 31 | _ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper)); 32 | _fileExtensionContentTypeProvider = new FileExtensionContentTypeProvider(); 33 | 34 | _optionsMonitor.OnChange((options, name) => _fileSystems.TryRemove(name ?? Options.DefaultName, out _)); 35 | } 36 | 37 | /// 38 | /// is null. 39 | public IAzureBlobFileSystem GetFileSystem(string name) 40 | { 41 | ArgumentNullException.ThrowIfNull(name); 42 | 43 | return _fileSystems.GetOrAdd(name, name => 44 | { 45 | AzureBlobFileSystemOptions options = _optionsMonitor.Get(name); 46 | 47 | return new AzureBlobFileSystem(options, _hostingEnvironment, _ioHelper, _fileExtensionContentTypeProvider); 48 | }); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/UmbBlockGridDemoTwoColumnLayoutBlock.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// Two Column Layout 22 | [PublishedModel("umbBlockGridDemoTwoColumnLayoutBlock")] 23 | public partial class UmbBlockGridDemoTwoColumnLayoutBlock : PublishedElementModel 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "umbBlockGridDemoTwoColumnLayoutBlock"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Content; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public UmbBlockGridDemoTwoColumnLayoutBlock(IPublishedElement content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/Views/_Master.cshtml: -------------------------------------------------------------------------------- 1 | @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage 2 | @{ 3 | Layout = null; 4 | // Get basic design settings from the homepage 5 | var home = Model.Root(); 6 | } 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | @Model.Name - @home.Sitename 15 | 16 | 17 | 18 | 19 | @await RenderSectionAsync("Header", required: false) 20 | 21 | 22 | 23 |
24 | 27 |
28 | 29 |
30 | 31 | 43 | 44 | 47 | 48 |
49 |
50 | 51 |
52 |
53 | 54 |
55 | 56 |
57 | @RenderBody() 58 |
59 | 60 |
61 |
62 |
63 |
64 | @home.FooterAddress 65 |
66 |
67 |
68 |
69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/Member.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// Member 22 | [PublishedModel("Member")] 23 | public partial class Member : PublishedContentModel 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "Member"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Member; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public Member(IPublishedContent content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | 52 | /// 53 | /// Comments 54 | /// 55 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 56 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 57 | [ImplementPropertyType("umbracoMemberComments")] 58 | public virtual string UmbracoMemberComments => this.Value(_publishedValueFallback, "umbracoMemberComments"); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/UmbBlockGridDemoHeadlineBlock.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// Headline 22 | [PublishedModel("umbBlockGridDemoHeadlineBlock")] 23 | public partial class UmbBlockGridDemoHeadlineBlock : PublishedElementModel 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "umbBlockGridDemoHeadlineBlock"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Content; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public UmbBlockGridDemoHeadlineBlock(IPublishedElement content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | 52 | /// 53 | /// Headline 54 | /// 55 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 56 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 57 | [ImplementPropertyType("headline")] 58 | public virtual string Headline => this.Value(_publishedValueFallback, "headline"); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/UmbBlockGridDemoImageBlock.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// Image 22 | [PublishedModel("umbBlockGridDemoImageBlock")] 23 | public partial class UmbBlockGridDemoImageBlock : PublishedElementModel 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "umbBlockGridDemoImageBlock"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Content; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public UmbBlockGridDemoImageBlock(IPublishedElement content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | 52 | /// 53 | /// Image 54 | /// 55 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 56 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 57 | [ImplementPropertyType("image")] 58 | public virtual global::Umbraco.Cms.Core.Models.MediaWithCrops Image => this.Value(_publishedValueFallback, "image"); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/UmbBlockGridDemoRichTextBlock.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// Rich Text 22 | [PublishedModel("umbBlockGridDemoRichTextBlock")] 23 | public partial class UmbBlockGridDemoRichTextBlock : PublishedElementModel 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "umbBlockGridDemoRichTextBlock"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Content; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public UmbBlockGridDemoRichTextBlock(IPublishedElement content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | 52 | /// 53 | /// Text 54 | /// 55 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 56 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 57 | [ImplementPropertyType("richText")] 58 | public virtual global::Umbraco.Cms.Core.Strings.IHtmlEncodedString RichText => this.Value(_publishedValueFallback, "richText"); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/Feature.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// Feature 22 | [PublishedModel("feature")] 23 | public partial class Feature : PublishedElementModel 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "feature"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Content; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public Feature(IPublishedElement content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | 52 | /// 53 | /// Details 54 | /// 55 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 56 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 57 | [ImplementPropertyType("featureDetails")] 58 | public virtual string FeatureDetails => this.Value(_publishedValueFallback, "featureDetails"); 59 | 60 | /// 61 | /// Name 62 | /// 63 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 64 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 65 | [ImplementPropertyType("featureName")] 66 | public virtual string FeatureName => this.Value(_publishedValueFallback, "featureName"); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders.AzureBlob.ImageSharp/DependencyInjection/AddAzureBlobImageSharpCacheExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using Microsoft.Extensions.Options; 3 | using SixLabors.ImageSharp.Web.Caching; 4 | using Umbraco.Extensions; 5 | using Umbraco.StorageProviders.AzureBlob.ImageSharp; 6 | using Umbraco.StorageProviders.AzureBlob.IO; 7 | 8 | namespace Umbraco.Cms.Core.DependencyInjection; 9 | 10 | /// 11 | /// Extension methods to help register an Azure Blob Storage image cache for ImageSharp. 12 | /// 13 | public static class AddAzureBlobImageSharpCacheExtensions 14 | { 15 | private const string ContainerRootPath = "cache"; 16 | 17 | /// 18 | /// Registers an configured using the for media and container root path. 19 | /// 20 | /// The . 21 | /// 22 | /// The . 23 | /// 24 | /// is null. 25 | public static IUmbracoBuilder AddAzureBlobImageSharpCache(this IUmbracoBuilder builder) 26 | => builder.AddInternal(AzureBlobFileSystemOptions.MediaFileSystemName, ContainerRootPath); 27 | 28 | /// 29 | /// Registers an configured using the specified . 30 | /// 31 | /// The . 32 | /// The name of the file system. 33 | /// The container root path (will use if null). 34 | /// 35 | /// The . 36 | /// 37 | /// is null. 38 | public static IUmbracoBuilder AddAzureBlobImageSharpCache(this IUmbracoBuilder builder, string name, string? containerRootPath = null) 39 | => builder.AddInternal(name, containerRootPath); 40 | 41 | /// 42 | /// Registers an configured using the specified . 43 | /// 44 | /// The . 45 | /// The name of the file system. 46 | /// The container root path (will use if null). 47 | /// 48 | /// The . 49 | /// 50 | /// is null. 51 | internal static IUmbracoBuilder AddInternal(this IUmbracoBuilder builder, string name, string? containerRootPath) 52 | { 53 | ArgumentNullException.ThrowIfNull(builder); 54 | 55 | builder.Services.AddUnique(provider => new AzureBlobFileSystemImageCache(provider.GetRequiredService>(), name, containerRootPath)); 56 | 57 | return builder; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders/CdnMediaUrlProvider.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Options; 2 | using Umbraco.Cms.Core.Configuration.Models; 3 | using Umbraco.Cms.Core.Hosting; 4 | using Umbraco.Cms.Core.Models.PublishedContent; 5 | using Umbraco.Cms.Core.PropertyEditors; 6 | using Umbraco.Cms.Core.Routing; 7 | using Umbraco.Extensions; 8 | 9 | namespace Umbraco.StorageProviders; 10 | 11 | /// 12 | /// A that returns a CDN URL for a media item. 13 | /// 14 | /// 15 | public sealed class CdnMediaUrlProvider : DefaultMediaUrlProvider 16 | { 17 | private Uri _cdnUrl; 18 | private bool _removeMediaFromPath; 19 | private string _mediaPath; 20 | 21 | /// 22 | /// Initializes a new instance of the class. 23 | /// 24 | /// The options. 25 | /// The global settings. 26 | /// The hosting environment. 27 | /// The media path generators. 28 | /// The URL assembler. 29 | public CdnMediaUrlProvider(IOptionsMonitor options, IOptionsMonitor globalSettings, IHostingEnvironment hostingEnvironment, MediaUrlGeneratorCollection mediaPathGenerators, IUrlAssembler urlAssembler) 30 | : base(mediaPathGenerators, urlAssembler) 31 | { 32 | ArgumentNullException.ThrowIfNull(options); 33 | ArgumentNullException.ThrowIfNull(globalSettings); 34 | ArgumentNullException.ThrowIfNull(hostingEnvironment); 35 | 36 | _cdnUrl = options.CurrentValue.Url; 37 | _removeMediaFromPath = options.CurrentValue.RemoveMediaFromPath; 38 | _mediaPath = hostingEnvironment.ToAbsolute(globalSettings.CurrentValue.UmbracoMediaPath).EnsureEndsWith('/'); 39 | 40 | options.OnChange((options, name) => 41 | { 42 | if (name == Options.DefaultName) 43 | { 44 | _removeMediaFromPath = options.RemoveMediaFromPath; 45 | _cdnUrl = options.Url; 46 | } 47 | }); 48 | 49 | globalSettings.OnChange((options, name) => 50 | { 51 | if (name == Options.DefaultName) 52 | { 53 | _mediaPath = hostingEnvironment.ToAbsolute(options.UmbracoMediaPath).EnsureEndsWith('/'); 54 | } 55 | }); 56 | } 57 | 58 | /// 59 | public override UrlInfo? GetMediaUrl(IPublishedContent content, string propertyAlias, UrlMode mode, string? culture, Uri current) 60 | { 61 | UrlInfo? mediaUrl = base.GetMediaUrl(content, propertyAlias, UrlMode.Relative, culture, current); 62 | if (mediaUrl?.Url is Uri url) 63 | { 64 | var path = url.ToString(); 65 | 66 | int startIndex = 0; 67 | if (_removeMediaFromPath && path.StartsWith(_mediaPath, StringComparison.OrdinalIgnoreCase)) 68 | { 69 | startIndex = _mediaPath.Length; 70 | } 71 | else if (path.StartsWith('/')) 72 | { 73 | startIndex = 1; 74 | } 75 | 76 | return UrlInfo.AsUrl(_cdnUrl + path[startIndex..], mediaUrl.Provider, mediaUrl.Culture, mediaUrl.IsExternal); 77 | } 78 | 79 | return mediaUrl; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders.AzureBlob/AzureBlobItemInfo.cs: -------------------------------------------------------------------------------- 1 | using Azure.Storage.Blobs; 2 | using Azure.Storage.Blobs.Models; 3 | using Microsoft.Extensions.FileProviders; 4 | 5 | namespace Umbraco.StorageProviders.AzureBlob; 6 | 7 | /// 8 | /// Represents an Azure Blob Storage blob item. 9 | /// 10 | /// 11 | public sealed class AzureBlobItemInfo : IFileInfo 12 | { 13 | private readonly BlobClient _blobClient; 14 | 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// 18 | /// The blob client. 19 | /// The properties. 20 | /// is null. 21 | /// is null. 22 | public AzureBlobItemInfo(BlobClient blobClient, BlobProperties properties) 23 | : this(blobClient) 24 | { 25 | ArgumentNullException.ThrowIfNull(properties); 26 | 27 | LastModified = properties.LastModified; 28 | Length = properties.ContentLength; 29 | } 30 | 31 | /// 32 | /// Initializes a new instance of the class. 33 | /// 34 | /// The blob client. 35 | /// The properties. 36 | /// is null. 37 | /// is null. 38 | public AzureBlobItemInfo(BlobClient blobClient, BlobItemProperties properties) 39 | : this(blobClient) 40 | { 41 | ArgumentNullException.ThrowIfNull(properties); 42 | 43 | LastModified = properties.LastModified.GetValueOrDefault(); 44 | Length = properties.ContentLength.GetValueOrDefault(-1); 45 | } 46 | 47 | /// 48 | /// Initializes a new instance of the class. 49 | /// 50 | /// The blob client. 51 | /// is null. 52 | private AzureBlobItemInfo(BlobClient blobClient) 53 | { 54 | _blobClient = blobClient ?? throw new ArgumentNullException(nameof(blobClient)); 55 | 56 | Name = ParseName(blobClient.Name); 57 | } 58 | 59 | /// 60 | public bool Exists => true; 61 | 62 | /// 63 | public bool IsDirectory => false; 64 | 65 | /// 66 | public DateTimeOffset LastModified { get; } 67 | 68 | /// 69 | public long Length { get; } 70 | 71 | /// 72 | public string Name { get; } 73 | 74 | /// 75 | public string? PhysicalPath => null; 76 | 77 | /// 78 | public Stream CreateReadStream() => _blobClient.OpenRead(); 79 | 80 | /// 81 | /// Parses the name from the file path. 82 | /// 83 | /// The file path. 84 | /// 85 | /// The name. 86 | /// 87 | internal static string ParseName(string path) => path[(path.LastIndexOf('/') + 1)..]; 88 | } 89 | -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders.AzureBlob/AzureBlobFileProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using Azure; 3 | using Azure.Storage.Blobs; 4 | using Azure.Storage.Blobs.Models; 5 | using Microsoft.Extensions.FileProviders; 6 | using Microsoft.Extensions.Primitives; 7 | using Umbraco.Cms.Core; 8 | using Umbraco.Extensions; 9 | using Umbraco.StorageProviders.AzureBlob.IO; 10 | 11 | namespace Umbraco.StorageProviders.AzureBlob; 12 | 13 | /// 14 | /// Represents a read-only Azure Blob Storage file provider. 15 | /// 16 | /// 17 | public sealed class AzureBlobFileProvider : IFileProvider 18 | { 19 | private readonly BlobContainerClient _containerClient; 20 | private readonly string? _containerRootPath; 21 | 22 | /// 23 | /// Initializes a new instance of the class. 24 | /// 25 | /// The container client. 26 | /// The container root path. 27 | /// is null. 28 | public AzureBlobFileProvider(BlobContainerClient containerClient, string? containerRootPath = null) 29 | { 30 | _containerClient = containerClient ?? throw new ArgumentNullException(nameof(containerClient)); 31 | _containerRootPath = containerRootPath?.Trim(Constants.CharArrays.ForwardSlash); 32 | } 33 | 34 | /// 35 | /// Initializes a new instance of the class. 36 | /// 37 | /// The options. 38 | /// is null. 39 | public AzureBlobFileProvider(AzureBlobFileSystemOptions options) 40 | { 41 | ArgumentNullException.ThrowIfNull(options); 42 | 43 | _containerClient = options.CreateBlobContainerClient(); 44 | _containerRootPath = options.ContainerRootPath?.Trim(Constants.CharArrays.ForwardSlash); 45 | } 46 | 47 | /// 48 | public IDirectoryContents GetDirectoryContents(string subpath) 49 | { 50 | var path = GetFullPath(subpath); 51 | 52 | // Get all blobs and iterate to fetch all pages 53 | var blobs = _containerClient.GetBlobsByHierarchy(delimiter: "/", prefix: path).ToList(); 54 | 55 | return blobs.Count == 0 56 | ? NotFoundDirectoryContents.Singleton 57 | : new AzureBlobDirectoryContents(_containerClient, blobs); 58 | } 59 | 60 | /// 61 | public IFileInfo GetFileInfo(string subpath) 62 | { 63 | var path = GetFullPath(subpath); 64 | BlobClient blobClient = _containerClient.GetBlobClient(path); 65 | 66 | BlobProperties properties; 67 | try 68 | { 69 | properties = blobClient.GetProperties().Value; 70 | } 71 | catch (RequestFailedException ex) when (ex.Status == (int)HttpStatusCode.NotFound) 72 | { 73 | return new NotFoundFileInfo(AzureBlobItemInfo.ParseName(path)); 74 | } 75 | 76 | return new AzureBlobItemInfo(blobClient, properties); 77 | } 78 | 79 | /// 80 | public IChangeToken Watch(string filter) => NullChangeToken.Singleton; 81 | 82 | private string GetFullPath(string subpath) => _containerRootPath + subpath.EnsureStartsWith('/'); 83 | } 84 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/LatestBlogposts.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// Latest Blogposts 22 | [PublishedModel("latestBlogposts")] 23 | public partial class LatestBlogposts : PublishedElementModel 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "latestBlogposts"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Content; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public LatestBlogposts(IPublishedElement content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | 52 | /// 53 | /// How many posts should be shown? 54 | /// 55 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 56 | [ImplementPropertyType("numberOfPosts")] 57 | public virtual decimal NumberOfPosts => this.Value(_publishedValueFallback, "numberOfPosts"); 58 | 59 | /// 60 | /// Which posts should be shown? 61 | /// 62 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 63 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 64 | [ImplementPropertyType("startNode")] 65 | public virtual global::Umbraco.Cms.Core.Models.PublishedContent.IPublishedContent StartNode => this.Value(_publishedValueFallback, "startNode"); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/File.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// File 22 | [PublishedModel("File")] 23 | public partial class File : PublishedContentModel 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "File"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Media; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public File(IPublishedContent content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | 52 | /// 53 | /// File size 54 | /// 55 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 56 | [ImplementPropertyType("umbracoBytes")] 57 | public virtual long UmbracoBytes => this.Value(_publishedValueFallback, "umbracoBytes"); 58 | 59 | /// 60 | /// File extension 61 | /// 62 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 63 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 64 | [ImplementPropertyType("umbracoExtension")] 65 | public virtual string UmbracoExtension => this.Value(_publishedValueFallback, "umbracoExtension"); 66 | 67 | /// 68 | /// File 69 | /// 70 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 71 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 72 | [ImplementPropertyType("umbracoFile")] 73 | public virtual string UmbracoFile => this.Value(_publishedValueFallback, "umbracoFile"); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/UmbracoMediaAudio.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// Audio 22 | [PublishedModel("umbracoMediaAudio")] 23 | public partial class UmbracoMediaAudio : PublishedContentModel 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "umbracoMediaAudio"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Media; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public UmbracoMediaAudio(IPublishedContent content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | 52 | /// 53 | /// File size 54 | /// 55 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 56 | [ImplementPropertyType("umbracoBytes")] 57 | public virtual long UmbracoBytes => this.Value(_publishedValueFallback, "umbracoBytes"); 58 | 59 | /// 60 | /// File extension 61 | /// 62 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 63 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 64 | [ImplementPropertyType("umbracoExtension")] 65 | public virtual string UmbracoExtension => this.Value(_publishedValueFallback, "umbracoExtension"); 66 | 67 | /// 68 | /// Audio 69 | /// 70 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 71 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 72 | [ImplementPropertyType("umbracoFile")] 73 | public virtual string UmbracoFile => this.Value(_publishedValueFallback, "umbracoFile"); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/UmbracoMediaVideo.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// Video 22 | [PublishedModel("umbracoMediaVideo")] 23 | public partial class UmbracoMediaVideo : PublishedContentModel 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "umbracoMediaVideo"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Media; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public UmbracoMediaVideo(IPublishedContent content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | 52 | /// 53 | /// File size 54 | /// 55 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 56 | [ImplementPropertyType("umbracoBytes")] 57 | public virtual long UmbracoBytes => this.Value(_publishedValueFallback, "umbracoBytes"); 58 | 59 | /// 60 | /// File extension 61 | /// 62 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 63 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 64 | [ImplementPropertyType("umbracoExtension")] 65 | public virtual string UmbracoExtension => this.Value(_publishedValueFallback, "umbracoExtension"); 66 | 67 | /// 68 | /// Video 69 | /// 70 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 71 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 72 | [ImplementPropertyType("umbracoFile")] 73 | public virtual string UmbracoFile => this.Value(_publishedValueFallback, "umbracoFile"); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/UmbracoMediaArticle.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// Article 22 | [PublishedModel("umbracoMediaArticle")] 23 | public partial class UmbracoMediaArticle : PublishedContentModel 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "umbracoMediaArticle"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Media; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public UmbracoMediaArticle(IPublishedContent content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | 52 | /// 53 | /// File size 54 | /// 55 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 56 | [ImplementPropertyType("umbracoBytes")] 57 | public virtual long UmbracoBytes => this.Value(_publishedValueFallback, "umbracoBytes"); 58 | 59 | /// 60 | /// File extension 61 | /// 62 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 63 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 64 | [ImplementPropertyType("umbracoExtension")] 65 | public virtual string UmbracoExtension => this.Value(_publishedValueFallback, "umbracoExtension"); 66 | 67 | /// 68 | /// Article 69 | /// 70 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 71 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 72 | [ImplementPropertyType("umbracoFile")] 73 | public virtual string UmbracoFile => this.Value(_publishedValueFallback, "umbracoFile"); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/UmbracoMediaVectorGraphics.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// Vector Graphics (SVG) 22 | [PublishedModel("umbracoMediaVectorGraphics")] 23 | public partial class UmbracoMediaVectorGraphics : PublishedContentModel 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "umbracoMediaVectorGraphics"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Media; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public UmbracoMediaVectorGraphics(IPublishedContent content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | 52 | /// 53 | /// File size 54 | /// 55 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 56 | [ImplementPropertyType("umbracoBytes")] 57 | public virtual long UmbracoBytes => this.Value(_publishedValueFallback, "umbracoBytes"); 58 | 59 | /// 60 | /// File extension 61 | /// 62 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 63 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 64 | [ImplementPropertyType("umbracoExtension")] 65 | public virtual string UmbracoExtension => this.Value(_publishedValueFallback, "umbracoExtension"); 66 | 67 | /// 68 | /// Vector Graphics 69 | /// 70 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 71 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 72 | [ImplementPropertyType("umbracoFile")] 73 | public virtual string UmbracoFile => this.Value(_publishedValueFallback, "umbracoFile"); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders.AzureBlob.ImageSharp/AzureBlobFileSystemImageCache.cs: -------------------------------------------------------------------------------- 1 | using Azure.Storage.Blobs; 2 | using Azure.Storage.Blobs.Models; 3 | using Microsoft.Extensions.Options; 4 | using SixLabors.ImageSharp.Web; 5 | using SixLabors.ImageSharp.Web.Caching; 6 | using SixLabors.ImageSharp.Web.Resolvers; 7 | using SixLabors.ImageSharp.Web.Resolvers.Azure; 8 | using Umbraco.Extensions; 9 | using Umbraco.StorageProviders.AzureBlob.IO; 10 | 11 | namespace Umbraco.StorageProviders.AzureBlob.ImageSharp; 12 | 13 | /// 14 | /// Implements an Azure Blob Storage based cache storing files in a cache subfolder. 15 | /// 16 | public sealed class AzureBlobFileSystemImageCache : IImageCache 17 | { 18 | private BlobContainerClient _container; 19 | private string? _containerRootPath; 20 | 21 | /// 22 | /// Initializes a new instance of the class. 23 | /// 24 | /// The options. 25 | /// The name. 26 | /// The container root path (will use if null). 27 | /// is null. 28 | public AzureBlobFileSystemImageCache(IOptionsMonitor options, string name, string? containerRootPath) 29 | { 30 | ArgumentNullException.ThrowIfNull(options); 31 | ArgumentNullException.ThrowIfNull(name); 32 | 33 | AzureBlobFileSystemOptions fileSystemOptions = options.Get(name); 34 | _container = fileSystemOptions.CreateBlobContainerClient(); 35 | _containerRootPath = GetContainerRootPath(containerRootPath, fileSystemOptions); 36 | 37 | options.OnChange((options, changedName) => 38 | { 39 | if (changedName == name) 40 | { 41 | _container = options.CreateBlobContainerClient(); 42 | _containerRootPath = GetContainerRootPath(containerRootPath, options); 43 | } 44 | }); 45 | } 46 | 47 | /// 48 | /// Initializes a new instance of the class. 49 | /// 50 | /// The blob container client. 51 | /// The container root path. 52 | /// is null. 53 | public AzureBlobFileSystemImageCache(BlobContainerClient blobContainerClient, string? containerRootPath) 54 | { 55 | _container = blobContainerClient ?? throw new ArgumentNullException(nameof(blobContainerClient)); 56 | _containerRootPath = GetContainerRootPath(containerRootPath); 57 | } 58 | 59 | /// 60 | public async Task GetAsync(string key) 61 | { 62 | BlobClient blob = _container.GetBlobClient(_containerRootPath + key); 63 | 64 | return !await blob.ExistsAsync().ConfigureAwait(false) 65 | ? null 66 | : new AzureBlobStorageCacheResolver(blob); 67 | } 68 | 69 | /// 70 | public async Task SetAsync(string key, Stream stream, ImageCacheMetadata metadata) 71 | { 72 | BlobClient blob = _container.GetBlobClient(_containerRootPath + key); 73 | 74 | await blob.UploadAsync(stream, new BlobUploadOptions() 75 | { 76 | Metadata = metadata.ToDictionary() 77 | }).ConfigureAwait(false); 78 | } 79 | 80 | private static string? GetContainerRootPath(string? containerRootPath, AzureBlobFileSystemOptions? options = null) 81 | { 82 | var path = containerRootPath ?? options?.ContainerRootPath; 83 | 84 | return string.IsNullOrEmpty(path) ? null : path.EnsureEndsWith('/'); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders.AzureBlob/IO/AzureBlobFileSystemOptionsExtensions.cs: -------------------------------------------------------------------------------- 1 | using Azure.Storage.Blobs; 2 | 3 | namespace Umbraco.StorageProviders.AzureBlob.IO; 4 | 5 | /// 6 | /// Extension methods for . 7 | /// 8 | public static class AzureBlobFileSystemOptionsExtensions 9 | { 10 | /// 11 | /// Creates a using the default constructor accepting a connection string and container name. 12 | /// 13 | /// The Azure Blob File System options. 14 | /// is null. 15 | public static void CreateBlobContainerClientUsingDefault(this AzureBlobFileSystemOptions options) 16 | { 17 | ArgumentNullException.ThrowIfNull(options); 18 | 19 | options.BlobContainerClientFactory = AzureBlobFileSystemOptions.DefaultBlobContainerClientFactory; 20 | } 21 | 22 | /// 23 | /// Creates a using the default constructor accepting a connection string, container name and Blob client options. 24 | /// 25 | /// The Azure Blob File System options. 26 | /// The Azure Blob client options. 27 | /// is null. 28 | public static void CreateBlobContainerClientUsingOptions(this AzureBlobFileSystemOptions options, BlobClientOptions blobClientOptions) 29 | { 30 | ArgumentNullException.ThrowIfNull(options); 31 | 32 | options.BlobContainerClientFactory = options => new BlobContainerClient(options.ConnectionString, options.ContainerName, blobClientOptions); 33 | } 34 | 35 | /// 36 | /// Parses the connection string to a URI and invokes the delegate to create a . 37 | /// 38 | /// The Azure Blob File System options. 39 | /// The delegate to create a from the parsed . 40 | /// 41 | /// If the connection string can't be parsed to a URI, the existing delegate will be used instead. 42 | /// 43 | /// is null. 44 | public static void TryCreateBlobContainerClientUsingUri(this AzureBlobFileSystemOptions options, Func create) 45 | { 46 | ArgumentNullException.ThrowIfNull(options); 47 | 48 | Func defaultCreate = options.BlobContainerClientFactory; 49 | options.BlobContainerClientFactory = options => 50 | { 51 | if (Uri.TryCreate(options.ConnectionString, UriKind.Absolute, out Uri? blobContainerUri)) 52 | { 53 | var blobUriBuilder = new BlobUriBuilder(blobContainerUri) 54 | { 55 | BlobContainerName = options.ContainerName 56 | }; 57 | 58 | return create(blobUriBuilder.ToUri()); 59 | } 60 | 61 | return defaultCreate(options); 62 | }; 63 | } 64 | 65 | /// 66 | /// Creates the Azure Blob Container client using the configured factory. 67 | /// 68 | /// The Azure Blob File System options. 69 | /// 70 | /// The Azure Blob Container client. 71 | /// 72 | /// is null. 73 | public static BlobContainerClient CreateBlobContainerClient(this AzureBlobFileSystemOptions options) 74 | { 75 | ArgumentNullException.ThrowIfNull(options); 76 | 77 | return options.BlobContainerClientFactory(options); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders.AzureBlob/DependencyInjection/AzureBlobMediaFileSystemExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using Microsoft.Extensions.Options; 3 | using Umbraco.Cms.Core.Configuration.Models; 4 | using Umbraco.Cms.Infrastructure.DependencyInjection; 5 | using Umbraco.StorageProviders.AzureBlob.IO; 6 | 7 | namespace Umbraco.Cms.Core.DependencyInjection; 8 | 9 | /// 10 | /// Extension methods to help registering Azure Blob Storage file systems for Umbraco media. 11 | /// 12 | public static class AzureBlobMediaFileSystemExtensions 13 | { 14 | /// 15 | /// Registers an and it's dependencies configured for media. 16 | /// 17 | /// The . 18 | /// 19 | /// The . 20 | /// 21 | /// is null. 22 | public static IUmbracoBuilder AddAzureBlobMediaFileSystem(this IUmbracoBuilder builder) 23 | => builder.AddInternal(); 24 | 25 | /// 26 | /// Registers a and it's dependencies configured for media. 27 | /// 28 | /// The . 29 | /// An action used to configure the . 30 | /// 31 | /// The . 32 | /// 33 | /// is null. 34 | public static IUmbracoBuilder AddAzureBlobMediaFileSystem(this IUmbracoBuilder builder, Action configure) 35 | => builder.AddInternal(x => x.Configure(configure)); 36 | 37 | /// 38 | /// Registers a and it's dependencies configured for media. 39 | /// 40 | /// A dependency used by the configure action. 41 | /// The . 42 | /// An action used to configure the . 43 | /// 44 | /// The . 45 | /// 46 | /// is null. 47 | public static IUmbracoBuilder AddAzureBlobFileSystem(this IUmbracoBuilder builder, Action configure) 48 | where TDep : class 49 | => builder.AddInternal(x => x.Configure(configure)); 50 | 51 | /// 52 | /// Registers a and it's dependencies configured for media. 53 | /// 54 | /// The . 55 | /// An action used to configure the . 56 | /// 57 | /// The . 58 | /// 59 | /// is null. 60 | internal static IUmbracoBuilder AddInternal(this IUmbracoBuilder builder, Action>? configure = null) 61 | { 62 | ArgumentNullException.ThrowIfNull(builder); 63 | 64 | builder.AddInternal(AzureBlobFileSystemOptions.MediaFileSystemName, optionsBuilder => 65 | { 66 | optionsBuilder.Configure>((options, globalSettings) => options.VirtualPath = globalSettings.Value.UmbracoMediaPath); 67 | configure?.Invoke(optionsBuilder); 68 | }); 69 | 70 | builder.SetMediaFileSystem(provider => provider.GetRequiredService().GetFileSystem(AzureBlobFileSystemOptions.MediaFileSystemName)); 71 | 72 | return builder; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/Image.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// Image 22 | [PublishedModel("Image")] 23 | public partial class Image : PublishedContentModel 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "Image"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Media; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public Image(IPublishedContent content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | 52 | /// 53 | /// File size 54 | /// 55 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 56 | [ImplementPropertyType("umbracoBytes")] 57 | public virtual long UmbracoBytes => this.Value(_publishedValueFallback, "umbracoBytes"); 58 | 59 | /// 60 | /// File extension 61 | /// 62 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 63 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 64 | [ImplementPropertyType("umbracoExtension")] 65 | public virtual string UmbracoExtension => this.Value(_publishedValueFallback, "umbracoExtension"); 66 | 67 | /// 68 | /// Image 69 | /// 70 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 71 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 72 | [ImplementPropertyType("umbracoFile")] 73 | public virtual global::Umbraco.Cms.Core.PropertyEditors.ValueConverters.ImageCropperValue UmbracoFile => this.Value(_publishedValueFallback, "umbracoFile"); 74 | 75 | /// 76 | /// Height 77 | /// 78 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 79 | [ImplementPropertyType("umbracoHeight")] 80 | public virtual int UmbracoHeight => this.Value(_publishedValueFallback, "umbracoHeight"); 81 | 82 | /// 83 | /// Width 84 | /// 85 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 86 | [ImplementPropertyType("umbracoWidth")] 87 | public virtual int UmbracoWidth => this.Value(_publishedValueFallback, "umbracoWidth"); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders/DependencyInjection/CdnMediaUrlProviderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using Microsoft.Extensions.Options; 3 | using Umbraco.Cms.Core.Configuration.Models; 4 | using Umbraco.StorageProviders; 5 | 6 | namespace Umbraco.Cms.Core.DependencyInjection; 7 | 8 | /// 9 | /// Extension methods to help registering a CDN media URL provider. 10 | /// 11 | public static class CdnMediaUrlProviderExtensions 12 | { 13 | /// 14 | /// Registers and configures the . 15 | /// 16 | /// The . 17 | /// 18 | /// The . 19 | /// 20 | /// is null. 21 | public static IUmbracoBuilder AddCdnMediaUrlProvider(this IUmbracoBuilder builder) 22 | => builder.AddInternal(); 23 | 24 | /// 25 | /// Registers and configures the . 26 | /// 27 | /// The . 28 | /// An action used to configure the . 29 | /// 30 | /// The . 31 | /// 32 | /// is null. 33 | public static IUmbracoBuilder AddCdnMediaUrlProvider(this IUmbracoBuilder builder, Action configure) 34 | => builder.AddInternal(optionsBuilder => optionsBuilder.Configure(configure)); 35 | 36 | /// 37 | /// Registers and configures the . 38 | /// 39 | /// The . 40 | /// An action used to configure the . 41 | /// 42 | /// The . 43 | /// 44 | /// is null. 45 | public static IUmbracoBuilder AddCdnMediaUrlProvider(this IUmbracoBuilder builder, Action configure) 46 | => builder.AddInternal(optionsBuilder => optionsBuilder.Configure(configure)); 47 | 48 | /// 49 | /// Registers and configures the . 50 | /// 51 | /// A dependency used by the configure action. 52 | /// The . 53 | /// An action used to configure the . 54 | /// 55 | /// The . 56 | /// 57 | /// is null. 58 | public static IUmbracoBuilder AddCdnMediaUrlProvider(this IUmbracoBuilder builder, Action configure) 59 | where TDep : class 60 | => builder.AddInternal(optionsBuilder => optionsBuilder.Configure(configure)); 61 | 62 | /// 63 | /// Registers and configures the . 64 | /// 65 | /// The . 66 | /// An action used to configure the . 67 | /// 68 | /// The . 69 | /// 70 | /// is null. 71 | internal static IUmbracoBuilder AddInternal(this IUmbracoBuilder builder, Action>? configure = null) 72 | { 73 | ArgumentNullException.ThrowIfNull(builder); 74 | 75 | builder.MediaUrlProviders().Insert(); 76 | 77 | OptionsBuilder optionsBuilder = builder.Services.AddOptions() 78 | .BindConfiguration("Umbraco:Storage:Cdn") 79 | .ValidateDataAnnotations(); 80 | 81 | configure?.Invoke(optionsBuilder); 82 | 83 | // Configure CDN as allowed media host 84 | builder.Services.AddOptions().PostConfigure>((options, cdnMediaUrlProviderOptions) => 85 | { 86 | options.AllowedMediaHosts.Add(cdnMediaUrlProviderOptions.Value.Url.Host); 87 | }); 88 | 89 | return builder; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/ContentBase.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | // Mixin Content Type with alias "contentBase" 22 | /// Content Base 23 | public partial interface IContentBase : IPublishedContent 24 | { 25 | /// Content 26 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 27 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 28 | global::Umbraco.Cms.Core.Models.Blocks.BlockGridModel BodyText { get; } 29 | 30 | /// Page Title 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | string PageTitle { get; } 34 | } 35 | 36 | /// Content Base 37 | [PublishedModel("contentBase")] 38 | public partial class ContentBase : PublishedContentModel, IContentBase 39 | { 40 | // helpers 41 | #pragma warning disable 0109 // new is redundant 42 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 43 | public new const string ModelTypeAlias = "contentBase"; 44 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 45 | public new const PublishedItemType ModelItemType = PublishedItemType.Content; 46 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 47 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 48 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 49 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 50 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 51 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 52 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 53 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 54 | #pragma warning restore 0109 55 | 56 | private IPublishedValueFallback _publishedValueFallback; 57 | 58 | // ctor 59 | public ContentBase(IPublishedContent content, IPublishedValueFallback publishedValueFallback) 60 | : base(content, publishedValueFallback) 61 | { 62 | _publishedValueFallback = publishedValueFallback; 63 | } 64 | 65 | // properties 66 | 67 | /// 68 | /// Content 69 | /// 70 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 71 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 72 | [ImplementPropertyType("bodyText")] 73 | public virtual global::Umbraco.Cms.Core.Models.Blocks.BlockGridModel BodyText => GetBodyText(this, _publishedValueFallback); 74 | 75 | /// Static getter for Content 76 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 77 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 78 | public static global::Umbraco.Cms.Core.Models.Blocks.BlockGridModel GetBodyText(IContentBase that, IPublishedValueFallback publishedValueFallback) => that.Value(publishedValueFallback, "bodyText"); 79 | 80 | /// 81 | /// Page Title: The title of the page, this is also the first text in a google search result. The ideal length is between 40 and 60 characters 82 | /// 83 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 84 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 85 | [ImplementPropertyType("pageTitle")] 86 | public virtual string PageTitle => GetPageTitle(this, _publishedValueFallback); 87 | 88 | /// Static getter for Page Title 89 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 90 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 91 | public static string GetPageTitle(IContentBase that, IPublishedValueFallback publishedValueFallback) => that.Value(publishedValueFallback, "pageTitle"); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/ContentPage.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// Content Page 22 | [PublishedModel("contentPage")] 23 | public partial class ContentPage : PublishedContentModel, IContentBase, INavigationBase 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "contentPage"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Content; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public ContentPage(IPublishedContent content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | 52 | /// 53 | /// Content 54 | /// 55 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 56 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 57 | [ImplementPropertyType("bodyText")] 58 | public virtual global::Umbraco.Cms.Core.Models.Blocks.BlockGridModel BodyText => global::Umbraco.Cms.Web.Common.PublishedModels.ContentBase.GetBodyText(this, _publishedValueFallback); 59 | 60 | /// 61 | /// Page Title: The title of the page, this is also the first text in a google search result. The ideal length is between 40 and 60 characters 62 | /// 63 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 64 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 65 | [ImplementPropertyType("pageTitle")] 66 | public virtual string PageTitle => global::Umbraco.Cms.Web.Common.PublishedModels.ContentBase.GetPageTitle(this, _publishedValueFallback); 67 | 68 | /// 69 | /// Keywords: Keywords that describe the content of the page. This is considered optional since most modern search engines don't use this anymore 70 | /// 71 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 72 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 73 | [ImplementPropertyType("keywords")] 74 | public virtual global::System.Collections.Generic.IEnumerable Keywords => global::Umbraco.Cms.Web.Common.PublishedModels.NavigationBase.GetKeywords(this, _publishedValueFallback); 75 | 76 | /// 77 | /// Description: A brief description of the content on your page. This text is shown below the title in a google search result and also used for Social Sharing Cards. The ideal length is between 130 and 155 characters 78 | /// 79 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 80 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 81 | [ImplementPropertyType("seoMetaDescription")] 82 | public virtual string SeoMetaDescription => global::Umbraco.Cms.Web.Common.PublishedModels.NavigationBase.GetSeoMetaDescription(this, _publishedValueFallback); 83 | 84 | /// 85 | /// Hide in Navigation: If you don't want this page to appear in the navigation, check this box 86 | /// 87 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 88 | [ImplementPropertyType("umbracoNavihide")] 89 | public virtual bool UmbracoNavihide => global::Umbraco.Cms.Web.Common.PublishedModels.NavigationBase.GetUmbracoNavihide(this, _publishedValueFallback); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/Product.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// Product 22 | [PublishedModel("product")] 23 | public partial class Product : PublishedContentModel 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "product"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Content; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public Product(IPublishedContent content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | 52 | /// 53 | /// Content 54 | /// 55 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 56 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 57 | [ImplementPropertyType("bodyText")] 58 | public virtual global::Umbraco.Cms.Core.Models.Blocks.BlockGridModel BodyText => this.Value(_publishedValueFallback, "bodyText"); 59 | 60 | /// 61 | /// Category 62 | /// 63 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 64 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 65 | [ImplementPropertyType("category")] 66 | public virtual global::System.Collections.Generic.IEnumerable Category => this.Value>(_publishedValueFallback, "category"); 67 | 68 | /// 69 | /// Description 70 | /// 71 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 72 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 73 | [ImplementPropertyType("description")] 74 | public virtual string Description => this.Value(_publishedValueFallback, "description"); 75 | 76 | /// 77 | /// Features 78 | /// 79 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 80 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 81 | [ImplementPropertyType("features")] 82 | public virtual global::Umbraco.Cms.Core.Models.Blocks.BlockListModel Features => this.Value(_publishedValueFallback, "features"); 83 | 84 | /// 85 | /// Photos 86 | /// 87 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 88 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 89 | [ImplementPropertyType("photos")] 90 | public virtual global::Umbraco.Cms.Core.Models.MediaWithCrops Photos => this.Value(_publishedValueFallback, "photos"); 91 | 92 | /// 93 | /// Price 94 | /// 95 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 96 | [ImplementPropertyType("price")] 97 | public virtual decimal Price => this.Value(_publishedValueFallback, "price"); 98 | 99 | /// 100 | /// Product Name 101 | /// 102 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 103 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 104 | [ImplementPropertyType("productName")] 105 | public virtual string ProductName => this.Value(_publishedValueFallback, "productName"); 106 | 107 | /// 108 | /// SKU 109 | /// 110 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 111 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 112 | [ImplementPropertyType("sku")] 113 | public virtual string Sku => this.Value(_publishedValueFallback, "sku"); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/People.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// People 22 | [PublishedModel("people")] 23 | public partial class People : PublishedContentModel, IContentBase, INavigationBase 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "people"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Content; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public People(IPublishedContent content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | 52 | /// 53 | /// Featured People 54 | /// 55 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 56 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 57 | [ImplementPropertyType("featuredPeople")] 58 | public virtual global::System.Collections.Generic.IEnumerable FeaturedPeople => this.Value>(_publishedValueFallback, "featuredPeople"); 59 | 60 | /// 61 | /// Content 62 | /// 63 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 64 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 65 | [ImplementPropertyType("bodyText")] 66 | public virtual global::Umbraco.Cms.Core.Models.Blocks.BlockGridModel BodyText => global::Umbraco.Cms.Web.Common.PublishedModels.ContentBase.GetBodyText(this, _publishedValueFallback); 67 | 68 | /// 69 | /// Page Title: The title of the page, this is also the first text in a google search result. The ideal length is between 40 and 60 characters 70 | /// 71 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 72 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 73 | [ImplementPropertyType("pageTitle")] 74 | public virtual string PageTitle => global::Umbraco.Cms.Web.Common.PublishedModels.ContentBase.GetPageTitle(this, _publishedValueFallback); 75 | 76 | /// 77 | /// Keywords: Keywords that describe the content of the page. This is considered optional since most modern search engines don't use this anymore 78 | /// 79 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 80 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 81 | [ImplementPropertyType("keywords")] 82 | public virtual global::System.Collections.Generic.IEnumerable Keywords => global::Umbraco.Cms.Web.Common.PublishedModels.NavigationBase.GetKeywords(this, _publishedValueFallback); 83 | 84 | /// 85 | /// Description: A brief description of the content on your page. This text is shown below the title in a google search result and also used for Social Sharing Cards. The ideal length is between 130 and 155 characters 86 | /// 87 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 88 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 89 | [ImplementPropertyType("seoMetaDescription")] 90 | public virtual string SeoMetaDescription => global::Umbraco.Cms.Web.Common.PublishedModels.NavigationBase.GetSeoMetaDescription(this, _publishedValueFallback); 91 | 92 | /// 93 | /// Hide in Navigation: If you don't want this page to appear in the navigation, check this box 94 | /// 95 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 96 | [ImplementPropertyType("umbracoNavihide")] 97 | public virtual bool UmbracoNavihide => global::Umbraco.Cms.Web.Common.PublishedModels.NavigationBase.GetUmbracoNavihide(this, _publishedValueFallback); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/Blogpost.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// Blogpost 22 | [PublishedModel("blogpost")] 23 | public partial class Blogpost : PublishedContentModel, INavigationBase 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "blogpost"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Content; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public Blogpost(IPublishedContent content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | 52 | /// 53 | /// Content 54 | /// 55 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 56 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 57 | [ImplementPropertyType("bodyText")] 58 | public virtual global::Umbraco.Cms.Core.Models.Blocks.BlockGridModel BodyText => this.Value(_publishedValueFallback, "bodyText"); 59 | 60 | /// 61 | /// Categories (tags) 62 | /// 63 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 64 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 65 | [ImplementPropertyType("categories")] 66 | public virtual global::System.Collections.Generic.IEnumerable Categories => this.Value>(_publishedValueFallback, "categories"); 67 | 68 | /// 69 | /// Excerpt: Introduction to your blog post. This is also used in the summaries on the front of the blog as well as the homepage 70 | /// 71 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 72 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 73 | [ImplementPropertyType("excerpt")] 74 | public virtual string Excerpt => this.Value(_publishedValueFallback, "excerpt"); 75 | 76 | /// 77 | /// Page Title: The title of the page, this is also the first text in a google search result. The ideal length is between 40 and 60 characters 78 | /// 79 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 80 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 81 | [ImplementPropertyType("pageTitle")] 82 | public virtual string PageTitle => this.Value(_publishedValueFallback, "pageTitle"); 83 | 84 | /// 85 | /// Keywords: Keywords that describe the content of the page. This is considered optional since most modern search engines don't use this anymore 86 | /// 87 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 88 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 89 | [ImplementPropertyType("keywords")] 90 | public virtual global::System.Collections.Generic.IEnumerable Keywords => global::Umbraco.Cms.Web.Common.PublishedModels.NavigationBase.GetKeywords(this, _publishedValueFallback); 91 | 92 | /// 93 | /// Description: A brief description of the content on your page. This text is shown below the title in a google search result and also used for Social Sharing Cards. The ideal length is between 130 and 155 characters 94 | /// 95 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 96 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 97 | [ImplementPropertyType("seoMetaDescription")] 98 | public virtual string SeoMetaDescription => global::Umbraco.Cms.Web.Common.PublishedModels.NavigationBase.GetSeoMetaDescription(this, _publishedValueFallback); 99 | 100 | /// 101 | /// Hide in Navigation: If you don't want this page to appear in the navigation, check this box 102 | /// 103 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 104 | [ImplementPropertyType("umbracoNavihide")] 105 | public virtual bool UmbracoNavihide => global::Umbraco.Cms.Web.Common.PublishedModels.NavigationBase.GetUmbracoNavihide(this, _publishedValueFallback); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/Blog.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// Blog 22 | [PublishedModel("blog")] 23 | public partial class Blog : PublishedContentModel, IContentBase, INavigationBase 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "blog"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Content; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public Blog(IPublishedContent content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | 52 | /// 53 | /// Disqus Shortname: To use comments, you'll need to sign up for Disqus and enter your shortname here (more info: https://help.disqus.com/customer/portal/articles/472097-universal-embed-code) 54 | /// 55 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 56 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 57 | [ImplementPropertyType("disqusShortname")] 58 | public virtual string DisqusShortname => this.Value(_publishedValueFallback, "disqusShortname"); 59 | 60 | /// 61 | /// How many posts should be shown? 62 | /// 63 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 64 | [ImplementPropertyType("howManyPostsShouldBeShown")] 65 | public virtual decimal HowManyPostsShouldBeShown => this.Value(_publishedValueFallback, "howManyPostsShouldBeShown"); 66 | 67 | /// 68 | /// Content 69 | /// 70 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 71 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 72 | [ImplementPropertyType("bodyText")] 73 | public virtual global::Umbraco.Cms.Core.Models.Blocks.BlockGridModel BodyText => global::Umbraco.Cms.Web.Common.PublishedModels.ContentBase.GetBodyText(this, _publishedValueFallback); 74 | 75 | /// 76 | /// Page Title: The title of the page, this is also the first text in a google search result. The ideal length is between 40 and 60 characters 77 | /// 78 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 79 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 80 | [ImplementPropertyType("pageTitle")] 81 | public virtual string PageTitle => global::Umbraco.Cms.Web.Common.PublishedModels.ContentBase.GetPageTitle(this, _publishedValueFallback); 82 | 83 | /// 84 | /// Keywords: Keywords that describe the content of the page. This is considered optional since most modern search engines don't use this anymore 85 | /// 86 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 87 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 88 | [ImplementPropertyType("keywords")] 89 | public virtual global::System.Collections.Generic.IEnumerable Keywords => global::Umbraco.Cms.Web.Common.PublishedModels.NavigationBase.GetKeywords(this, _publishedValueFallback); 90 | 91 | /// 92 | /// Description: A brief description of the content on your page. This text is shown below the title in a google search result and also used for Social Sharing Cards. The ideal length is between 130 and 155 characters 93 | /// 94 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 95 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 96 | [ImplementPropertyType("seoMetaDescription")] 97 | public virtual string SeoMetaDescription => global::Umbraco.Cms.Web.Common.PublishedModels.NavigationBase.GetSeoMetaDescription(this, _publishedValueFallback); 98 | 99 | /// 100 | /// Hide in Navigation: If you don't want this page to appear in the navigation, check this box 101 | /// 102 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 103 | [ImplementPropertyType("umbracoNavihide")] 104 | public virtual bool UmbracoNavihide => global::Umbraco.Cms.Web.Common.PublishedModels.NavigationBase.GetUmbracoNavihide(this, _publishedValueFallback); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/Products.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// Products 22 | [PublishedModel("products")] 23 | public partial class Products : PublishedContentModel, IContentBase, INavigationBase 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "products"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Content; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public Products(IPublishedContent content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | 52 | /// 53 | /// Default Currency: This is just used to prefix pricing 54 | /// 55 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 56 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 57 | [ImplementPropertyType("defaultCurrency")] 58 | public virtual string DefaultCurrency => this.Value(_publishedValueFallback, "defaultCurrency"); 59 | 60 | /// 61 | /// Featured Products 62 | /// 63 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 64 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 65 | [ImplementPropertyType("featuredProducts")] 66 | public virtual global::System.Collections.Generic.IEnumerable FeaturedProducts => this.Value>(_publishedValueFallback, "featuredProducts"); 67 | 68 | /// 69 | /// Content 70 | /// 71 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 72 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 73 | [ImplementPropertyType("bodyText")] 74 | public virtual global::Umbraco.Cms.Core.Models.Blocks.BlockGridModel BodyText => global::Umbraco.Cms.Web.Common.PublishedModels.ContentBase.GetBodyText(this, _publishedValueFallback); 75 | 76 | /// 77 | /// Page Title: The title of the page, this is also the first text in a google search result. The ideal length is between 40 and 60 characters 78 | /// 79 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 80 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 81 | [ImplementPropertyType("pageTitle")] 82 | public virtual string PageTitle => global::Umbraco.Cms.Web.Common.PublishedModels.ContentBase.GetPageTitle(this, _publishedValueFallback); 83 | 84 | /// 85 | /// Keywords: Keywords that describe the content of the page. This is considered optional since most modern search engines don't use this anymore 86 | /// 87 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 88 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 89 | [ImplementPropertyType("keywords")] 90 | public virtual global::System.Collections.Generic.IEnumerable Keywords => global::Umbraco.Cms.Web.Common.PublishedModels.NavigationBase.GetKeywords(this, _publishedValueFallback); 91 | 92 | /// 93 | /// Description: A brief description of the content on your page. This text is shown below the title in a google search result and also used for Social Sharing Cards. The ideal length is between 130 and 155 characters 94 | /// 95 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 96 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 97 | [ImplementPropertyType("seoMetaDescription")] 98 | public virtual string SeoMetaDescription => global::Umbraco.Cms.Web.Common.PublishedModels.NavigationBase.GetSeoMetaDescription(this, _publishedValueFallback); 99 | 100 | /// 101 | /// Hide in Navigation: If you don't want this page to appear in the navigation, check this box 102 | /// 103 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 104 | [ImplementPropertyType("umbracoNavihide")] 105 | public virtual bool UmbracoNavihide => global::Umbraco.Cms.Web.Common.PublishedModels.NavigationBase.GetUmbracoNavihide(this, _publishedValueFallback); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/NavigationBase.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | // Mixin Content Type with alias "navigationBase" 22 | /// Navigation Base 23 | public partial interface INavigationBase : IPublishedContent 24 | { 25 | /// Keywords 26 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 27 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 28 | global::System.Collections.Generic.IEnumerable Keywords { get; } 29 | 30 | /// Description 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | string SeoMetaDescription { get; } 34 | 35 | /// Hide in Navigation 36 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 37 | bool UmbracoNavihide { get; } 38 | } 39 | 40 | /// Navigation Base 41 | [PublishedModel("navigationBase")] 42 | public partial class NavigationBase : PublishedContentModel, INavigationBase 43 | { 44 | // helpers 45 | #pragma warning disable 0109 // new is redundant 46 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 47 | public new const string ModelTypeAlias = "navigationBase"; 48 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 49 | public new const PublishedItemType ModelItemType = PublishedItemType.Content; 50 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 51 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 52 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 53 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 54 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 55 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 56 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 57 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 58 | #pragma warning restore 0109 59 | 60 | private IPublishedValueFallback _publishedValueFallback; 61 | 62 | // ctor 63 | public NavigationBase(IPublishedContent content, IPublishedValueFallback publishedValueFallback) 64 | : base(content, publishedValueFallback) 65 | { 66 | _publishedValueFallback = publishedValueFallback; 67 | } 68 | 69 | // properties 70 | 71 | /// 72 | /// Keywords: Keywords that describe the content of the page. This is considered optional since most modern search engines don't use this anymore 73 | /// 74 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 75 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 76 | [ImplementPropertyType("keywords")] 77 | public virtual global::System.Collections.Generic.IEnumerable Keywords => GetKeywords(this, _publishedValueFallback); 78 | 79 | /// Static getter for Keywords 80 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 81 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 82 | public static global::System.Collections.Generic.IEnumerable GetKeywords(INavigationBase that, IPublishedValueFallback publishedValueFallback) => that.Value>(publishedValueFallback, "keywords"); 83 | 84 | /// 85 | /// Description: A brief description of the content on your page. This text is shown below the title in a google search result and also used for Social Sharing Cards. The ideal length is between 130 and 155 characters 86 | /// 87 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 88 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 89 | [ImplementPropertyType("seoMetaDescription")] 90 | public virtual string SeoMetaDescription => GetSeoMetaDescription(this, _publishedValueFallback); 91 | 92 | /// Static getter for Description 93 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 94 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 95 | public static string GetSeoMetaDescription(INavigationBase that, IPublishedValueFallback publishedValueFallback) => that.Value(publishedValueFallback, "seoMetaDescription"); 96 | 97 | /// 98 | /// Hide in Navigation: If you don't want this page to appear in the navigation, check this box 99 | /// 100 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 101 | [ImplementPropertyType("umbracoNavihide")] 102 | public virtual bool UmbracoNavihide => GetUmbracoNavihide(this, _publishedValueFallback); 103 | 104 | /// Static getter for Hide in Navigation 105 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 106 | public static bool GetUmbracoNavihide(INavigationBase that, IPublishedValueFallback publishedValueFallback) => that.Value(publishedValueFallback, "umbracoNavihide"); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/Umbraco.StorageProviders.AzureBlob/DependencyInjection/AzureBlobFileSystemExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using Microsoft.Extensions.DependencyInjection.Extensions; 3 | using Microsoft.Extensions.Options; 4 | using Umbraco.StorageProviders.AzureBlob.IO; 5 | 6 | namespace Umbraco.Cms.Core.DependencyInjection; 7 | 8 | /// 9 | /// Extension methods to help registering Azure Blob Storage file systems. 10 | /// 11 | public static class AzureBlobFileSystemExtensions 12 | { 13 | /// 14 | /// Registers a in the , with it's configuration 15 | /// loaded from Umbraco:Storage:AzureBlob:{name} where {name} is the value of the parameter. 16 | /// 17 | /// The . 18 | /// The name of the file system. 19 | /// 20 | /// The . 21 | /// 22 | /// is null. 23 | public static IUmbracoBuilder AddAzureBlobFileSystem(this IUmbracoBuilder builder, string name) 24 | => builder.AddInternal(name); 25 | 26 | /// 27 | /// Registers a in the , with it's configuration 28 | /// loaded from Umbraco:Storage:AzureBlob:{name} where {name} is the value of the parameter. 29 | /// 30 | /// The . 31 | /// The name of the file system. 32 | /// An action used to configure the . 33 | /// 34 | /// The . 35 | /// 36 | /// is null. 37 | /// is null. 38 | public static IUmbracoBuilder AddAzureBlobFileSystem(this IUmbracoBuilder builder, string name, Action configure) 39 | => builder.AddInternal(name, optionsBuilder => optionsBuilder.Configure(configure)); 40 | 41 | /// 42 | /// Registers a in the , with it's configuration 43 | /// loaded from Umbraco:Storage:AzureBlob:{name} where {name} is the value of the parameter. 44 | /// 45 | /// The . 46 | /// The name of the file system. 47 | /// An action used to configure the . 48 | /// 49 | /// The . 50 | /// 51 | /// is null. 52 | /// is null. 53 | public static IUmbracoBuilder AddAzureBlobFileSystem(this IUmbracoBuilder builder, string name, Action configure) 54 | => builder.AddInternal(name, optionsBuilder => optionsBuilder.Configure(configure)); 55 | 56 | /// 57 | /// Registers a in the , with it's configuration 58 | /// loaded from Umbraco:Storage:AzureBlob:{name} where {name} is the value of the parameter. 59 | /// 60 | /// A dependency used by the configure action. 61 | /// The . 62 | /// The name of the file system. 63 | /// An action used to configure the . 64 | /// 65 | /// The . 66 | /// 67 | /// is null. 68 | /// is null. 69 | public static IUmbracoBuilder AddAzureBlobFileSystem(this IUmbracoBuilder builder, string name, Action configure) 70 | where TDep : class 71 | => builder.AddInternal(name, optionsBuilder => optionsBuilder.Configure(configure)); 72 | 73 | /// 74 | /// Registers a in the , with it's configuration 75 | /// loaded from Umbraco:Storage:AzureBlob:{name} where {name} is the value of the parameter. 76 | /// 77 | /// The . 78 | /// The name of the file system. 79 | /// An action used to configure the . 80 | /// 81 | /// The . 82 | /// 83 | /// is null. 84 | /// is null. 85 | internal static IUmbracoBuilder AddInternal(this IUmbracoBuilder builder, string name, Action>? configure = null) 86 | { 87 | ArgumentNullException.ThrowIfNull(builder); 88 | ArgumentNullException.ThrowIfNull(name); 89 | 90 | builder.Services.TryAddSingleton(); 91 | 92 | OptionsBuilder optionsBuilder = builder.Services.AddOptions(name) 93 | .BindConfiguration($"Umbraco:Storage:AzureBlob:{name}") 94 | .ValidateDataAnnotations(); 95 | 96 | configure?.Invoke(optionsBuilder); 97 | 98 | return builder; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /.globalconfig: -------------------------------------------------------------------------------- 1 | is_global = true 2 | 3 | ########################################## 4 | # StyleCopAnalyzers Settings 5 | ########################################## 6 | 7 | # All constant fields must be PascalCase 8 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1303.md 9 | dotnet_naming_symbols.stylecop_constant_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private 10 | dotnet_naming_symbols.stylecop_constant_fields_group.required_modifiers = const 11 | dotnet_naming_symbols.stylecop_constant_fields_group.applicable_kinds = field 12 | dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.symbols = stylecop_constant_fields_group 13 | dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.style = pascal_case_style 14 | 15 | # All static readonly fields must be PascalCase 16 | # Ajusted to ignore private fields. 17 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1311.md 18 | dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected 19 | dotnet_naming_symbols.stylecop_static_readonly_fields_group.required_modifiers = static, readonly 20 | dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_kinds = field 21 | dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.symbols = stylecop_static_readonly_fields_group 22 | dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.style = pascal_case_style 23 | 24 | # No non-private instance fields are allowed 25 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1401.md 26 | dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected 27 | dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_kinds = field 28 | dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.symbols = stylecop_fields_must_be_private_group 29 | dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.style = disallowed_style 30 | 31 | # Local variables must be camelCase 32 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1312.md 33 | dotnet_naming_symbols.stylecop_local_fields_group.applicable_accessibilities = local 34 | dotnet_naming_symbols.stylecop_local_fields_group.applicable_kinds = local 35 | dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.symbols = stylecop_local_fields_group 36 | dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.style = camel_case_style 37 | 38 | ########################################## 39 | # StyleCopAnalyzers rule severity 40 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers 41 | ########################################## 42 | 43 | dotnet_analyzer_diagnostic.category-StyleCop.CSharp.DocumentationRules.severity = suggestion 44 | dotnet_analyzer_diagnostic.category-StyleCop.CSharp.ReadabilityRules.severity = suggestion 45 | dotnet_analyzer_diagnostic.category-StyleCop.CSharp.NamingRules.severity = suggestion 46 | dotnet_analyzer_diagnostic.category-StyleCop.CSharp.SpacingRules.severity = suggestion 47 | dotnet_analyzer_diagnostic.category-StyleCop.CSharp.OrderingRules.severity = suggestion 48 | dotnet_analyzer_diagnostic.category-StyleCop.CSharp.MaintainabilityRules.severity = suggestion 49 | dotnet_analyzer_diagnostic.category-StyleCop.CSharp.LayoutRules.severity = suggestion 50 | 51 | dotnet_diagnostic.SA1101.severity = none # PrefixLocalCallsWithThis - stylecop appears to be ignoring dotnet_style_qualification_for_* 52 | dotnet_diagnostic.SA1309.severity = none # FieldNamesMustNotBeginWithUnderscore 53 | dotnet_diagnostic.SA1413.severity = none # UseTrailingCommasInMultiLineInitializers 54 | dotnet_diagnostic.SA1633.severity = none # FileMustHaveHeader 55 | dotnet_diagnostic.SA1636.severity = none # FileHeaderCopyrightTextMustMatch 56 | 57 | dotnet_diagnostic.SA1503.severity = warning # BracesMustNotBeOmitted 58 | dotnet_diagnostic.SA1117.severity = warning # ParametersMustBeOnSameLineOrSeparateLines 59 | dotnet_diagnostic.SA1116.severity = warning # SplitParametersMustStartOnLineAfterDeclaration 60 | dotnet_diagnostic.SA1122.severity = warning # UseStringEmptyForEmptyStrings 61 | dotnet_diagnostic.SA1028.severity = warning # CodeMustNotContainTrailingWhitespace 62 | dotnet_diagnostic.SA1500.severity = warning # BracesForMultiLineStatementsMustNotShareLine 63 | dotnet_diagnostic.SA1401.severity = warning # FieldsMustBePrivate 64 | dotnet_diagnostic.SA1519.severity = warning # BracesMustNotBeOmittedFromMultiLineChildStatement 65 | dotnet_diagnostic.SA1111.severity = warning # ClosingParenthesisMustBeOnLineOfLastParameter 66 | dotnet_diagnostic.SA1520.severity = warning # UseBracesConsistently 67 | dotnet_diagnostic.SA1407.severity = warning # ArithmeticExpressionsMustDeclarePrecedence 68 | dotnet_diagnostic.SA1400.severity = warning # AccessModifierMustBeDeclared 69 | dotnet_diagnostic.SA1119.severity = warning # StatementMustNotUseUnnecessaryParenthesis 70 | dotnet_diagnostic.SA1649.severity = warning # FileNameMustMatchTypeName 71 | dotnet_diagnostic.SA1121.severity = warning # UseBuiltInTypeAlias 72 | dotnet_diagnostic.SA1132.severity = warning # DoNotCombineFields 73 | dotnet_diagnostic.SA1134.severity = warning # AttributesMustNotShareLine 74 | dotnet_diagnostic.SA1106.severity = warning # CodeMustNotContainEmptyStatements 75 | dotnet_diagnostic.SA1312.severity = warning # VariableNamesMustBeginWithLowerCaseLetter 76 | dotnet_diagnostic.SA1310.severity = warning # FieldNamesMustNotContainUnderscore 77 | dotnet_diagnostic.SA1303.severity = warning # ConstFieldNamesMustBeginWithUpperCaseLetter 78 | dotnet_diagnostic.SA1130.severity = warning # UseLambdaSyntax 79 | dotnet_diagnostic.SA1405.severity = warning # DebugAssertMustProvideMessageText 80 | dotnet_diagnostic.SA1205.severity = warning # PartialElementsMustDeclareAccess 81 | dotnet_diagnostic.SA1306.severity = warning # FieldNamesMustBeginWithLowerCaseLetter 82 | dotnet_diagnostic.SA1209.severity = warning # UsingAliasDirectivesMustBePlacedAfterOtherUsingDirectives 83 | dotnet_diagnostic.SA1216.severity = warning # UsingStaticDirectivesMustBePlacedAtTheCorrectLocation 84 | dotnet_diagnostic.SA1133.severity = warning # DoNotCombineAttributes 85 | dotnet_diagnostic.SA1135.severity = warning # UsingDirectivesMustBeQualified 86 | 87 | # IDE0058: Expression value is never used 88 | dotnet_diagnostic.IDE0058.severity = none 89 | -------------------------------------------------------------------------------- /examples/Umbraco.StorageProviders.AzureBlob.TestSite/umbraco/models/Contact.generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Umbraco.ModelsBuilder.Embedded v17.0.0-beta+d9de69c 6 | // 7 | // Changes to this file will be lost if the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | using System; 12 | using System.Linq.Expressions; 13 | using Umbraco.Cms.Core.Models.PublishedContent; 14 | using Umbraco.Cms.Core.PublishedCache; 15 | using Umbraco.Cms.Infrastructure.ModelsBuilder; 16 | using Umbraco.Cms.Core; 17 | using Umbraco.Extensions; 18 | 19 | namespace Umbraco.Cms.Web.Common.PublishedModels 20 | { 21 | /// Contact 22 | [PublishedModel("contact")] 23 | public partial class Contact : PublishedContentModel, INavigationBase 24 | { 25 | // helpers 26 | #pragma warning disable 0109 // new is redundant 27 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 28 | public new const string ModelTypeAlias = "contact"; 29 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 30 | public new const PublishedItemType ModelItemType = PublishedItemType.Content; 31 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 32 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 33 | public new static IPublishedContentType GetModelContentType(IPublishedContentTypeCache contentTypeCache) 34 | => PublishedModelUtility.GetModelContentType(contentTypeCache, ModelItemType, ModelTypeAlias); 35 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 36 | [return: global::System.Diagnostics.CodeAnalysis.MaybeNull] 37 | public static IPublishedPropertyType GetModelPropertyType(IPublishedContentTypeCache contentTypeCache, Expression> selector) 38 | => PublishedModelUtility.GetModelPropertyType(GetModelContentType(contentTypeCache), selector); 39 | #pragma warning restore 0109 40 | 41 | private IPublishedValueFallback _publishedValueFallback; 42 | 43 | // ctor 44 | public Contact(IPublishedContent content, IPublishedValueFallback publishedValueFallback) 45 | : base(content, publishedValueFallback) 46 | { 47 | _publishedValueFallback = publishedValueFallback; 48 | } 49 | 50 | // properties 51 | 52 | /// 53 | /// Contact Form Header 54 | /// 55 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 56 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 57 | [ImplementPropertyType("contactFormHeader")] 58 | public virtual string ContactFormHeader => this.Value(_publishedValueFallback, "contactFormHeader"); 59 | 60 | /// 61 | /// Contact Intro 62 | /// 63 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 64 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 65 | [ImplementPropertyType("contactIntro")] 66 | public virtual global::Umbraco.Cms.Core.Strings.IHtmlEncodedString ContactIntro => this.Value(_publishedValueFallback, "contactIntro"); 67 | 68 | /// 69 | /// Map Coordinates 70 | /// 71 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 72 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 73 | [ImplementPropertyType("mapCoordinates")] 74 | public virtual global::Bergmania.OpenStreetMap.Core.OpenStreetMapModel MapCoordinates => this.Value(_publishedValueFallback, "mapCoordinates"); 75 | 76 | /// 77 | /// Map Header 78 | /// 79 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 80 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 81 | [ImplementPropertyType("mapHeader")] 82 | public virtual string MapHeader => this.Value(_publishedValueFallback, "mapHeader"); 83 | 84 | /// 85 | /// Page Title: The title of the page, this is also the first text in a google search result. The ideal length is between 40 and 60 characters 86 | /// 87 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 88 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 89 | [ImplementPropertyType("pageTitle")] 90 | public virtual string PageTitle => this.Value(_publishedValueFallback, "pageTitle"); 91 | 92 | /// 93 | /// Keywords: Keywords that describe the content of the page. This is considered optional since most modern search engines don't use this anymore 94 | /// 95 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 96 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 97 | [ImplementPropertyType("keywords")] 98 | public virtual global::System.Collections.Generic.IEnumerable Keywords => global::Umbraco.Cms.Web.Common.PublishedModels.NavigationBase.GetKeywords(this, _publishedValueFallback); 99 | 100 | /// 101 | /// Description: A brief description of the content on your page. This text is shown below the title in a google search result and also used for Social Sharing Cards. The ideal length is between 130 and 155 characters 102 | /// 103 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 104 | [global::System.Diagnostics.CodeAnalysis.MaybeNull] 105 | [ImplementPropertyType("seoMetaDescription")] 106 | public virtual string SeoMetaDescription => global::Umbraco.Cms.Web.Common.PublishedModels.NavigationBase.GetSeoMetaDescription(this, _publishedValueFallback); 107 | 108 | /// 109 | /// Hide in Navigation: If you don't want this page to appear in the navigation, check this box 110 | /// 111 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder.Embedded", "17.0.0-beta+d9de69c")] 112 | [ImplementPropertyType("umbracoNavihide")] 113 | public virtual bool UmbracoNavihide => global::Umbraco.Cms.Web.Common.PublishedModels.NavigationBase.GetUmbracoNavihide(this, _publishedValueFallback); 114 | } 115 | } 116 | --------------------------------------------------------------------------------