Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Jonathan Ben Avraham 43 posts 216 karma points
    May 05, 2016 @ 08:46
    Jonathan Ben Avraham
    0

    Exporting Blog Posts (umbNewsItem)

    Is there any way I can use the ContentService to export blog posts including their data like Title, Body Text, Author, PubDate etc?

    Currently I have to go a really round-about way to do this:

    public class ExportAllBlogsController : UmbracoAuthorizedApiController
    {
        private StringBuilder sb = new StringBuilder();
        [System.Web.Http.AcceptVerbs("GET", "POST")]
        public void ExportAll()
        {
            List<BlogPosts> BlogPostList = new List<BlogPosts>();
            BlogPostList = getPostList();
    
            string attachment = "attachment; filename= BlogPosts.xls;";
            HttpContext.Current.Response.Clear();
            HttpContext.Current.Response.ClearHeaders();
            HttpContext.Current.Response.ClearContent();
            HttpContext.Current.Response.AddHeader("Content-Disposition", attachment);
            HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";
            HttpContext.Current.Response.AddHeader("Pragma", "public");
            HttpContext.Current.Response.CacheControl= "private";
    
            WriteColumnName();
            foreach (BlogPosts post in BlogPostList)
            {
                WritePostInfo(post);
            }
    
            HttpContext.Current.Response.Flush();
            HttpContext.Current.Response.End();
        }
    
        private void WritePostInfo(BlogPosts post)
        {
            AddComma(post.dataNtext, sb);
            HttpContext.Current.Response.Write(sb.ToString());
            HttpContext.Current.Response.Write(Environment.NewLine);
        }
    
        private void AddComma(string value, StringBuilder sb)
        {
            sb.Append(value.Replace(',', ' '));
            sb.Append("; ");
        }
    
        private void WriteColumnName()
        {
            string columnNames = "Body Text";
            HttpContext.Current.Response.Write(columnNames);
            HttpContext.Current.Response.Write(Environment.NewLine);
        }
    
        public List<BlogPosts> getPostList()
        {
            UmbracoDatabase db = ApplicationContext.DatabaseContext.Database;
            var select = new Sql("SELECT dataNtext FROM cmsPropertyData WHERE propertytypeid = 57;");
            List<BlogPosts> BlogPostList = new List<BlogPosts>();
            BlogPostList = db.Fetch<BlogPosts>(select);
            return BlogPostList;
        }
    }
    

    This is my controller, you see I have to go into the database and select each column, but the problem here is that each column is in different tables.

    Id Umbraco ContentService has a way that would allow me to export this into a CSV or XLS file, that would be amazing to know.

    Thanks in advance!

  • Manish 373 posts 932 karma points
    May 05, 2016 @ 08:49
    Manish
    0

    How about using this package for blog

    https://our.umbraco.org/projects/starter-kits/smart-blog/

    Manish

  • Dennis Aaen 4499 posts 18254 karma points admin hq c-trib
    May 05, 2016 @ 08:50
    Dennis Aaen
    0

    Hi Jonathan,

    So you want to export the export blog posts including their data like Title, Body Text, Author, PubDate etc, so you can import it to another Umbraco installation?

    If this the case than you can use the package called CMSImport https://our.umbraco.org/projects/developer-tools/cmsimport/

    Another way is to create a package in Umbraco where you includes the document types and the content of the umbNewsItems.

    Here is an older blogpost on how to create a package. http://www.uquickstart.com/umbraco-tips-and-tools/package-up-your-umbraco-website but the method is the same in the newer Umbraco installations.

    Hope this helps,

    -Dennis

  • Jonathan Ben Avraham 43 posts 216 karma points
    May 05, 2016 @ 08:53
    Jonathan Ben Avraham
    0

    The point here is not to use an already built package. This is for a work project, I have to build a bespoke export package which allows the back office user to export/import the blog posts. Another challenge here might be that the package has to be compatible with both an older version of Umbraco where I would be exporting the blog and a newer version of Umbraco where I would be importing the blog.

  • Dennis Adolfi 1082 posts 6446 karma points MVP 5x c-trib
    May 05, 2016 @ 09:25
    Dennis Adolfi
    1

    Here is an small example of how you can get all nodes by a specific contenttype (umbNewsItem), get the properties you want and then return it like a custom list:

    public List<BlogPost> GetPostList()
            {
                var contentType = ApplicationContext.Current.Services.ContentTypeService.GetContentType("umbNewsItem");
                var nodes = ApplicationContext.Current.Services.ContentService.GetContentOfContentType(contentType.Id).Select(content => new Node(content.Id));
    
                return nodes.Select(node => new BlogPost()
                                                       {
                                                            Id = node.Id,
                                                            CustomProperty = node.GetProperty("customPropertyAlias").ToNullSafeString()
                                                       }).ToList();
            }
    

    The ContentService applies to Umbraco 6.x and newer: https://our.umbraco.org/documentation/reference/management/services/contentservice

  • Jonathan Ben Avraham 43 posts 216 karma points
    May 05, 2016 @ 10:09
    Jonathan Ben Avraham
    0

    I seem to get an compilation error when using this:

    Member 'Umbraco.Core.ApplicationContext.Current.get' cannot be accessed with an instance reference; qualify it with a type name instead
    

    So I did this:

    public List<BlogPostsList> getPostList()
        {
            string name = "umbNewsItem";
            var contentType = ApplicationContext.Current.Services.ContentTypeService.GetContentOfContentType(string name );
            var nodes = ApplicationContext.Current.Services.ContentService.GetContentOfContentType(contentType.Id).Select(content => new Node(content.Id));
    
            return nodes.Select(node => new BlogPostNew()
            {
                Id = node.Id,
                Title = node.GetProperty("Title").ToNullSafeString(),
                Content = node.GetProperty("Content").ToNullSafeString(),
                Author = node.GetProperty("Author").ToNullSafeString(),
                PubDate = node.GetProperty("Publish date").ToNullSafeString()
            }).ToList();
        }
    

    Because GetContentType isn't a valid method for ContentService.

    I am still however getting an error but it's changed:

    CS1513: } expected
    
  • Dennis Adolfi 1082 posts 6446 karma points MVP 5x c-trib
    May 05, 2016 @ 11:18
    Dennis Adolfi
    1

    Because GetContentType isn't a valid method for ContentService.

    No, its a part of ContentTypeService, not ContentService.

    ContentTypeService.GetContentType() method is a part of the ContentTypeService and you can pass in either a id (int) or an alias (string) https://our.umbraco.org/documentation/reference/Management/Services/ContentTypeService.

    Looking at your code i see you are using the method ContentService.GetContentOfContentType() with a string parameter which is not supported according to https://our.umbraco.org/documentation/reference/Management/Services/ContentService, it should be an integer parameter for the id.

    Did you copy the exact code I posted without any adjustments? Becaus that code works for me on Umbraco 7.4.2 and i get a list of all my blogposts. Maybe it might be a version issue? What version are you using?

    Also, note that you are not supposed to create an instance of ApplicationContext, you access directly. The compilation errror you got initially indicates that you have created a instance of ApplicationContext.

    Best of luck!!

  • Jonathan Ben Avraham 43 posts 216 karma points
    May 05, 2016 @ 12:20
    Jonathan Ben Avraham
    1

    I realized I made a bit of a stuff up with it, not to worry, I sorted that out:

    public List<BlogPostsList> getPostList()
        {
            var contentType = ApplicationContext.Current.Services.ContentTypeService.GetContentType((string)"umbNewsItem");
            var nodes = ApplicationContext.Current.Services.ContentService.GetContentOfContentType(contentType.Id).Select(content => new Node(content.Id));
    
            return nodes.Select(node => new BlogPostNew()
            {
                Id = node.Id,
                Title = node.GetProperty("Title").ToNullSafeString(),
                Content = node.GetProperty("Content").ToNullSafeString(),
                Author = node.GetProperty("Author").ToNullSafeString(),
                PubDate = node.GetProperty("Publish date").ToNullSafeString()
            }).ToList();
        }
    

    The only issue now is that it's not finding the Node namespace and I've used the using references on the Service pages.

    Update

    Never mind, I fixed that too, I wasn't using umbraco.NodeFactory;

    It's throwing an issue saying that the object reference is not set to an instance of an object.

  • Dennis Adolfi 1082 posts 6446 karma points MVP 5x c-trib
    May 05, 2016 @ 12:30
    Dennis Adolfi
    1

    So everything is working except that it cant find the Node reference? Sounds close! :) Try add this:

    using umbraco.NodeFactory;
    

    Please let me know if this works out for you!

  • Jonathan Ben Avraham 43 posts 216 karma points
    May 05, 2016 @ 12:44
    Jonathan Ben Avraham
    0

    You're a star! That was an obvious miss there for me, but now I don't understand why this part is telling me that:

    Object reference not set to an instance of an object.

    return nodes.Select(node => new BlogPostsList()
            {
                Id = node.Id,
                Title = node.GetProperty("Title").ToString(),
                Content = node.GetProperty("Content").ToString(),
                Author = node.GetProperty("Author").ToString(),
                PublishDate = node.GetProperty("Publish date").ToString()
            })
    
  • Dennis Adolfi 1082 posts 6446 karma points MVP 5x c-trib
    May 05, 2016 @ 12:52
    Dennis Adolfi
    1

    Thank you. :)

    The GetProperty() method returns a object and if that property is null, the ToString() method will throw a nullreference exception.

    Try the ToNullSafeString() instead.

    return nodes.Select(node => new BlogPostsList()
            {
                Id = node.Id,
                Title = node.GetProperty("Title").ToNullSafeString(),
                Content = node.GetProperty("Content").ToNullSafeString(),
                Author = node.GetProperty("Author").ToNullSafeString(),
                PublishDate = node.GetProperty("Publish date").ToNullSafeString()
            })
    
  • Jonathan Ben Avraham 43 posts 216 karma points
    May 05, 2016 @ 13:01
    Jonathan Ben Avraham
    0

    New error:

    CS1061: 'umbraco.interfaces.IProperty' does not contain a definition for 'ToNullSafeString' and no extension method 'ToNullSafeString' accepting a first argument of type 'umbraco.interfaces.IProperty' could be found (are you missing a using directive or an assembly reference?)
    

    Thanks :)

  • Dennis Adolfi 1082 posts 6446 karma points MVP 5x c-trib
    May 05, 2016 @ 13:09
    Dennis Adolfi
    0

    Oh, my bad. Im using the AutoMapper.Internal extension method.

    Either add the using AutoMapper.Internal (make sure your solution references the AutoMapper.dll) or make sure all the properties is not null before you do ToString():

    return nodes.Select(node => new BlogPostsList()
                {
                    Id = node.Id,
                    Title = node.GetProperty("Title") != null ? node.GetProperty("Title").ToString() : "",
                    Content = node.GetProperty("Content") != null ? node.GetProperty("Content").ToString() : "",
                    Author = node.GetProperty("Author") != null ? node.GetProperty("Author").ToString() : "",
                    PublishDate = node.GetProperty("Publish date") != null ? node.GetProperty("Publish date").ToString() : ""
                });
    
  • Jonathan Ben Avraham 43 posts 216 karma points
    May 05, 2016 @ 15:40
    Jonathan Ben Avraham
    0

    Now I have ensured ToNullSafeString is working, for whatever reason it's not fetching the properties...

    any ideas?

    return nodes.Select(node => new BlogPostsList()
            {
                Id = node.Id,
                Title = node.GetProperty("umbTitle").ToNullSafeString(),
                Author = node.GetProperty("author").ToNullSafeString(),
                Content = node.GetProperty("content").ToNullSafeString(),
                PublishDate = node.GetProperty("publish date").ToNullSafeString()
            }).ToList();
        }
    
  • Dennis Adolfi 1082 posts 6446 karma points MVP 5x c-trib
    May 05, 2016 @ 16:22
    Dennis Adolfi
    0

    That's strange. Could you double check that you've given the correct alias for the contentType? I see in your code you wrote "umbNewsItem" and in the post header you wrote "umbNewsItems". Also check that the propertyAliases are correct. Can you debug the code in VS or something to make sure you get the correct nodes?

  • Dennis Adolfi 1082 posts 6446 karma points MVP 5x c-trib
    May 06, 2016 @ 06:52
    Dennis Adolfi
    0

    Hi again Jonathan. Did it work out for you or are you still having problems with this? If so, could you post your code (complete class, not just the method) and maybe i can help you find whats missing.

  • Jonathan Ben Avraham 43 posts 216 karma points
    May 06, 2016 @ 10:32
    Jonathan Ben Avraham
    0

    I'm pretty sure it's umbNewsItem.

    When I change it to umbNewsItems it throws me an "object reference not set to an instance of an object" exception on line.

    I think it's maybe the property strings which might be wrong?

  • Dennis Adolfi 1082 posts 6446 karma points MVP 5x c-trib
    May 06, 2016 @ 10:53
    Dennis Adolfi
    0

    Could be, have you double checked that the property string aliases are correct?

  • Jonathan Ben Avraham 43 posts 216 karma points
    May 06, 2016 @ 13:07
    Jonathan Ben Avraham
    0

    Checked it all, still pulling through null:

    here is my entire class:

    using ExportUmbracoBlogsPackage.Models;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Web;
    using System.Web.Mvc;
    using System.Text;
    using System.Data;
    using System.Data.SqlClient;
    using Umbraco.Core.Persistence;
    using Umbraco.Web;
    using Umbraco.Web.WebApi;
    using Umbraco.Core;
    using Umbraco.Core.Models;
    using Umbraco.Core.Services;
    using umbraco.NodeFactory;
    using AutoMapper.Internal;
    
    namespace ExportUmbracoBlogsPackage.App_Code
    {
        public class ExportAllBlogsController : UmbracoAuthorizedApiController
        {
            StringBuilder sb = new StringBuilder();
            [System.Web.Http.AcceptVerbs("GET", "POST")]
            public void ExportAll()
            {
                List<BlogPostsList> BlogPostList = new List<BlogPostsList>();
                BlogPostList = getPostList();
    
                string attachment = "attachment; filename= BlogPosts.csv;";
                HttpContext.Current.Response.Clear();
                HttpContext.Current.Response.ClearHeaders();
                HttpContext.Current.Response.ClearContent();
                HttpContext.Current.Response.AddHeader("Content-Disposition", attachment);
                HttpContext.Current.Response.ContentType = "text/csv";
                HttpContext.Current.Response.AddHeader("Pragma", "public");
                HttpContext.Current.Response.CacheControl= "private";
    
                WriteColumnName();
                foreach (BlogPostsList post in BlogPostList)
                {
                    WritePostInfo(post);
                }
    
                HttpContext.Current.Response.Flush();
                HttpContext.Current.Response.End();
            }
    
            private void WritePostInfo(BlogPostsList post)
            {
                AddComma(post.Title, sb);
                AddComma(post.Author, sb);
                AddComma(post.Content, sb);
                AddComma(post.PublishDate.ToString(), sb);
                HttpContext.Current.Response.Write(sb.ToString());
                HttpContext.Current.Response.Write(Environment.NewLine);
            }
    
            private void AddComma( string value, StringBuilder sb )
            {
                sb.Append(value.Replace(',', ' '));
                sb.Append(", ");
            }
    
            private void WriteColumnName()
            {
                string columnNames = "Title, Author, Content, Publish Date";
                HttpContext.Current.Response.Write(columnNames);
                HttpContext.Current.Response.Write(Environment.NewLine);
            }
    
            //public List<BlogPosts> getPostList()
            //{
            //    UmbracoDatabase db = ApplicationContext.DatabaseContext.Database;
            //    var select = new Sql("SELECT dataNtext FROM cmsPropertyData WHERE propertytypeid = 57;");
            //    List<BlogPosts> BlogPostList = new List<BlogPosts>();
            //    BlogPostList = db.Fetch<BlogPosts>(select);
            //    return BlogPostList;
            //}
    
            public List<BlogPostsList> getPostList()
            {
                var contentType = ApplicationContext.Current.Services.ContentTypeService.GetContentType("umbNewsItem");
                var nodes = ApplicationContext.Current.Services.ContentService.GetContentOfContentType(contentType.Id).Select(content => new Node(content.Id));
    
                return nodes.Select(node => new BlogPostsList()
                {
                    Id = node.Id,
                    Title = node.GetProperty((string)"title").ToNullSafeString(),
                    Author = node.GetProperty((string)"author").ToNullSafeString(),
                    Content = node.GetProperty((string)"bodyText").ToNullSafeString(),
                    PublishDate = node.GetProperty((string)"publishDate").ToNullSafeString()
                }).ToList();
            }
        }
    }
    

    I'm not sure what's going on here, now I'm getting an object reference not set to an instance of an object on this line:

                sb.Append(value.Replace(',', ' '));
    

    It's saying sb is not an instance of an object.

  • Dennis Adolfi 1082 posts 6446 karma points MVP 5x c-trib
    May 06, 2016 @ 13:35
    Dennis Adolfi
    0

    Its probobly value that is null, and when you try to run Replace() on a null object, it throws an exception. Replace it with this:

    private void AddComma(string value, StringBuilder sb)
            {
                if (value != null)
                {
                    sb.Append(value.Replace(',', ' '));
                    sb.Append(", ");
                }
            }
    
  • Dennis Adolfi 1082 posts 6446 karma points MVP 5x c-trib
    May 09, 2016 @ 06:08
    Dennis Adolfi
    1

    Hi Jonathan.

    Did this work out for you? Did the nullcheck fix the problem?

  • Jonathan Ben Avraham 43 posts 216 karma points
    May 09, 2016 @ 08:30
    Jonathan Ben Avraham
    0

    unfortunately not :( It just runs the script and nothing happens and the tab that open to run the script which downloads the csv file, returns a DNS error.

  • Jonathan Ben Avraham 43 posts 216 karma points
    May 09, 2016 @ 08:41
    Jonathan Ben Avraham
    1

    Yeah it is working if I remove Publish Date. hmm not entirely sure, also the sheet ends up looking like this:

    http://pasteboard.co/N046g0E.png

    Not sure why it's doing this, it's not finding the title or author data.

  • Dennis Adolfi 1082 posts 6446 karma points MVP 5x c-trib
    May 09, 2016 @ 09:33
    Dennis Adolfi
    1

    Sounds like a formatting error on the publish date.

    Did you open this in Visual Studio so that you can step through and debug. I think that will solve a lot of your ploblem.

    Sounds like you are close anyway. :)

    Best of luck to you!!

  • Jonathan Ben Avraham 43 posts 216 karma points
    May 09, 2016 @ 09:55
    Jonathan Ben Avraham
    0

    Hi Dennis,

    I now have the publish date working, however it's still not pulling the data for the title or author. I have the alias correct for title, but I'm not sure what the alias for Author is, because it doesn't specifically say.

    Figured out: I can use a userSelector datatype and I was missing text in the title section because the page title was being pulled through to the front end as the blog title. So I managed to sort that out, new problem is that my CSV has multiple rows of the same data.

    Thanks, Jonathan

  • Jonathan Ben Avraham 43 posts 216 karma points
    May 09, 2016 @ 13:38
    Jonathan Ben Avraham
    100

    Sorted!

    I moved the instance of StringBuilder into the WritePostInfo method.

    Thanks, Jonathan

  • Dennis Adolfi 1082 posts 6446 karma points MVP 5x c-trib
    May 09, 2016 @ 13:45
    Dennis Adolfi
    1

    Awsome Jonathan, im happy to hear that it worked out for you!!! :)

    Best of luck to you with the rest of this package!!

    Have a great day!!

Please Sign in or register to post replies

Write your reply to:

Draft