2

Scenario: There are three views (Razor) named "InvoiceBill", "Index", "Create".

  1. The Create view contains the form page for entering Invoice data.
  2. The Index page contains the list of all current date invoice bills.
  3. The InvoiceBill contains the code which generate the excel document (as an invoice report) based on this link (http://forums.asp.net/t/1711971.aspx/1).

Once i submit the form (Create view) it can post the form data to the DB (using EF). After the data inserted, it returns the Index page.

But now i need to call the "InvoiceBill" view before calling Index page.

[HttpPost]
public ActionResult Create(FormCollection collection, InvoiceViewModel INVViewModel)
{
   if ((collection != null) && (this.ModelState.IsValid))
   {
        salesOrder.AccountNumber = INVViewModel.AccountNumber;
        salesOrder.BillToAddressID = INVViewModel.BillToAddressID;
        salesOrder.Comment = INVViewModel.Comment;
        salesOrder.ContactID = INVViewModel.ContactID;
        .
        .
        .
        .
        int sID = Using<CreateSalesOrder>().Execute(0, salesOrder);
***** From here i need to call the InvoiceBill page. Or guide me any other good way to achieve this
        return RedirectToAction("Index");
   }
}

Right now i am achieving this with some workarounds. But i feel that is not good. Please guide me how can i achieving this in a right way? Thanks

EDIT:

public ActionResult PrintInvoice(int id)
        {
            InvoiceReportViewModel invoiceReport = new InvoiceReportViewModel();
            var soToView = Using<GetSalesOrders>().ExecuteForReport(id);

            invoiceReport.InvoiceBillName = "Invoice" + id.ToString();
            invoiceReport.CustomerName = soToView.Customer.Name;
            invoiceReport.SalesOrderNumber = soToView.SalesOrderNumber;
            .
            .
            .
            .

            return View(invoiceReport);
        }

The InvoiceReport.cshtml

@model eItemBox.Web.Models.InvoiceReportViewModel
@{
    Layout = null;
    Response.ContentType = "application/vnd.ms-excel";
    Response.AddHeader("Content-Disposition", "attachment; filename=" + Model.InvoiceBillName);
    //Content-Disposition is defined in RFC-2183
}
<Worksheet ss:Name="MyInvoice">
.
.
.

</Workbook>
getmk
  • 155
  • 3
  • 13

1 Answers1

0

I suppose your question is very similar to this question. The only difference is, you need to save the output as Excel instead of sending it as Email.

Please try to use the RenderViewToString method from the question above:

public virtual string RenderViewToString(
  ControllerContext controllerContext,
  string viewPath,
  string masterPath,
  ViewDataDictionary viewData,
  TempDataDictionary tempData)
{
  Stream filter = null;
  ViewPage viewPage = new ViewPage();

  //Right, create our view
  viewPage.ViewContext = new ViewContext(controllerContext, new WebFormView(viewPath, masterPath), viewData, tempData);

  //Get the response context, flush it and get the response filter.
  var response = viewPage.ViewContext.HttpContext.Response;
  response.Flush();
  var oldFilter = response.Filter;

  try
  {
      //Put a new filter into the response
      filter = new MemoryStream();
      response.Filter = filter;

      //Now render the view into the memorystream and flush the response
      viewPage.ViewContext.View.Render(viewPage.ViewContext, viewPage.ViewContext.HttpContext.Response.Output);
      response.Flush();

      //Now read the rendered view.
      filter.Position = 0;
      var reader = new StreamReader(filter, response.ContentEncoding);
      return reader.ReadToEnd();
  }
  finally
  {
      //Clean up.
      if (filter != null)
      {
        filter.Dispose();
      }

      //Now replace the response filter
      response.Filter = oldFilter;
  }
}

UPDATE: Another (a little bit different) way of doing this, can be found here

Community
  • 1
  • 1
Alexander Yezutov
  • 3,144
  • 2
  • 21
  • 23
  • Thanks Alex. But unlikely i am getting this following error in the excel document. "Cannot redirect after HTTP headers have been sent." – getmk Dec 10 '11 at 10:25
  • I suppose the link from the update is about handling exactly same situation: http://mikehadlow.blogspot.com/2008/06/mvc-framework-capturing-output-of-view_05.html – Alexander Yezutov Dec 10 '11 at 11:12
  • In view words, `HttpContext.Current` should be used instead of `controllerContext.HttpContext.Response.Filter` – Alexander Yezutov Dec 10 '11 at 11:13
  • I have been edited the question, can you guide me where can i do changes – getmk Dec 12 '11 at 06:51