/* ---------------------------------------------------------------------------------------------------------- */ #region Class Members #endregion /* ---------------------------------------------------------------------------------------------------------- */ #region Constructors/Initialisation public BlogPostListItemModel(BlogPost blogPost) { BlogPostContent blogPostContent = blogPost.BlogPostContent.OrderByDescending(s => s.UTCDateUpdated).First(); BlogPostId = blogPost.BlogId; Title = blogPostContent.Title; LastEditedByName = blogPostContent.LastEditedByUser.UserName; DateUpdated = blogPostContent.UTCDateUpdated.ToLocalTime(); bool isPublished = blogPost.BlogPostContent.Count(s => s.PublishStatus == PublishStatus.Published) > 0; bool hasDraft = blogPost.BlogPostContent.Count(s => s.PublishStatus == PublishStatus.Draft) > 0; if (isPublished && hasDraft) { PageStatus = "Published / Draft Pending"; } else if (isPublished) { PageStatus = "Published"; } else if (hasDraft) { PageStatus = "Draft Pending"; } else { PageStatus = "Not Published, No Draft"; } }
public static void SeedDb(IConfiguration configuration) { var services = new ServiceCollection(); services.AddDbContext <AppDbContext>(o => o.UseSqlServer(configuration.GetConnectionString("Default"))); var serviceProvider = services.BuildServiceProvider(); using (serviceProvider.CreateScope()) { var context = serviceProvider.GetService <AppDbContext>(); var user = new User("Test"); var authorProfile = new AuthorProfile("Tom", "Bina", "About me"); var authorValidator = new AuthorValidator(context); var author = Author.Create(user, authorProfile, authorValidator).Result; for (var i = 0; i < 20; i++) { var blogPostContent = new BlogPostContent("This is a test subject.", "Let's begin with a test intro", "And here's the test content"); var category = new Category("Test", 1, "Test description"); var blogPost = new BlogPost(blogPostContent, author, category); context.BlogPosts.Add(blogPost); } context.SaveChanges(); } serviceProvider.Dispose(); }
public async Task <BlogPostContent> GetDefaultPostItemAsync() { var blobList = await GetBlobList(_appSettings.BlogPostContainer); var baseDate = DateTime.Now.AddYears(-2); var blob = blobList .Where(x => Convert.ToInt32(x.Parent.Prefix.Substring(0, 4)) >= baseDate.Year) .OrderByDescending(x => Convert.ToInt32(x.Parent.Prefix.Substring(0, 4))) .ThenByDescending(x => Convert.ToInt32(x.Parent.Prefix.Substring(5, 2))) .ThenByDescending(x => Convert.ToInt32(x.Parent.Prefix.Substring(8, 2))) .ThenByDescending(x => x.Properties.LastModified) .FirstOrDefault(); var operationContext = new OperationContext(); var stream = await blob.OpenReadAsync(null, null, operationContext); var datePosted = await FormatDatePostedStringAsync(blob.Parent.Prefix); using var reader = new StreamReader(stream); var contentBuilder = new StringBuilder(); var blobContent = await reader.ReadToEndAsync(); var blogPostContent = new BlogPostContent { DatePosted = datePosted, PageContent = blobContent }; return(blogPostContent); }
/* ---------------------------------------------------------------------------------------------------------- */ #region Private Methods /// <summary> /// Creates a new row in the database. /// </summary> private SaveResult CreateBlog(BlogPostModel model, ContentManagementDb db) { try { BlogPost blog = db.Blogs.CreateAdd(); blog.Initialise(); blog.BlogPostContent = new List <BlogPostContent>(); AutoMap.Map(model, blog); blog.CreatedByUserId = UserSession.Current.UserId; blog.DomainId = UserSession.Current.DomainId; BlogPostContent blogContent = new BlogPostContent(); AutoMap.Map(model, blogContent); blog.BlogPostContent.Add(blogContent); blogContent.Initialize(); blogContent.LastEditedByUserId = blog.CreatedByUserId; SetPublishStatus(blog, blogContent, model.Publish); db.SaveChanges(); return(SaveResult.Success); } catch { return(SaveResult.Fail); } }
public BlogPostContent CreateNewBlogPostContent() { var entity = new BlogPostContent(); PopulateHtmlContentProperties(entity); return(entity); }
protected virtual void GetBlogPostAndContentEntities(BlogPostViewModel request, IPrincipal principal, string[] roles, ref bool isNew, out BlogPostContent content, out PageContent pageContent, out BlogPost blogPost) { content = null; pageContent = null; // Loading blog post and it's content, or creating new, if such not exists if (!isNew) { var blogPostFuture = repository .AsQueryable <BlogPost>(b => b.Id == request.Id) .ToFuture(); content = repository .AsQueryable <BlogPostContent>(c => c.PageContents.Any(x => x.Page.Id == request.Id && !x.IsDeleted)) .ToFuture() .FirstOrDefault(); blogPost = blogPostFuture.FirstOne(); if (configuration.Security.AccessControlEnabled) { accessControlService.DemandAccess(blogPost, principal, AccessLevel.ReadWrite, roles); } if (content != null) { // Check if user has confirmed the deletion of content if (!request.IsUserConfirmed && blogPost.IsMasterPage) { var hasAnyChildren = contentService.CheckIfContentHasDeletingChildren(blogPost.Id, content.Id, request.Content); if (hasAnyChildren) { var message = PagesGlobalization.SaveContent_ContentHasChildrenContents_RegionDeleteConfirmationMessage; var logMessage = string.Format("User is trying to delete content regions which has children contents. Confirmation is required. ContentId: {0}, PageId: {1}", content.Id, blogPost.Id); throw new ConfirmationRequestException(() => message, logMessage); } } var bpRef = blogPost; var contentRef = content; pageContent = repository.FirstOrDefault <PageContent>(c => c.Page == bpRef && !c.IsDeleted && c.Content == contentRef); } } else { blogPost = new BlogPost(); } if (pageContent == null) { pageContent = new PageContent { Page = blogPost }; } }
protected virtual void GetBlogPostAndContentEntities(BlogPostViewModel request, IPrincipal principal, string[] roles, ref bool isNew, out BlogPostContent content, out PageContent pageContent, out BlogPost blogPost) { content = null; pageContent = null; // Loading blog post and it's content, or creating new, if such not exists if (!isNew) { var blogPostFuture = repository .AsQueryable <BlogPost>(b => b.Id == request.Id) .ToFuture(); content = repository .AsQueryable <BlogPostContent>(c => c.PageContents.Any(x => x.Page.Id == request.Id && !x.IsDeleted)) .ToFuture() .FirstOrDefault(); blogPost = blogPostFuture.FirstOne(); if (configuration.Security.AccessControlEnabled) { accessControlService.DemandAccess(blogPost, principal, AccessLevel.ReadWrite, roles); } if (content != null) { // Check if user has confirmed the deletion of content if (!request.IsUserConfirmed && blogPost.IsMasterPage) { contentService.CheckIfContentHasDeletingChildrenWithException(blogPost.Id, content.Id, request.Content); } var bpRef = blogPost; var contentRef = content; pageContent = repository.FirstOrDefault <PageContent>(c => c.Page == bpRef && !c.IsDeleted && c.Content == contentRef); } } else { blogPost = new BlogPost(); } if (pageContent == null) { pageContent = new PageContent { Page = blogPost }; } }
public override async Task InitializeAsync() { using (var context = TestContext.CreateNewContext()) { var user = new User("Test"); var authorProfile = new AuthorProfile("Tom", "Bina", "About me"); var authorValidator = new AuthorValidator(RequestDbContext); var author = await Author.Create(user, authorProfile, authorValidator); var blogPostContent = new BlogPostContent("Testsubject", "Testintro", "Testcontent"); var category = new Category("Testcategory", 1, "Test description"); var blogPost = new BlogPost(blogPostContent, author, category); context.BlogPosts.Add(blogPost); await context.SaveChangesAsync(); } }
/// <summary> /// Sets the publish status for the entity. /// </summary> private void SetPublishStatus(BlogPost page, BlogPostContent pageContent, bool publish) { if (publish) { page.BlogPostContent.Where(s => s.BlogContentId != pageContent.BlogContentId && (s.PublishStatus == PublishStatus.Draft || s.PublishStatus == PublishStatus.Published)).ToList().ForEach(s => s.PublishStatus = PublishStatus.OutOfDate); pageContent.PublishStatus = PublishStatus.Published; pageContent.PublishedByUserId = pageContent.PublishedByUserId ?? UserSession.Current.UserId; pageContent.PublishedUTCDate = pageContent.PublishedUTCDate ?? DateTime.UtcNow; } else { page.BlogPostContent.Where(s => s.BlogContentId != pageContent.BlogContentId && s.PublishStatus == PublishStatus.Draft).ToList().ForEach(s => s.PublishStatus = PublishStatus.Deleted); pageContent.PublishStatus = PublishStatus.Draft; pageContent.PublishedByUserId = null; pageContent.PublishedUTCDate = null; } }
public async Task BlogPostBuilder_DoesNotUpdatesBlogWithEqualMetaTag() { var blogPostContent = new BlogPostContent("", "", ""); var author = await Author.Create(new User(""), new AuthorProfile("", "", ""), Mock.Of <IAuthorValidator>()); var category = new Category("", 1, ""); var blogPost = new BlogPost(blogPostContent, author, category); blogPost.MetaTags.Add(new MetaTag("description", "test description")); var builder = new ExistingBlogPostBuilder(Mock.Of <IImageService>()); var tags = new[] { new MetaTag("description", "test description") }; await builder.UseBlogPost(blogPost).WithMetaTags(tags).Build(); Assert.Single(blogPost.MetaTags); }
/// <summary> /// Initializes a new instance of the <see cref="RenderBlogPostViewModel" /> class. /// </summary> /// <param name="blogPost">The blog post.</param> /// <param name="content">The content.</param> public RenderBlogPostViewModel(BlogPost blogPost = null, BlogPostContent content = null) { if (content != null) { ActivationDate = content.ActivationDate; ExpirationDate = content.ExpirationDate; } if (blogPost != null) { if (blogPost.Author != null) { Author = new RenderBlogPostAuthorViewModel(blogPost.Author); } if (content == null) { ActivationDate = blogPost.ActivationDate; ExpirationDate = blogPost.ExpirationDate; } } }
public override async Task InitializeAsync() { using (var context = TestContext.CreateNewContext()) { var user = new User("Test"); var authorProfile = new AuthorProfile("Tom", "Bina", "About me"); var authorValidator = new AuthorValidator(RequestDbContext); var author = await Author.Create(user, authorProfile, authorValidator); var blogPostContent = new BlogPostContent("Testsubject", "Testintro", "Testcontent"); var category = new Category("Testcategory", 1, "Test description"); var blogPost = new BlogPost(blogPostContent, author, category); context.BlogPosts.Add(blogPost); await context.SaveChangesAsync(); var userService = new Mock <IUserService>(); userService.Setup(exp => exp.GetOrCreateCurrentUserAsync()).ReturnsAsync(user); userService.Setup(exp => exp.TryGetCurrentUserAsync()).ReturnsAsync(user.ToSuccessResult()); } }
/// <summary> /// Updates an existing row in the database. /// </summary> private SaveResult UpdateBlog(BlogPost blog, BlogPostModel model, ContentManagementDb db) { if (UserSession.Current.IsAdministrator == false) { return(SaveResult.AccessDenied); } if (UserSession.Current.CurrentDomain().CanAccess(blog) == false) { return(SaveResult.IncorrectDomain); } try { BlogPostContent pageContent = blog.BlogPostContent.FirstOrDefault(s => s.PublishStatus == PublishStatus.Draft); if (pageContent == null) { pageContent = new BlogPostContent(); blog.BlogPostContent.Add(pageContent); } AutoMap.Map(model, pageContent); blog.UpdateTimeStamp(); pageContent.UpdateTimeStamp(); pageContent.LastEditedByUserId = UserSession.Current.UserId; SetPublishStatus(blog, pageContent, model.Publish); db.SaveChanges(); return(SaveResult.Success); } catch { return(SaveResult.Fail); } }
protected override BlogPostContent SaveContentWithStatusUpdate(bool isNew, BlogPostContent newContent, BlogPostViewModel model, IPrincipal principal) { var modelExt = model as BlogPostViewModelExtender; if (isNew && modelExt != null && !modelExt.ContentId.HasDefaultValue()) { contentService.UpdateDynamicContainer(newContent); if (model.DesirableStatus == ContentStatus.Published) { newContent.PublishedOn = modelExt.PublishedOn ?? DateTime.Now; newContent.PublishedByUser = principal.Identity.Name; // TODO: pass published by user newContent.PublishedByUser = !string.IsNullOrEmpty(request.Data.PublishedByUser) ? request.Data.PublishedByUser : securityService.CurrentPrincipalName; } newContent.Status = model.DesirableStatus; newContent.Id = modelExt.ContentId; repository.Save(newContent); return(newContent); } return(base.SaveContentWithStatusUpdate(isNew, newContent, model, principal)); }
public async Task <BlogPostContent> GetBlogPostContentAsync(string year, string month, string day, string name) { var blobName = $"{ year }/{ month }/{ day }/{ name }.md"; var client = await GetCloudBlobClientAsync(); var container = client.GetContainerReference(_appSettings.BlogPostContainer); var blogPostItem = container.GetBlockBlobReference(blobName); var stream = await blogPostItem.OpenReadAsync(null, null, new OperationContext()); var datePosted = await FormatDatePostedStringAsync(blogPostItem.Parent.Prefix); using var reader = new StreamReader(stream); var contentBuilder = new StringBuilder(); var blobContent = await reader.ReadToEndAsync(); var blogPostContent = new BlogPostContent { DatePosted = datePosted, PageContent = blobContent }; return(blogPostContent); }
protected virtual void MapExtraProperties(bool isNew, BlogPost entity, BlogPostContent content, PageContent pageContent, BlogPostViewModel model, IPrincipal principal) { entity.Version = model.Version; }
public BlogPostBuilder WithContent(IBlogPostContent content) { _blogPostContent = new BlogPostContent(content.Subject, content.ContentIntro, content.Content); return(this); }
/// <summary> /// Executes the specified request. /// </summary> /// <param name="id">The page id.</param> /// <returns></returns> /// <exception cref="System.NotImplementedException"></exception> public BlogPostViewModel Execute(Guid id) { var model = new BlogPostViewModel(); var categoriesFilterKey = BlogPost.CategorizableItemKeyForBlogs; if (!id.HasDefaultValue()) { var result = Repository.AsQueryable <BlogPost>() .Where(bp => bp.Id == id) .Select(bp => new { Entity = bp, AccessRules = bp.AccessRules, Model = new BlogPostViewModel { Id = bp.Id, Version = bp.Version, Title = bp.Title, BlogUrl = bp.PageUrl, UseCanonicalUrl = bp.UseCanonicalUrl, IntroText = bp.Description, AuthorId = bp.Author != null ? bp.Author.Id : (Guid?)null, Image = bp.Image == null || bp.Image.IsDeleted ? null : new ImageSelectorViewModel { ImageId = bp.Image.Id, ImageVersion = bp.Image.Version, ImageUrl = fileUrlResolver.EnsureFullPathUrl(bp.Image.PublicUrl), ThumbnailUrl = fileUrlResolver.EnsureFullPathUrl(bp.Image.PublicThumbnailUrl), ImageTooltip = bp.Image.Caption, FolderId = bp.Image.Folder != null ? bp.Image.Folder.Id : (Guid?)null } } }) .ToList() .FirstOne(); model = result.Model; if (model != null) { categoriesFilterKey = result.Entity.GetCategorizableItemKey(); if (cmsConfiguration.Security.AccessControlEnabled) { SetIsReadOnly(model, result.AccessRules.Cast <IAccessRule>().ToList()); } var pageContentId = Repository.AsQueryable <PageContent>() .Where(pageContent => pageContent.Page.Id == id && !pageContent.Page.IsDeleted && pageContent.Content is BlogPostContent) .Select(pageContent => pageContent.Id) .FirstOrDefault(); BlogPostContent content = null; if (!pageContentId.HasDefaultValue()) { var pageContent = contentService.GetPageContentForEdit(pageContentId); if (pageContent != null) { content = pageContent.Item2 as BlogPostContent; } } if (content != null) { model.Content = content.Html; model.ContentId = content.Id; model.ContentVersion = content.Version; model.LiveFromDate = content.ActivationDate; model.LiveToDate = content.ExpirationDate; model.EditInSourceMode = content.EditInSourceMode; model.CurrentStatus = content.Status; model.HasPublishedContent = content.Original != null; } else { model.LiveFromDate = DateTime.Today; } model.Categories = categoryService.GetSelectedCategories <BlogPost, PageCategory>(id).ToList(); model.Tags = tagService.GetPageTagNames(id).ToList(); } else { model = new BlogPostViewModel(); } } else { model.LiveFromDate = DateTime.Today; } model.Authors = authorService.GetAuthors(); model.RedirectFromOldUrl = true; model.CategoriesFilterKey = categoriesFilterKey; return(model); }
/// <summary> /// Saves the blog post. /// </summary> /// <param name="request">The request.</param> /// <param name="principal">The principal.</param> /// <returns> /// Saved blog post entity /// </returns> public BlogPost SaveBlogPost(BlogPostViewModel request, IPrincipal principal) { string[] roles; if (request.DesirableStatus == ContentStatus.Published) { accessControlService.DemandAccess(principal, RootModuleConstants.UserRoles.PublishContent); roles = new[] { RootModuleConstants.UserRoles.PublishContent }; } else { accessControlService.DemandAccess(principal, RootModuleConstants.UserRoles.EditContent); roles = new[] { RootModuleConstants.UserRoles.EditContent }; } Layout layout; Page masterPage; LoadLayout(out layout, out masterPage); if (masterPage != null) { var level = accessControlService.GetAccessLevel(masterPage, principal); if (level < AccessLevel.Read) { var message = BlogGlobalization.SaveBlogPost_FailedToSave_InaccessibleMasterPage; const string logMessage = "Failed to save blog post. Selected master page for page layout is inaccessible."; throw new ValidationException(() => message, logMessage); } } var region = LoadRegion(layout, masterPage); var isNew = request.Id.HasDefaultValue(); var userCanEdit = securityService.IsAuthorized(RootModuleConstants.UserRoles.EditContent); // UnitOfWork.BeginTransaction(); // NOTE: this causes concurrent data exception. BlogPost blogPost; BlogPostContent content = null; PageContent pageContent = null; Pages.Models.Redirect redirectCreated = null; // Loading blog post and it's content, or creating new, if such not exists if (!isNew) { var blogPostFuture = repository .AsQueryable <BlogPost>(b => b.Id == request.Id) .ToFuture(); content = repository .AsQueryable <BlogPostContent>(c => c.PageContents.Any(x => x.Page.Id == request.Id && !x.IsDeleted)) .ToFuture() .FirstOrDefault(); blogPost = blogPostFuture.FirstOne(); if (cmsConfiguration.Security.AccessControlEnabled) { accessControlService.DemandAccess(blogPost, principal, AccessLevel.ReadWrite, roles); } if (content != null) { // Check if user has confirmed the deletion of content if (!request.IsUserConfirmed && blogPost.IsMasterPage) { var hasAnyChildren = contentService.CheckIfContentHasDeletingChildren(blogPost.Id, content.Id, request.Content); if (hasAnyChildren) { var message = PagesGlobalization.SaveContent_ContentHasChildrenContents_RegionDeleteConfirmationMessage; var logMessage = string.Format("User is trying to delete content regions which has children contents. Confirmation is required. ContentId: {0}, PageId: {1}", content.Id, blogPost.Id); throw new ConfirmationRequestException(() => message, logMessage); } } pageContent = repository.FirstOrDefault <PageContent>(c => c.Page == blogPost && !c.IsDeleted && c.Content == content); } if (userCanEdit && !string.Equals(blogPost.PageUrl, request.BlogUrl) && request.BlogUrl != null) { request.BlogUrl = urlService.FixUrl(request.BlogUrl); pageService.ValidatePageUrl(request.BlogUrl, request.Id); if (request.RedirectFromOldUrl) { var redirect = redirectService.CreateRedirectEntity(blogPost.PageUrl, request.BlogUrl); if (redirect != null) { repository.Save(redirect); redirectCreated = redirect; } } blogPost.PageUrl = urlService.FixUrl(request.BlogUrl); } } else { blogPost = new BlogPost(); } if (pageContent == null) { pageContent = new PageContent { Region = region, Page = blogPost }; } // Push to change modified data each time. blogPost.ModifiedOn = DateTime.Now; blogPost.Version = request.Version; if (userCanEdit) { blogPost.Title = request.Title; blogPost.Description = request.IntroText; blogPost.Author = request.AuthorId.HasValue ? repository.AsProxy <Author>(request.AuthorId.Value) : null; blogPost.Category = request.CategoryId.HasValue ? repository.AsProxy <Category>(request.CategoryId.Value) : null; blogPost.Image = (request.Image != null && request.Image.ImageId.HasValue) ? repository.AsProxy <MediaImage>(request.Image.ImageId.Value) : null; if (isNew || request.DesirableStatus == ContentStatus.Published) { blogPost.ActivationDate = request.LiveFromDate; blogPost.ExpirationDate = TimeHelper.FormatEndDate(request.LiveToDate); } } if (isNew) { if (!string.IsNullOrWhiteSpace(request.BlogUrl)) { blogPost.PageUrl = urlService.FixUrl(request.BlogUrl); pageService.ValidatePageUrl(blogPost.PageUrl); } else { blogPost.PageUrl = CreateBlogPermalink(request.Title); } blogPost.MetaTitle = request.MetaTitle ?? request.Title; if (masterPage != null) { blogPost.MasterPage = masterPage; masterPageService.SetPageMasterPages(blogPost, masterPage.Id); } else { blogPost.Layout = layout; } UpdateStatus(blogPost, request.DesirableStatus); AddDefaultAccessRules(blogPost, principal, masterPage); } else if (request.DesirableStatus == ContentStatus.Published || blogPost.Status == PageStatus.Preview) { // Update only if publishing or current status is preview. // Else do not change, because it may change from published to draft status UpdateStatus(blogPost, request.DesirableStatus); } // Create content. var newContent = new BlogPostContent { Id = content != null ? content.Id : Guid.Empty, Name = request.Title, Html = request.Content ?? string.Empty, EditInSourceMode = request.EditInSourceMode, ActivationDate = request.LiveFromDate, ExpirationDate = TimeHelper.FormatEndDate(request.LiveToDate) }; // Preserve content if user is not authorized to change it. if (!userCanEdit) { if (content == null) { throw new SecurityException("Forbidden: Access is denied."); // User has no rights to create new content. } var contentToPublish = (BlogPostContent)(content.History != null ? content.History.FirstOrDefault(c => c.Status == ContentStatus.Draft) ?? content : content); newContent.Name = contentToPublish.Name; newContent.Html = contentToPublish.Html; } content = (BlogPostContent)contentService.SaveContentWithStatusUpdate(newContent, request.DesirableStatus); pageContent.Content = content; blogPost.PageUrlHash = blogPost.PageUrl.UrlHash(); blogPost.UseCanonicalUrl = request.UseCanonicalUrl; repository.Save(blogPost); repository.Save(content); repository.Save(pageContent); pageContent.Content = content; blogPost.PageContents = new [] { pageContent }; IList <Tag> newTags = null; if (userCanEdit) { tagService.SavePageTags(blogPost, request.Tags, out newTags); } // Commit unitOfWork.Commit(); // Notify about new or updated blog post. if (isNew) { Events.BlogEvents.Instance.OnBlogCreated(blogPost); } else { Events.BlogEvents.Instance.OnBlogUpdated(blogPost); } // Notify about new created tags. Events.RootEvents.Instance.OnTagCreated(newTags); // Notify about redirect creation. if (redirectCreated != null) { Events.PageEvents.Instance.OnRedirectCreated(redirectCreated); } return(blogPost); }
/// <summary> /// Executes the specified request. /// </summary> /// <param name="id">The page id.</param> /// <returns></returns> /// <exception cref="System.NotImplementedException"></exception> public BlogPostViewModel Execute(Guid id) { var model = new BlogPostViewModel(); if (!id.HasDefaultValue()) { model = Repository.AsQueryable <BlogPost>() .Where(bp => bp.Id == id) .Select(bp => new BlogPostViewModel { Id = bp.Id, Version = bp.Version, Title = bp.Title, BlogUrl = bp.PageUrl, LiveFromDate = bp.ActivationDate, LiveToDate = bp.ExpirationDate, IntroText = bp.Description, AuthorId = bp.Author.Id, CategoryId = bp.Category.Id, Image = bp.Image == null ? null : new ImageSelectorViewModel { ImageId = bp.Image.Id, ImageVersion = bp.Image.Version, ImageUrl = bp.Image.PublicUrl, ThumbnailUrl = bp.Image.PublicThumbnailUrl, ImageTooltip = bp.Image.Caption } }) .FirstOne(); if (model != null) { var regionId = UnitOfWork.Session .QueryOver <Region>() .Where(r => r.RegionIdentifier == BlogModuleConstants.BlogPostMainContentRegionIdentifier) .Select(r => r.Id) .FutureValue <Guid>(); PageContent pageContentAlias = null; BlogPostContent blogPostContentAlias = null; var pageContentId = UnitOfWork.Session .QueryOver(() => pageContentAlias) .Inner.JoinAlias(c => c.Content, () => blogPostContentAlias) .Where(() => pageContentAlias.Page.Id == id && !pageContentAlias.IsDeleted && pageContentAlias.Region.Id == regionId.Value) .OrderBy(() => pageContentAlias.CreatedOn).Asc .Select(c => c.Id) .Take(1) .List <Guid>() .FirstOrDefault(); BlogPostContent content = null; if (!pageContentId.HasDefaultValue()) { var pageContent = contentService.GetPageContentForEdit(pageContentId); if (pageContent != null) { content = pageContent.Item2 as BlogPostContent; } } if (content != null) { model.Content = content.Html; model.ContentId = content.Id; model.ContentVersion = content.Version; model.EditInSourceMode = content.EditInSourceMode; model.CurrentStatus = content.Status; model.HasPublishedContent = content.Original != null; } else { model.LiveFromDate = DateTime.Today; } model.Tags = tagService.GetPageTagNames(id); } else { model = new BlogPostViewModel(); } } else { model.LiveFromDate = DateTime.Today; } model.Authors = authorService.GetAuthors(); model.Categories = categoryService.GetCategories(); model.RedirectFromOldUrl = true; return(model); }
/// <summary> /// Executes the specified request. /// </summary> /// <param name="request">The request.</param> /// <returns>Blog post view model</returns> public SaveBlogPostCommandResponse Execute(BlogPostViewModel request) { if (request.DesirableStatus == ContentStatus.Published) { AccessControlService.DemandAccess(Context.Principal, RootModuleConstants.UserRoles.PublishContent); } var layout = LoadLayout(); var region = LoadRegion(); var isNew = request.Id.HasDefaultValue(); var userCanEdit = false; if (isNew || request.DesirableStatus != ContentStatus.Published) { AccessControlService.DemandAccess(Context.Principal, RootModuleConstants.UserRoles.EditContent); userCanEdit = true; } else { userCanEdit = SecurityService.IsAuthorized(RootModuleConstants.UserRoles.EditContent); } // UnitOfWork.BeginTransaction(); // NOTE: this causes concurrent data exception. BlogPost blogPost; BlogPostContent content = null; PageContent pageContent = null; Pages.Models.Redirect redirectCreated = null; // Loading blog post and it's content, or creating new, if such not exists if (!isNew) { blogPost = Repository.First <BlogPost>(request.Id); content = Repository.FirstOrDefault <BlogPostContent>(c => c.PageContents.Any(x => x.Page == blogPost && x.Region == region && !x.IsDeleted)); if (content != null) { pageContent = Repository.FirstOrDefault <PageContent>(c => c.Page == blogPost && c.Region == region && !c.IsDeleted && c.Content == content); } if (userCanEdit && !string.Equals(blogPost.PageUrl, request.BlogUrl) && request.BlogUrl != null) { request.BlogUrl = urlService.FixUrl(request.BlogUrl); pageService.ValidatePageUrl(request.BlogUrl, request.Id); if (request.RedirectFromOldUrl) { var redirect = redirectService.CreateRedirectEntity(blogPost.PageUrl, request.BlogUrl); if (redirect != null) { Repository.Save(redirect); redirectCreated = redirect; } } blogPost.PageUrl = urlService.FixUrl(request.BlogUrl); } } else { blogPost = new BlogPost(); AddDefaultAccessRules(blogPost); } if (pageContent == null) { pageContent = new PageContent { Region = region, Page = blogPost }; } // Push to change modified data each time. blogPost.ModifiedOn = DateTime.Now; blogPost.Version = request.Version; if (userCanEdit) { blogPost.Title = request.Title; blogPost.Description = request.IntroText; blogPost.Author = request.AuthorId.HasValue ? Repository.AsProxy <Author>(request.AuthorId.Value) : null; blogPost.Category = request.CategoryId.HasValue ? Repository.AsProxy <Category>(request.CategoryId.Value) : null; blogPost.Image = (request.Image != null && request.Image.ImageId.HasValue) ? Repository.AsProxy <MediaImage>(request.Image.ImageId.Value) : null; if (isNew || request.DesirableStatus == ContentStatus.Published) { blogPost.ActivationDate = request.LiveFromDate; blogPost.ExpirationDate = TimeHelper.FormatEndDate(request.LiveToDate); } } if (isNew) { if (!string.IsNullOrWhiteSpace(request.BlogUrl)) { blogPost.PageUrl = urlService.FixUrl(request.BlogUrl); pageService.ValidatePageUrl(blogPost.PageUrl); } else { blogPost.PageUrl = blogService.CreateBlogPermalink(request.Title); } blogPost.MetaTitle = request.Title; blogPost.Layout = layout; UpdateStatus(blogPost, request.DesirableStatus); } else if (request.DesirableStatus == ContentStatus.Published) { UpdateStatus(blogPost, request.DesirableStatus); } // Create content. var newContent = new BlogPostContent { Id = content != null ? content.Id : Guid.Empty, Name = request.Title, Html = request.Content ?? string.Empty, EditInSourceMode = request.EditInSourceMode, ActivationDate = request.LiveFromDate, ExpirationDate = TimeHelper.FormatEndDate(request.LiveToDate) }; // Preserve content if user is not authorized to change it. if (!userCanEdit) { if (content == null) { throw new SecurityException("Forbidden: Access is denied."); // User has no rights to create new content. } var contentToPublish = (BlogPostContent)(content.History != null ? content.History.FirstOrDefault(c => c.Status == ContentStatus.Draft) ?? content : content); newContent.Name = contentToPublish.Name; newContent.Html = contentToPublish.Html; } content = (BlogPostContent)contentService.SaveContentWithStatusUpdate(newContent, request.DesirableStatus); pageContent.Content = content; blogPost.PageUrlHash = blogPost.PageUrl.UrlHash(); blogPost.UseCanonicalUrl = request.UseCanonicalUrl; Repository.Save(blogPost); Repository.Save(content); Repository.Save(pageContent); // Save tags if user has edit right. IList <Tag> newTags = null; if (userCanEdit) { tagService.SavePageTags(blogPost, request.Tags, out newTags); } // Commit UnitOfWork.Commit(); // Notify about new or updated blog post. if (isNew) { Events.BlogEvents.Instance.OnBlogCreated(blogPost); } else { Events.BlogEvents.Instance.OnBlogUpdated(blogPost); } // Notify about new created tags. Events.RootEvents.Instance.OnTagCreated(newTags); // Notify about redirect creation. if (redirectCreated != null) { Events.PageEvents.Instance.OnRedirectCreated(redirectCreated); } return(new SaveBlogPostCommandResponse { Id = blogPost.Id, Version = blogPost.Version, Title = blogPost.Title, PageUrl = blogPost.PageUrl, ModifiedByUser = blogPost.ModifiedByUser, ModifiedOn = blogPost.ModifiedOn.ToFormattedDateString(), CreatedOn = blogPost.CreatedOn.ToFormattedDateString(), PageStatus = blogPost.Status, DesirableStatus = request.DesirableStatus, PageContentId = pageContent.Id }); }
/// <summary> /// Creates the test view model. /// </summary> /// <returns>Test view model</returns> private RenderPageViewModel CreateTestViewModel(bool extendModel = false) { var entity = new BlogPost { Title = "Fake Page Title", PageUrl = "/Fake/Page/Url/s", Id = new Guid("DB4C3C70-F5F3-44A1-9472-6155A9A77D89"), CreatedOn = new DateTime(2010, 11, 15), ModifiedOn = new DateTime(2012, 12, 3), CreatedByUser = "******", ModifiedByUser = "******", MetaTitle = "Fake Page Meta Title", MetaKeywords = "Fake Page Meta Keywords", MetaDescription = "Fake Page MetaDescription", ActivationDate = new DateTime(2012, 5, 12), ExpirationDate = new DateTime(2013, 4, 18) }; if (extendModel) { entity.Categories = new List <PageCategory>() { new PageCategory() { Category = new Category { Name = "Fake Category Name" }, Page = entity } }; entity.Author = new Author { Name = "Fake Author Name" }; entity.Image = new MediaImage { PublicUrl = "/Fake/Main/Image/Url/" }; entity.SecondaryImage = new MediaImage { PublicUrl = "/Fake/Secondary/Image/Url/" }; entity.FeaturedImage = new MediaImage { PublicUrl = "/Fake/Featured/Image/Url/" }; entity.ActivationDate = new DateTime(); var content = new BlogPostContent { ActivationDate = new DateTime(2012, 5, 12), ExpirationDate = new DateTime(2013, 4, 18) }; var pageContent = new PageContent { Content = content, Page = entity }; entity.PageContents = new List <PageContent> { pageContent }; } var model = new RenderPageViewModel(entity) { Options = new List <IOptionValue> { new OptionValueViewModel { OptionKey = OptionNames.Text, OptionValue = "Fake Option Value", Type = OptionType.Text }, new OptionValueViewModel { OptionKey = OptionNames.Float, OptionValue = 10.123456M, Type = OptionType.Float }, new OptionValueViewModel { OptionKey = OptionNames.Date, OptionValue = new DateTime(2009, 4, 27), Type = OptionType.DateTime } } }; if (extendModel) { model.Contents = new List <PageContentProjection>(); model.Contents.Add( new PageContentProjection( entity.PageContents[0], entity.PageContents[0].Content, new BlogPostContentAccessor((BlogPostContent)entity.PageContents[0].Content, new List <IOptionValue>()))); model.ExtendWithPageData(entity); model.ExtendWithBlogData(entity); } return(model); }
/// <summary> /// Saves the blog post. /// </summary> /// <param name="request">The request.</param> /// <param name="childContentOptionValues">The child content option values.</param> /// <param name="principal">The principal.</param> /// <param name="errorMessages">The error messages.</param> /// <returns> /// Saved blog post entity /// </returns> /// <exception cref="System.ComponentModel.DataAnnotations.ValidationException"></exception> /// <exception cref="SecurityException">Forbidden: Access is denied.</exception> public BlogPost SaveBlogPost(BlogPostViewModel request, IList <ContentOptionValuesViewModel> childContentOptionValues, IPrincipal principal, out string[] errorMessages) { errorMessages = new string[0]; string[] roles; if (request.DesirableStatus == ContentStatus.Published) { accessControlService.DemandAccess(principal, RootModuleConstants.UserRoles.PublishContent); roles = new[] { RootModuleConstants.UserRoles.PublishContent }; } else { accessControlService.DemandAccess(principal, RootModuleConstants.UserRoles.EditContent); roles = new[] { RootModuleConstants.UserRoles.EditContent }; } var isNew = request.Id.HasDefaultValue(); var userCanEdit = securityService.IsAuthorized(RootModuleConstants.UserRoles.EditContent); ValidateData(isNew, request); BlogPost blogPost; BlogPostContent content; PageContent pageContent; GetBlogPostAndContentEntities(request, principal, roles, ref isNew, out content, out pageContent, out blogPost); var beforeChange = new UpdatingBlogModel(blogPost); // Master page / layout Layout layout; Page masterPage; Region region; LoadDefaultLayoutAndRegion(out layout, out masterPage, out region); if (masterPage != null) { var level = accessControlService.GetAccessLevel(masterPage, principal); if (level < AccessLevel.Read) { var message = BlogGlobalization.SaveBlogPost_FailedToSave_InaccessibleMasterPage; const string logMessage = "Failed to save blog post. Selected master page for page layout is inaccessible."; throw new ValidationException(() => message, logMessage); } } if (pageContent.Region == null) { pageContent.Region = region; } // Load master pages for updating page's master path and page's children master path IList <Guid> newMasterIds; IList <Guid> oldMasterIds; IList <Guid> childrenPageIds; IList <MasterPage> existingChildrenMasterPages; PrepareForUpdateChildrenMasterPages(isNew, blogPost, request, out newMasterIds, out oldMasterIds, out childrenPageIds, out existingChildrenMasterPages); // TODO: TEST AND TRY TO FIX IT: TRANSACTION HERE IS REQUIRED! // UnitOfWork.BeginTransaction(); // NOTE: this causes concurrent data exception. Redirect redirectCreated = null; if (!isNew && userCanEdit && !string.Equals(blogPost.PageUrl, request.BlogUrl) && !string.IsNullOrWhiteSpace(request.BlogUrl)) { request.BlogUrl = urlService.FixUrl(request.BlogUrl); pageService.ValidatePageUrl(request.BlogUrl, request.Id); if (request.RedirectFromOldUrl) { var redirect = redirectService.CreateRedirectEntity(blogPost.PageUrl, request.BlogUrl); if (redirect != null) { repository.Save(redirect); redirectCreated = redirect; } } blogPost.PageUrl = urlService.FixUrl(request.BlogUrl); } // Push to change modified data each time. blogPost.ModifiedOn = DateTime.Now; if (userCanEdit) { blogPost.Title = request.Title; blogPost.Description = request.IntroText; blogPost.Author = request.AuthorId.HasValue ? repository.AsProxy <Author>(request.AuthorId.Value) : null; blogPost.Category = request.CategoryId.HasValue ? repository.AsProxy <Category>(request.CategoryId.Value) : null; blogPost.Image = (request.Image != null && request.Image.ImageId.HasValue) ? repository.AsProxy <MediaImage>(request.Image.ImageId.Value) : null; if (isNew || request.DesirableStatus == ContentStatus.Published) { blogPost.ActivationDate = request.LiveFromDate; blogPost.ExpirationDate = TimeHelper.FormatEndDate(request.LiveToDate); } } if (isNew) { if (!string.IsNullOrWhiteSpace(request.BlogUrl)) { blogPost.PageUrl = urlService.FixUrl(request.BlogUrl); pageService.ValidatePageUrl(blogPost.PageUrl); } else { blogPost.PageUrl = CreateBlogPermalink(request.Title, null, blogPost.Category != null ? (Guid?)blogPost.Category.Id : null); } blogPost.MetaTitle = request.MetaTitle ?? request.Title; if (masterPage != null) { blogPost.MasterPage = masterPage; masterPageService.SetPageMasterPages(blogPost, masterPage.Id); } else { blogPost.Layout = layout; } UpdateStatus(blogPost, request.DesirableStatus); AddDefaultAccessRules(blogPost, principal, masterPage); } else if (request.DesirableStatus == ContentStatus.Published || blogPost.Status == PageStatus.Preview) { // Update only if publishing or current status is preview. // Else do not change, because it may change from published to draft status UpdateStatus(blogPost, request.DesirableStatus); } // Create content. var newContent = new BlogPostContent { Id = content != null ? content.Id : Guid.Empty, Name = request.Title, Html = request.Content ?? string.Empty, EditInSourceMode = request.EditInSourceMode, ActivationDate = request.LiveFromDate, ExpirationDate = TimeHelper.FormatEndDate(request.LiveToDate) }; // Preserve content if user is not authorized to change it. if (!userCanEdit) { if (content == null) { throw new SecurityException("Forbidden: Access is denied."); // User has no rights to create new content. } var contentToPublish = (BlogPostContent)(content.History != null ? content.History.FirstOrDefault(c => c.Status == ContentStatus.Draft) ?? content : content); newContent.Name = contentToPublish.Name; newContent.Html = contentToPublish.Html; } content = SaveContentWithStatusUpdate(isNew, newContent, request, principal); pageContent.Content = content; optionService.SaveChildContentOptions(content, childContentOptionValues, request.DesirableStatus); blogPost.PageUrlHash = blogPost.PageUrl.UrlHash(); blogPost.UseCanonicalUrl = request.UseCanonicalUrl; MapExtraProperties(isNew, blogPost, content, pageContent, request, principal); // Notify about page properties changing. var cancelEventArgs = Events.BlogEvents.Instance.OnBlogChanging(beforeChange, new UpdatingBlogModel(blogPost)); if (cancelEventArgs.Cancel) { errorMessages = cancelEventArgs.CancellationErrorMessages.ToArray(); return(null); } repository.Save(blogPost); repository.Save(content); repository.Save(pageContent); masterPageService.UpdateChildrenMasterPages(existingChildrenMasterPages, oldMasterIds, newMasterIds, childrenPageIds); pageContent.Content = content; blogPost.PageContents = new [] { pageContent }; IList <Tag> newTags = null; if (userCanEdit) { newTags = SaveTags(blogPost, request); } // Commit unitOfWork.Commit(); // Notify about new created tags. Events.RootEvents.Instance.OnTagCreated(newTags); // Notify about new or updated blog post. if (isNew) { Events.BlogEvents.Instance.OnBlogCreated(blogPost); } else { Events.BlogEvents.Instance.OnBlogUpdated(blogPost); } // Notify about redirect creation. if (redirectCreated != null) { Events.PageEvents.Instance.OnRedirectCreated(redirectCreated); } return(blogPost); }
protected virtual BlogPostContent SaveContentWithStatusUpdate(bool isNew, BlogPostContent newContent, BlogPostViewModel request, IPrincipal principal) { return((BlogPostContent)contentService.SaveContentWithStatusUpdate(newContent, request.DesirableStatus)); }
/// <summary> /// Gets the filtered blog posts query. /// </summary> /// <param name="request">The filter.</param> /// <param name="joinContents">if set to <c>true</c> join contents tables.</param> /// <returns> /// NHibernate query for getting filtered blog posts /// </returns> public NHibernate.IQueryOver <BlogPost, BlogPost> GetFilteredBlogPostsQuery(ViewModels.Filter.BlogsFilter request, bool joinContents = false) { request.SetDefaultSortingOptions("Title"); BlogPost alias = null; var query = unitOfWork.Session .QueryOver(() => alias) .Where(() => !alias.IsDeleted && alias.Status != PageStatus.Preview); if (!request.IncludeArchived) { query = query.Where(() => !alias.IsArchived); } if (!string.IsNullOrWhiteSpace(request.SearchQuery)) { var searchQuery = string.Format("%{0}%", request.SearchQuery); query = query.Where(Restrictions.InsensitiveLike(Projections.Property(() => alias.Title), searchQuery)); } if (request.CategoryId.HasValue) { query = query.Where(Restrictions.Eq(Projections.Property(() => alias.Category.Id), request.CategoryId.Value)); } if (request.LanguageId.HasValue) { if (request.LanguageId.Value.HasDefaultValue()) { query = query.Where(Restrictions.IsNull(Projections.Property(() => alias.Language.Id))); } else { query = query.Where(Restrictions.Eq(Projections.Property(() => alias.Language.Id), request.LanguageId.Value)); } } if (request.Tags != null) { foreach (var tagKeyValue in request.Tags) { var id = tagKeyValue.Key.ToGuidOrDefault(); query = query.WithSubquery.WhereExists(QueryOver.Of <PageTag>().Where(tag => tag.Tag.Id == id && tag.Page.Id == alias.Id).Select(tag => 1)); } } if (request.Status.HasValue) { if (request.Status.Value == PageStatusFilterType.OnlyPublished) { query = query.Where(() => alias.Status == PageStatus.Published); } else if (request.Status.Value == PageStatusFilterType.OnlyUnpublished) { query = query.Where(() => alias.Status != PageStatus.Published); } else if (request.Status.Value == PageStatusFilterType.ContainingUnpublishedContents) { const ContentStatus draft = ContentStatus.Draft; Root.Models.Content contentAlias = null; var subQuery = QueryOver.Of <PageContent>() .JoinAlias(p => p.Content, () => contentAlias) .Where(pageContent => pageContent.Page.Id == alias.Id) .And(() => contentAlias.Status == draft) .And(() => !contentAlias.IsDeleted) .Select(pageContent => 1); query = query.WithSubquery.WhereExists(subQuery); } } if (request.SeoStatus.HasValue) { var subQuery = QueryOver.Of <SitemapNode>() .Where(x => x.Page.Id == alias.Id || x.UrlHash == alias.PageUrlHash) .And(x => !x.IsDeleted) .JoinQueryOver(s => s.Sitemap) .And(x => !x.IsDeleted) .Select(s => 1); var hasSeoDisjunction = Restrictions.Disjunction() .Add(RestrictionsExtensions.IsNullOrWhiteSpace(Projections.Property(() => alias.MetaTitle))) .Add(RestrictionsExtensions.IsNullOrWhiteSpace(Projections.Property(() => alias.MetaKeywords))) .Add(RestrictionsExtensions.IsNullOrWhiteSpace(Projections.Property(() => alias.MetaDescription))) .Add(Subqueries.WhereNotExists(subQuery)); if (request.SeoStatus.Value == SeoStatusFilterType.HasSeo) { query = query.Where(Restrictions.Not(hasSeoDisjunction)); } else { query = query.Where(hasSeoDisjunction); } } if (joinContents) { PageContent pcAlias = null; BlogPostContent bcAlias = null; query = query.JoinAlias(() => alias.PageContents, () => pcAlias); query = query.JoinAlias(() => pcAlias.Content, () => bcAlias); } return(query); }
protected override void MapExtraProperties(bool isNew, BlogPost entity, BlogPostContent content, PageContent pageContent, BlogPostViewModel model, IPrincipal principal) { var currentVersion = entity.Version; base.MapExtraProperties(isNew, entity, content, pageContent, model, principal); var modelExt = model as BlogPostViewModelExtender; if (modelExt != null) { // Restore version if not set from the extended model if (model.Version <= 0) { entity.Version = currentVersion; } entity.SecondaryImage = modelExt.SecondaryImageId.HasValue ? repository.AsProxy <MediaImage>(modelExt.SecondaryImageId.Value) : null; entity.FeaturedImage = modelExt.FeaturedImageId.HasValue ? repository.AsProxy <MediaImage>(modelExt.FeaturedImageId.Value) : null; entity.IsArchived = modelExt.IsArchived; entity.UseNoFollow = modelExt.UseNoFollow; entity.UseNoIndex = modelExt.UseNoIndex; entity.MetaKeywords = modelExt.MetaKeywords; entity.MetaDescription = modelExt.MetaDescription; if (modelExt.UpdateLanguage) { entity.Language = modelExt.LanguageId.HasValue ? repository.AsProxy <Language>(modelExt.LanguageId.Value) : null; entity.LanguageGroupIdentifier = modelExt.LanguageGroupIdentifier; } // If creating new and content / page content / region ids are set, enforce them to be set explicitly if (isNew && !model.ContentId.HasDefaultValue() && modelExt.PageContentId.HasValue && modelExt.RegionId.HasValue) { pageContent.Id = modelExt.PageContentId.Value; pageContent.Region = repository.AsProxy <Region>(modelExt.RegionId.Value); } // Set blog post Id, if it's set if (isNew && !model.Id.HasDefaultValue()) { entity.Id = model.Id; } // PublishedOn if (isNew && entity.Status == PageStatus.Published && modelExt.PublishedOn.HasValue) { entity.PublishedOn = modelExt.PublishedOn.Value; } // Set layout / master page if (modelExt.MasterPageId.HasValue) { entity.Layout = null; if (isNew) { entity.MasterPage = repository .AsQueryable <Page>(p => p.Id == modelExt.MasterPageId.Value) .FetchMany(p => p.AccessRules) .ToList() .FirstOne(); if (modelExt.AccessRules == null) { AddDefaultAccessRules(entity, principal, entity.MasterPage); } masterPageService.SetPageMasterPages(entity, entity.MasterPage.Id); } else { entity.MasterPage = repository.AsProxy <Page>(modelExt.MasterPageId.Value); } } else if (modelExt.LayoutId.HasValue) { entity.Layout = repository.AsProxy <Layout>(modelExt.LayoutId.Value); entity.MasterPage = null; if (isNew && modelExt.AccessRules == null) { AddDefaultAccessRules(entity, principal, null); } } // Add access rules from the request if (modelExt.AccessRules != null) { if (entity.AccessRules == null) { entity.AccessRules = new List <AccessRule>(); } else { entity.AccessRules.RemoveDuplicateEntities(); } var accessRules = modelExt.AccessRules .Select(r => (IAccessRule) new AccessRule { AccessLevel = (AccessLevel)(int)r.AccessLevel, Identity = r.Identity, IsForRole = r.IsForRole }).ToList(); accessControlService.UpdateAccessControl(entity, accessRules); } } }
protected override void GetBlogPostAndContentEntities(BlogPostViewModel model, IPrincipal principal, string[] roles, ref bool isNew, out BlogPostContent content, out PageContent pageContent, out BlogPost blogPost) { var modelExt = model as BlogPostViewModelExtender; if (!isNew && modelExt != null) { content = null; pageContent = null; blogPost = repository .AsQueryable <BlogPost>(bp => bp.Id == model.Id) .FetchMany(bp => bp.AccessRules) .FetchMany(bp => bp.PageTags) .ThenFetch(pt => pt.Tag) .ToList() .FirstOrDefault(); if (blogPost != null) { if (configuration.Security.AccessControlEnabled) { accessControlService.DemandAccess(blogPost, principal, AccessLevel.ReadWrite, roles); } if (modelExt.PageContentId.HasValue) { content = repository .AsQueryable <BlogPostContent>(c => c.PageContents.Any(x => x.Page.Id == model.Id && !x.IsDeleted && x.Id == modelExt.PageContentId.Value && !x.IsDeleted && c.Id == model.ContentId)) .ToFuture() .FirstOrDefault(); if (content == null) { const string message = "Cannot find a blog post content by specified blog post content and Id and page content Id."; var logMessage = string.Format("{0} BlogId: {1}, BlogPostContentId: {2}, PageContentId: {3}", message, model.Id, model.ContentId, modelExt.PageContentId); throw new ValidationException(() => message, logMessage); } pageContent = repository.First <PageContent>(pc => pc.Id == modelExt.PageContentId.Value); } else { content = repository .AsQueryable <BlogPostContent>(c => c.PageContents.Any(x => x.Page.Id == model.Id && !x.IsDeleted) && !c.IsDeleted) .ToFuture() .FirstOrDefault(); if (content != null) { var contentRef = content; pageContent = repository.FirstOrDefault <PageContent>(c => c.Page.Id == model.Id && !c.IsDeleted && c.Content == contentRef); } } } isNew = blogPost == null; if (isNew) { blogPost = new BlogPost(); pageContent = new PageContent { Page = blogPost }; } } else { base.GetBlogPostAndContentEntities(model, principal, roles, ref isNew, out content, out pageContent, out blogPost); } }
public BlogPostModel(BlogPost blog) { BlogPostContent blogContent = blog.BlogPostContent.OrderByDescending(s => s.UTCDateUpdated).First(); AutoMap.Map(blogContent, this); }