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?
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();
}
}
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.
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.
This only returns Json. I guess I could use a plain old SurfaceController but wouldn't this compromise security?
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/
This may be old, but this is how I solved it:
I created an export button with angular with exportForms as the action
I then built an authorization handler. Just something simple to check if the user was logged in
Then I built a surface controller which throws an unauthorized if someone is not logged in.
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.
Hope that helps
like
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!
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:
Then the controller changes to:
The Authorization Handler remains the same
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.
I hope it helps to someone else, as the previous answers helped me.
Michele
is working on a reply...