Copied to clipboard

Flag this post as spam?

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


  • Matthieu Nelmes 102 posts 385 karma points
    Nov 11, 2015 @ 17:26
    Matthieu Nelmes
    0

    Exporting CSV from BackOffice (non usercontrol)

    The decision to try a non usercontrol approach was because I've managed to create a custom property editor that renders a list-view. So I wanted to stick with my angular/MVC approach.

    Struggling to see how I can force download as it seems the UmbracoAuthorizedApiController only returns Json so I'm open to suggestions.

    [Umbraco.Web.Mvc.PluginController("My.Admin")]
    public class RoomListExportApiController : UmbracoAuthorizedApiController
    {
        [System.Web.Http.AcceptVerbs("GET", "POST")]
        [System.Web.Http.HttpGet]
        public FileContentResult DownloadCsv()
        {
            string csv = "test,test1,test2";
            FileContentResult result = new FileContentResult(new System.Text.UTF8Encoding().GetBytes(csv), "text/csv");
            return result;
        }
        }
    

    This only returns Json. I guess I could use a plain old SurfaceController but wouldn't this compromise security?

  • Matthieu Nelmes 102 posts 385 karma points
    Nov 11, 2015 @ 18:39
    Matthieu Nelmes
    0

    Found a solution! A well written tutorial here was exactly what I was looking for!

    http://umbracodevelopers.sdesign1dev.co.uk/2015/7/30/ajax-newsletter-sign-up/

  • Taylor Mitchell 19 posts 43 karma points
    Nov 16, 2015 @ 22:16
    Taylor Mitchell
    2

    This may be old, but this is how I solved it:

    I created an export button with angular with exportForms as the action

    exportForms: function(type) {
                return $http.post("backoffice/MySection/ExportAction/export");
            }
    

    I then built an authorization handler. Just something simple to check if the user was logged in

    public class AuthorizationHandler
    {
        public static bool UserLoggedIn()
        {
            var httpCtxWrapper = new HttpContextWrapper(HttpContext.Current);
            var umbTicket = httpCtxWrapper.GetUmbracoAuthTicket();
            if (umbTicket == null || umbTicket.Name.IsEmpty() || umbTicket.Expired)
                return false;
            return true;
        }
    }
    

    Then I built a surface controller which throws an unauthorized if someone is not logged in.

    public class ExportActionsController : SurfaceController
    {
        public ActionResult Export(string type)
        {
            if (AuthorizationHandler.UserLoggedIn())
            {
                var query = //my sql statement here
                var forms = DatabaseContext.Database.Fetch<dynamic>(query);
    
                ExcelService.ExportForm(forms, type);
    
                if (HttpContext.Request.UrlReferrer != null)
                {
                    return Redirect(HttpContext.Request.UrlReferrer.AbsoluteUri);
                }
                return Redirect("/#/MySection");
            }
            else
            {
                throw new HttpException(401, "Unauthorized access");
            }
        }
    }
    

    Then I had to handle the exporting. I like to use closedXML.

    I'm modifying this code a bit because my original is a bit more complex.

        public class ExcelService
       {
           public static void ExportForm<T>(IEnumerable<T> forms, string filename)
          {
            XLWorkbook wb = new XLWorkbook();
    
            //this handles exporting my data into a datatable. You have to build this yourself.
            DataTable dt = ToDataTable(forms.ToList());
    
            //adds a worksheet with the data and the filename is the sheet name
            wb.Worksheets.Add(dt, filename);
    
            //This handles the download.
            HttpResponse httpResponse = HttpContext.Current.Response;
            httpResponse.Clear();
    
            //tell it the content type
            httpResponse.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    
            //give it your filename
            httpResponse.AddHeader("content-disposition", "attachment;filename=\"" + filename + " " + DateTime.Now.ToShortDateString() + ".xlsx\"");
    
            MemoryStream memoryStream = new MemoryStream();
    
            //save the workbook as a memory stream
            wb.SaveAs(memoryStream);
    
            //write file to users computer
            memoryStream.WriteTo(httpResponse.OutputStream);
    
            //never forget to close the stream and the response
            memoryStream.Close();
    
            httpResponse.End();
           }
        }
    

    Hope that helps

  • Biagio Paruolo 1621 posts 1914 karma points c-trib
    Dec 02, 2015 @ 15:04
    Biagio Paruolo
    0

    like

  • Matthieu Nelmes 102 posts 385 karma points
    Nov 16, 2015 @ 23:22
    Matthieu Nelmes
    0

    Thanks Taylor, I'll take a look.

    I did get a version working with some AngularJs magic but it's always worth exploring other options!

  • Michele Di Maria 34 posts 239 karma points
    Mar 30, 2021 @ 14:43
    Michele Di Maria
    1

    Thank you @Taylor Mitchell !!

    For Umbraco 8 things are a little different, but your reply was a very good starting point.

    The button in the html file changes to a simple link:

    <umb-button type="link"
        button-style="link"
        label="Scarica PDF"                            
        href="/umbraco/surface/BackofficeDownload/DownloadPDF?ID={{model.dialogData.IDData}}">
    </umb-button>
    

    Then the controller changes to:

    namespace XXX.Controllers
    {
        public class BackofficeDownloadController : SurfaceController
        {
            private readonly ILogger _logger;
    
            public BackofficeDownloadController()
            {
            }
    
            public BackofficeDownloadController(ILogger _logger)
            {
                this._logger = _logger;
            }
    
            [HttpGet]
            public ActionResult DownloadPDF(int ID)
            {
                if (AuthorizationHandler.UserLoggedIn())
                {
                    try
                    {
                        DocumentGenerator generatore = new DocumentGenerator ();
                        generatore.GeneratePDF(ID);
                        if (Request.UrlReferrer != null)
                        {
                            return new RedirectResult(Request.UrlReferrer.AbsoluteUri);
                        }
                        return new RedirectResult("/#/Preventivi");
                    }
                    catch (Exception ex)
                    {
                        Console.Write(ex.ToString());
                        _logger.Error("Error in BackofficeDownloadController.DownloadPDF", ex);
                        return null;
                    }
                }
                else
                {
                    throw new HttpException(401, "Unauthorized access");
                }
            }
        }
    }
    

    The Authorization Handler remains the same

    public class AuthorizationHandler
    {
        public static bool UserLoggedIn()
        {
            var httpCtxWrapper = new HttpContextWrapper(HttpContext.Current);
            var umbTicket = httpCtxWrapper.GetUmbracoAuthTicket();
            if (umbTicket == null || umbTicket.Identity == null || umbTicket.Identity.Name.IsEmpty() || !umbTicket.Identity.IsAuthenticated)
                return false;
            return true;
        }
    }
    

    Finally the document generator is whatever you need to create the document. In this case I am using ASPOSE.Words to generate a PDF file from a Word Document.

    public void GeneratePDF(int ID)
      {
            Document documento;
    
            try
            {
                MemoryStream stream = new MemoryStream();
                documento = GeneraDocumento(ID);
                documento.Save(stream, SaveFormat.Pdf);
                System.Web.HttpContext.Current.Response.Clear();
                System.Web.HttpContext.Current.Response.Buffer = true;
                System.Web.HttpContext.Current.Response.ContentType = "application/pdf";
                System.Web.HttpContext.Current.Response.AddHeader("content-length", stream.Length.ToString());
                System.Web.HttpContext.Current.Response.AddHeader("content-disposition", string.Format(@"attachment;filename=""Preventivo_{0}.pdf""", IDPreventivo));
                System.Web.HttpContext.Current.Response.BinaryWrite(stream.ToArray());
                System.Web.HttpContext.Current.Response.End();
            }
            catch (Exception ex)
            {
                Umbraco.Web.Composing.Current.Logger.Error(typeof(GeneratoreDocumenti), ex, "Error in DocumentGenerator.GeneratePDF");
            }
        }
    

    I hope it helps to someone else, as the previous answers helped me.

    Michele

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies