using AutoMapper; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc.Routing; using System; using System.Collections.Generic; using Timeline.Controllers; namespace Timeline.Models.Http { /// /// Info of post content. /// public class HttpTimelinePostContent { /// /// Type of the post content. /// public string Type { get; set; } = default!; /// /// If post is of text type. This is the text. /// public string? Text { get; set; } /// /// If post is of image type. This is the image url. /// public string? Url { get; set; } /// /// If post has data (currently it means it's a image post), this is the data etag. /// public string? ETag { get; set; } } /// /// Info of a post. /// public class HttpTimelinePost { /// /// Post id. /// public long Id { get; set; } /// /// Content of the post. May be null if post is deleted. /// public HttpTimelinePostContent? Content { get; set; } /// /// True if post is deleted. /// public bool Deleted { get; set; } /// /// Post time. /// public DateTime Time { get; set; } /// /// The author. May be null if the user has been deleted. /// public HttpUser? Author { get; set; } = default!; /// /// Last updated time. /// public DateTime LastUpdated { get; set; } = default!; } /// /// Info of a timeline. /// public class HttpTimeline { /// /// Unique id. /// public string UniqueId { get; set; } = default!; /// /// Title. /// public string Title { get; set; } = default!; /// /// Name of timeline. /// public string Name { get; set; } = default!; /// /// Last modified time of timeline name. /// public DateTime NameLastModifed { get; set; } = default!; /// /// Timeline description. /// public string Description { get; set; } = default!; /// /// Owner of the timeline. /// public HttpUser Owner { get; set; } = default!; /// /// Visibility of the timeline. /// public TimelineVisibility Visibility { get; set; } #pragma warning disable CA2227 // Collection properties should be read only /// /// Members of timeline. /// public List Members { get; set; } = default!; #pragma warning restore CA2227 // Collection properties should be read only /// /// Create time of timeline. /// public DateTime CreateTime { get; set; } = default!; /// /// Last modified time of timeline. /// public DateTime LastModified { get; set; } = default!; #pragma warning disable CA1707 // Identifiers should not contain underscores /// /// Related links. /// public HttpTimelineLinks _links { get; set; } = default!; #pragma warning restore CA1707 // Identifiers should not contain underscores } /// /// Related links for timeline. /// public class HttpTimelineLinks { /// /// Self. /// public string Self { get; set; } = default!; /// /// Posts url. /// public string Posts { get; set; } = default!; } public class HttpTimelineLinksValueResolver : IValueResolver { private readonly IActionContextAccessor _actionContextAccessor; private readonly IUrlHelperFactory _urlHelperFactory; public HttpTimelineLinksValueResolver(IActionContextAccessor actionContextAccessor, IUrlHelperFactory urlHelperFactory) { _actionContextAccessor = actionContextAccessor; _urlHelperFactory = urlHelperFactory; } public HttpTimelineLinks Resolve(TimelineInfo source, HttpTimeline destination, HttpTimelineLinks destMember, ResolutionContext context) { var actionContext = _actionContextAccessor.AssertActionContextForUrlFill(); var urlHelper = _urlHelperFactory.GetUrlHelper(actionContext); return new HttpTimelineLinks { Self = urlHelper.ActionLink(nameof(TimelineController.TimelineGet), nameof(TimelineController)[0..^nameof(Controller).Length], new { source.Name }), Posts = urlHelper.ActionLink(nameof(TimelineController.PostListGet), nameof(TimelineController)[0..^nameof(Controller).Length], new { source.Name }) }; } } public class HttpTimelinePostContentResolver : IValueResolver { private readonly IActionContextAccessor _actionContextAccessor; private readonly IUrlHelperFactory _urlHelperFactory; public HttpTimelinePostContentResolver(IActionContextAccessor actionContextAccessor, IUrlHelperFactory urlHelperFactory) { _actionContextAccessor = actionContextAccessor; _urlHelperFactory = urlHelperFactory; } public HttpTimelinePostContent? Resolve(TimelinePostInfo source, HttpTimelinePost destination, HttpTimelinePostContent? destMember, ResolutionContext context) { var actionContext = _actionContextAccessor.AssertActionContextForUrlFill(); var urlHelper = _urlHelperFactory.GetUrlHelper(actionContext); var sourceContent = source.Content; if (sourceContent == null) { return null; } if (sourceContent is TextTimelinePostContent textContent) { return new HttpTimelinePostContent { Type = TimelinePostContentTypes.Text, Text = textContent.Text }; } else if (sourceContent is ImageTimelinePostContent imageContent) { return new HttpTimelinePostContent { Type = TimelinePostContentTypes.Image, Url = urlHelper.ActionLink( action: nameof(TimelineController.PostDataGet), controller: nameof(TimelineController)[0..^nameof(Controller).Length], values: new { Name = source.TimelineName, Id = source.Id }), ETag = $"\"{imageContent.DataTag}\"" }; } else { throw new InvalidOperationException(Resources.Models.Http.Exception.UnknownPostContentType); } } } public class HttpTimelineAutoMapperProfile : Profile { public HttpTimelineAutoMapperProfile() { CreateMap().ForMember(u => u._links, opt => opt.MapFrom()); CreateMap().ForMember(p => p.Content, opt => opt.MapFrom()); } } }