V14: Extend IContentEntitySlim (#15890)
* Extend EntitySlim with key * Add ListView to GenericContentEntityDto and ContentEntitySlim * Move ContentTypeKey and ListViewKey back to BaseDto * Remove extra DB call when mapping to DocumentTypeReferenceResponseModel * Remove extra DB call when mapping to MediaTypeReferenceResponseModel * Remove duplicate db call for members * Remove now redundant base class * Fix comment
This commit is contained in:
@@ -1,33 +0,0 @@
|
||||
using Umbraco.Cms.Api.Management.ViewModels.ContentType;
|
||||
using Umbraco.Cms.Core.Mapping;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Entities;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
|
||||
namespace Umbraco.Cms.Api.Management.Factories;
|
||||
|
||||
internal abstract class ContentPresentationFactoryBase<TContentType, TContentTypeService>
|
||||
where TContentTypeService : IContentTypeBaseService<TContentType>
|
||||
where TContentType : IContentTypeComposition
|
||||
{
|
||||
private readonly TContentTypeService _contentTypeService;
|
||||
private readonly IUmbracoMapper _umbracoMapper;
|
||||
|
||||
protected ContentPresentationFactoryBase(TContentTypeService contentTypeService, IUmbracoMapper umbracoMapper)
|
||||
{
|
||||
_contentTypeService = contentTypeService;
|
||||
_umbracoMapper = umbracoMapper;
|
||||
}
|
||||
|
||||
protected TContentTypeReferenceResponseModel CreateContentTypeReferenceResponseModel<TContentTypeReferenceResponseModel>(IContentEntitySlim entity)
|
||||
where TContentTypeReferenceResponseModel : ContentTypeReferenceResponseModelBase, new()
|
||||
{
|
||||
// This sucks, since it'll cost an extra DB call.
|
||||
// but currently there's no really good way to get the content type key from an IDocumentEntitySlim or IMediaEntitySlim.
|
||||
// FIXME: to fix this, add content type key and "IsContainer" to IDocumentEntitySlim and IMediaEntitySlim, and use those here instead of fetching the entire content type.
|
||||
TContentType? contentType = _contentTypeService.Get(entity.ContentTypeAlias);
|
||||
return contentType is not null
|
||||
? _umbracoMapper.Map<TContentTypeReferenceResponseModel>(contentType)!
|
||||
: new TContentTypeReferenceResponseModel();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using Umbraco.Cms.Api.Management.Mapping.Content;
|
||||
using Umbraco.Cms.Api.Management.ViewModels;
|
||||
using Umbraco.Cms.Api.Management.ViewModels.Content;
|
||||
using Umbraco.Cms.Api.Management.ViewModels.Document;
|
||||
using Umbraco.Cms.Api.Management.ViewModels.Document.Item;
|
||||
using Umbraco.Cms.Api.Management.ViewModels.DocumentBlueprint.Item;
|
||||
@@ -16,8 +15,7 @@ using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Api.Management.Factories;
|
||||
|
||||
internal sealed class DocumentPresentationFactory
|
||||
: ContentPresentationFactoryBase<IContentType, IContentTypeService>, IDocumentPresentationFactory
|
||||
internal sealed class DocumentPresentationFactory : IDocumentPresentationFactory
|
||||
{
|
||||
private readonly IUmbracoMapper _umbracoMapper;
|
||||
private readonly IDocumentUrlFactory _documentUrlFactory;
|
||||
@@ -33,7 +31,6 @@ internal sealed class DocumentPresentationFactory
|
||||
IContentTypeService contentTypeService,
|
||||
IPublicAccessService publicAccessService,
|
||||
TimeProvider timeProvider)
|
||||
: base(contentTypeService, umbracoMapper)
|
||||
{
|
||||
_umbracoMapper = umbracoMapper;
|
||||
_documentUrlFactory = documentUrlFactory;
|
||||
@@ -70,11 +67,7 @@ internal sealed class DocumentPresentationFactory
|
||||
|
||||
responseModel.IsProtected = _publicAccessService.IsProtected(entity.Path);
|
||||
|
||||
IContentType? contentType = _contentTypeService.Get(entity.ContentTypeAlias);
|
||||
if (contentType is not null)
|
||||
{
|
||||
responseModel.DocumentType = _umbracoMapper.Map<DocumentTypeReferenceResponseModel>(contentType)!;
|
||||
}
|
||||
responseModel.DocumentType = _umbracoMapper.Map<DocumentTypeReferenceResponseModel>(entity)!;
|
||||
|
||||
responseModel.Variants = CreateVariantsItemResponseModels(entity);
|
||||
|
||||
@@ -118,7 +111,7 @@ internal sealed class DocumentPresentationFactory
|
||||
}
|
||||
|
||||
public DocumentTypeReferenceResponseModel CreateDocumentTypeReferenceResponseModel(IDocumentEntitySlim entity)
|
||||
=> CreateContentTypeReferenceResponseModel<DocumentTypeReferenceResponseModel>(entity);
|
||||
=> _umbracoMapper.Map<DocumentTypeReferenceResponseModel>(entity)!;
|
||||
|
||||
public Attempt<CultureAndScheduleModel, ContentPublishingOperationStatus> CreateCultureAndScheduleModel(PublishDocumentRequestModel requestModel)
|
||||
{
|
||||
|
||||
@@ -22,5 +22,6 @@ public interface IDocumentPresentationFactory
|
||||
IEnumerable<DocumentVariantItemResponseModel> CreateVariantsItemResponseModels(IDocumentEntitySlim entity);
|
||||
|
||||
DocumentTypeReferenceResponseModel CreateDocumentTypeReferenceResponseModel(IDocumentEntitySlim entity);
|
||||
|
||||
Attempt<CultureAndScheduleModel,ContentPublishingOperationStatus> CreateCultureAndScheduleModel(PublishDocumentRequestModel requestModel);
|
||||
}
|
||||
|
||||
@@ -14,28 +14,23 @@ using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Api.Management.Factories;
|
||||
|
||||
internal sealed class MediaPresentationFactory
|
||||
: ContentPresentationFactoryBase<IMediaType, IMediaTypeService>, IMediaPresentationFactory
|
||||
internal sealed class MediaPresentationFactory : IMediaPresentationFactory
|
||||
{
|
||||
private readonly IUmbracoMapper _umbracoMapper;
|
||||
private readonly ContentSettings _contentSettings;
|
||||
private readonly MediaUrlGeneratorCollection _mediaUrlGenerators;
|
||||
private readonly IAbsoluteUrlBuilder _absoluteUrlBuilder;
|
||||
private readonly IMediaTypeService _mediaTypeService;
|
||||
|
||||
public MediaPresentationFactory(
|
||||
IUmbracoMapper umbracoMapper,
|
||||
IOptions<ContentSettings> contentSettings,
|
||||
MediaUrlGeneratorCollection mediaUrlGenerators,
|
||||
IAbsoluteUrlBuilder absoluteUrlBuilder,
|
||||
IMediaTypeService mediaTypeService)
|
||||
: base(mediaTypeService, umbracoMapper)
|
||||
IAbsoluteUrlBuilder absoluteUrlBuilder)
|
||||
{
|
||||
_umbracoMapper = umbracoMapper;
|
||||
_contentSettings = contentSettings.Value;
|
||||
_mediaUrlGenerators = mediaUrlGenerators;
|
||||
_absoluteUrlBuilder = absoluteUrlBuilder;
|
||||
_mediaTypeService = mediaTypeService;
|
||||
}
|
||||
|
||||
public Task<MediaResponseModel> CreateResponseModelAsync(IMedia media)
|
||||
@@ -63,11 +58,7 @@ internal sealed class MediaPresentationFactory
|
||||
IsTrashed = entity.Trashed
|
||||
};
|
||||
|
||||
IMediaType? mediaType = _mediaTypeService.Get(entity.ContentTypeAlias);
|
||||
if (mediaType is not null)
|
||||
{
|
||||
responseModel.MediaType = _umbracoMapper.Map<MediaTypeReferenceResponseModel>(mediaType)!;
|
||||
}
|
||||
responseModel.MediaType = _umbracoMapper.Map<MediaTypeReferenceResponseModel>(entity)!;
|
||||
|
||||
responseModel.Variants = CreateVariantsItemResponseModels(entity);
|
||||
|
||||
@@ -85,5 +76,5 @@ internal sealed class MediaPresentationFactory
|
||||
};
|
||||
|
||||
public MediaTypeReferenceResponseModel CreateMediaTypeReferenceResponseModel(IMediaEntitySlim entity)
|
||||
=> CreateContentTypeReferenceResponseModel<MediaTypeReferenceResponseModel>(entity);
|
||||
=> _umbracoMapper.Map<MediaTypeReferenceResponseModel>(entity)!;
|
||||
}
|
||||
|
||||
@@ -9,24 +9,19 @@ using Umbraco.Cms.Core.Services;
|
||||
|
||||
namespace Umbraco.Cms.Api.Management.Factories;
|
||||
|
||||
internal sealed class MemberPresentationFactory
|
||||
: ContentPresentationFactoryBase<IMemberType, IMemberTypeService>, IMemberPresentationFactory
|
||||
internal sealed class MemberPresentationFactory : IMemberPresentationFactory
|
||||
{
|
||||
private readonly IUmbracoMapper _umbracoMapper;
|
||||
private readonly IMemberService _memberService;
|
||||
private readonly IMemberTypeService _memberTypeService;
|
||||
private readonly ITwoFactorLoginService _twoFactorLoginService;
|
||||
|
||||
public MemberPresentationFactory(
|
||||
IUmbracoMapper umbracoMapper,
|
||||
IMemberService memberService,
|
||||
IMemberTypeService memberTypeService,
|
||||
ITwoFactorLoginService twoFactorLoginService)
|
||||
: base(memberTypeService, umbracoMapper)
|
||||
{
|
||||
_umbracoMapper = umbracoMapper;
|
||||
_memberService = memberService;
|
||||
_memberTypeService = memberTypeService;
|
||||
_twoFactorLoginService = twoFactorLoginService;
|
||||
}
|
||||
|
||||
@@ -58,11 +53,7 @@ internal sealed class MemberPresentationFactory
|
||||
Id = entity.Key,
|
||||
};
|
||||
|
||||
IMemberType? memberType = _memberTypeService.Get(entity.ContentTypeAlias);
|
||||
if (memberType is not null)
|
||||
{
|
||||
responseModel.MemberType = _umbracoMapper.Map<MemberTypeReferenceResponseModel>(memberType)!;
|
||||
}
|
||||
responseModel.MemberType = _umbracoMapper.Map<MemberTypeReferenceResponseModel>(entity)!;
|
||||
|
||||
responseModel.Variants = CreateVariantsItemResponseModels(entity);
|
||||
|
||||
@@ -80,5 +71,5 @@ internal sealed class MemberPresentationFactory
|
||||
};
|
||||
|
||||
public MemberTypeReferenceResponseModel CreateMemberTypeReferenceResponseModel(IMemberEntitySlim entity)
|
||||
=> CreateContentTypeReferenceResponseModel<MemberTypeReferenceResponseModel>(entity);
|
||||
=> _umbracoMapper.Map<MemberTypeReferenceResponseModel>(entity)!;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using Umbraco.Cms.Api.Management.ViewModels;
|
||||
using Umbraco.Cms.Api.Management.ViewModels.DocumentType;
|
||||
using Umbraco.Cms.Core.Mapping;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Entities;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Api.Management.Mapping.DocumentType;
|
||||
@@ -16,6 +17,8 @@ public class DocumentTypeMapDefinition : ContentTypeMapDefinition<IContentType,
|
||||
mapper.Define<ISimpleContentType, DocumentTypeReferenceResponseModel>((_, _) => new DocumentTypeReferenceResponseModel(), Map);
|
||||
mapper.Define<IContentType, AllowedDocumentType>((_, _) => new AllowedDocumentType(), Map);
|
||||
mapper.Define<ISimpleContentType, DocumentTypeCollectionReferenceResponseModel>((_, _) => new DocumentTypeCollectionReferenceResponseModel(), Map);
|
||||
mapper.Define<IContentEntitySlim, DocumentTypeReferenceResponseModel>((_, _) => new DocumentTypeReferenceResponseModel(), Map);
|
||||
mapper.Define<IDocumentEntitySlim, DocumentTypeReferenceResponseModel>((_, _) => new DocumentTypeReferenceResponseModel(), Map);
|
||||
}
|
||||
|
||||
// Umbraco.Code.MapAll
|
||||
@@ -71,6 +74,22 @@ public class DocumentTypeMapDefinition : ContentTypeMapDefinition<IContentType,
|
||||
target.Collection = ReferenceByIdModel.ReferenceOrNull(source.ListView);
|
||||
}
|
||||
|
||||
// Umbraco.Code.MapAll
|
||||
private void Map(IContentEntitySlim source, DocumentTypeReferenceResponseModel target, MapperContext context)
|
||||
{
|
||||
target.Id = source.Key;
|
||||
target.Icon = source.ContentTypeIcon ?? string.Empty;
|
||||
target.Collection = ReferenceByIdModel.ReferenceOrNull(source.ListViewKey);
|
||||
}
|
||||
|
||||
// Umbraco.Code.MapAll
|
||||
private void Map(IDocumentEntitySlim source, DocumentTypeReferenceResponseModel target, MapperContext context)
|
||||
{
|
||||
target.Id = source.Key;
|
||||
target.Icon = source.ContentTypeIcon ?? string.Empty;
|
||||
target.Collection = ReferenceByIdModel.ReferenceOrNull(source.ListViewKey);
|
||||
}
|
||||
|
||||
// Umbraco.Code.MapAll
|
||||
private void Map(ISimpleContentType source, DocumentTypeReferenceResponseModel target, MapperContext context)
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using Umbraco.Cms.Api.Management.ViewModels;
|
||||
using Umbraco.Cms.Api.Management.ViewModels.MediaType;
|
||||
using Umbraco.Cms.Core.Mapping;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Entities;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Api.Management.Mapping.MediaType;
|
||||
@@ -13,6 +14,8 @@ public class MediaTypeMapDefinition : ContentTypeMapDefinition<IMediaType, Media
|
||||
{
|
||||
mapper.Define<IMediaType, MediaTypeResponseModel>((_, _) => new MediaTypeResponseModel(), Map);
|
||||
mapper.Define<IMediaType, MediaTypeReferenceResponseModel>((_, _) => new MediaTypeReferenceResponseModel(), Map);
|
||||
mapper.Define<IMediaEntitySlim, MediaTypeReferenceResponseModel>((_, _) => new MediaTypeReferenceResponseModel(), Map);
|
||||
mapper.Define<IContentEntitySlim, MediaTypeReferenceResponseModel>((_, _) => new MediaTypeReferenceResponseModel(), Map);
|
||||
mapper.Define<ISimpleContentType, MediaTypeReferenceResponseModel>((_, _) => new MediaTypeReferenceResponseModel(), Map);
|
||||
mapper.Define<IMediaType, AllowedMediaType>((_, _) => new AllowedMediaType(), Map);
|
||||
mapper.Define<ISimpleContentType, MediaTypeCollectionReferenceResponseModel>((_, _) => new MediaTypeCollectionReferenceResponseModel(), Map);
|
||||
@@ -55,6 +58,22 @@ public class MediaTypeMapDefinition : ContentTypeMapDefinition<IMediaType, Media
|
||||
target.Collection = ReferenceByIdModel.ReferenceOrNull(source.ListView);
|
||||
}
|
||||
|
||||
// Umbraco.Code.MapAll
|
||||
private void Map(IMediaEntitySlim source, MediaTypeReferenceResponseModel target, MapperContext context)
|
||||
{
|
||||
target.Id = source.Key;
|
||||
target.Icon = source.ContentTypeIcon ?? string.Empty;
|
||||
target.Collection = ReferenceByIdModel.ReferenceOrNull(source.ListViewKey);
|
||||
}
|
||||
|
||||
// Umbraco.Code.MapAll
|
||||
private void Map(IContentEntitySlim source, MediaTypeReferenceResponseModel target, MapperContext context)
|
||||
{
|
||||
target.Id = source.Key;
|
||||
target.Icon = source.ContentTypeIcon ?? string.Empty;
|
||||
target.Collection = ReferenceByIdModel.ReferenceOrNull(source.ListViewKey);
|
||||
}
|
||||
|
||||
// Umbraco.Code.MapAll
|
||||
private void Map(ISimpleContentType source, MediaTypeReferenceResponseModel target, MapperContext context)
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Umbraco.Cms.Api.Management.ViewModels.MemberType;
|
||||
using Umbraco.Cms.Core.Mapping;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Entities;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Api.Management.Mapping.MemberType;
|
||||
@@ -12,6 +13,8 @@ public class MemberTypeMapDefinition : ContentTypeMapDefinition<IMemberType, Mem
|
||||
{
|
||||
mapper.Define<IMemberType, MemberTypeResponseModel>((_, _) => new MemberTypeResponseModel(), Map);
|
||||
mapper.Define<IMemberType, MemberTypeReferenceResponseModel>((_, _) => new MemberTypeReferenceResponseModel(), Map);
|
||||
mapper.Define<IMemberEntitySlim, MemberTypeReferenceResponseModel>((_, _) => new MemberTypeReferenceResponseModel(), Map);
|
||||
mapper.Define<IContentEntitySlim, MemberTypeReferenceResponseModel>((_, _) => new MemberTypeReferenceResponseModel(), Map);
|
||||
mapper.Define<ISimpleContentType, MemberTypeReferenceResponseModel>((_, _) => new MemberTypeReferenceResponseModel(), Map);
|
||||
}
|
||||
|
||||
@@ -46,6 +49,18 @@ public class MemberTypeMapDefinition : ContentTypeMapDefinition<IMemberType, Mem
|
||||
target.Icon = source.Icon ?? string.Empty;
|
||||
}
|
||||
|
||||
private void Map(IMemberEntitySlim source, MemberTypeReferenceResponseModel target, MapperContext context)
|
||||
{
|
||||
target.Id = source.ContentTypeKey;
|
||||
target.Icon = source.ContentTypeIcon ?? string.Empty;
|
||||
}
|
||||
|
||||
private void Map(IContentEntitySlim source, MemberTypeReferenceResponseModel target, MapperContext context)
|
||||
{
|
||||
target.Id = source.ContentTypeKey;
|
||||
target.Icon = source.ContentTypeIcon ?? string.Empty;
|
||||
}
|
||||
|
||||
// Umbraco.Code.MapAll -Collection
|
||||
private void Map(ISimpleContentType source, MemberTypeReferenceResponseModel target, MapperContext context)
|
||||
{
|
||||
|
||||
@@ -8,6 +8,11 @@ public class ContentEntitySlim : EntitySlim, IContentEntitySlim
|
||||
/// <inheritdoc />
|
||||
public string ContentTypeAlias { get; set; } = string.Empty;
|
||||
|
||||
/// <inheritdoc />
|
||||
public Guid ContentTypeKey { get; set; }
|
||||
|
||||
public Guid? ListViewKey { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string? ContentTypeIcon { get; set; }
|
||||
|
||||
|
||||
@@ -10,6 +10,16 @@ public interface IContentEntitySlim : IEntitySlim
|
||||
/// </summary>
|
||||
string ContentTypeAlias { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content type key.
|
||||
/// </summary>
|
||||
Guid ContentTypeKey { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the listview key.
|
||||
/// </summary>
|
||||
Guid? ListViewKey { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content type icon.
|
||||
/// </summary>
|
||||
|
||||
@@ -373,6 +373,17 @@ namespace Umbraco.Extensions
|
||||
? sql.GetColumns<TDto>(withAlias: false)
|
||||
: fields.Select(x => sqlSyntax.GetFieldName(x)).ToArray();
|
||||
return sql.Append(", " + string.Join(", ", columns));
|
||||
|
||||
}
|
||||
|
||||
public static Sql<ISqlContext> AndBy<TDto>(this Sql<ISqlContext> sql, string tableAlias,
|
||||
params Expression<Func<TDto, object?>>[] fields)
|
||||
{
|
||||
ISqlSyntaxProvider sqlSyntax = sql.SqlContext.SqlSyntax;
|
||||
var columns = fields.Length == 0
|
||||
? sql.GetColumns<TDto>(withAlias: false)
|
||||
: fields.Select(x => sqlSyntax.GetFieldName(x, tableAlias)).ToArray();
|
||||
return sql.Append(", " + string.Join(", ", columns));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -472,7 +472,8 @@ internal class EntityRepository : RepositoryBase, IEntityRepositoryExtended
|
||||
x => x.Icon,
|
||||
x => x.Thumbnail,
|
||||
x => x.ListView,
|
||||
x => x.Variations);
|
||||
x => x.Variations)
|
||||
.AndSelect<NodeDto>("ContentTypeNode", x => Alias(x.UniqueId, "ContentTypeKey"));
|
||||
}
|
||||
|
||||
if (isContent)
|
||||
@@ -498,7 +499,9 @@ internal class EntityRepository : RepositoryBase, IEntityRepositoryExtended
|
||||
.On<NodeDto, ContentVersionDto>((left, right) => left.NodeId == right.NodeId && right.Current)
|
||||
.LeftJoin<ContentDto>().On<NodeDto, ContentDto>((left, right) => left.NodeId == right.NodeId)
|
||||
.LeftJoin<ContentTypeDto>()
|
||||
.On<ContentDto, ContentTypeDto>((left, right) => left.ContentTypeId == right.NodeId);
|
||||
.On<ContentDto, ContentTypeDto>((left, right) => left.ContentTypeId == right.NodeId)
|
||||
.LeftJoin<NodeDto>("ContentTypeNode")
|
||||
.On<NodeDto, ContentTypeDto>((left, right) => left.NodeId == right.NodeId, aliasLeft: "ContentTypeNode");
|
||||
}
|
||||
|
||||
if (isContent)
|
||||
@@ -605,7 +608,8 @@ internal class EntityRepository : RepositoryBase, IEntityRepositoryExtended
|
||||
x => x.Icon,
|
||||
x => x.Thumbnail,
|
||||
x => x.ListView,
|
||||
x => x.Variations);
|
||||
x => x.Variations)
|
||||
.AndBy<NodeDto>("ContentTypeNode", x => x.UniqueId);
|
||||
}
|
||||
|
||||
if (defaultSort)
|
||||
@@ -730,6 +734,10 @@ internal class EntityRepository : RepositoryBase, IEntityRepositoryExtended
|
||||
public string? Thumbnail { get; set; }
|
||||
public bool IsContainer { get; set; }
|
||||
|
||||
public Guid ContentTypeKey { get; set; }
|
||||
|
||||
public Guid? ListView { get; set; }
|
||||
|
||||
// ReSharper restore UnusedAutoPropertyAccessor.Local
|
||||
// ReSharper restore UnusedMember.Local
|
||||
}
|
||||
@@ -786,6 +794,8 @@ internal class EntityRepository : RepositoryBase, IEntityRepositoryExtended
|
||||
entity.ContentTypeAlias = dto.Alias;
|
||||
entity.ContentTypeIcon = dto.Icon;
|
||||
entity.ContentTypeThumbnail = dto.Thumbnail;
|
||||
entity.ContentTypeKey = dto.ContentTypeKey;
|
||||
entity.ListViewKey = dto.ListView;
|
||||
}
|
||||
|
||||
private MediaEntitySlim BuildMediaEntity(BaseDto dto)
|
||||
|
||||
Reference in New Issue
Block a user