2014-02-10 39 views
0

我有一个简单的HomeController与一个重载(GET/POST)索引方法,它显示一个HTML表中的Person对象列表中的数据,并为用户提供一个表单他们可以输入工作表名称和文件名并下载结果的Excel文件(EPPlus Excel library)并下载它们。要封装救我创建了以下视图模型的Excel文件所需的信息:在ASP.NET MVC 4中的扩展方法HttpPost ActionResult

public class ExcelDownloadView 
    { 
     public List<Person> Persons { get; set; } 
     //ConvertToDataTable is a List extension method return converts the list and its properties 
     //into a table where columns are the properties 
     public DataTable DataTable { get { return Persons.ConvertToDataTable(); } } 
     public string SheetName { get; set; } 
     public string FileName { get; set; } 
    } 

这里是我的观点的样子,并在最初的GET请求,一切都出来罚款:

@model ExportToExcel.Models.ExcelDownloadView 
@using ExportToExcel.Helpers 
@{ 
    ViewBag.Title = "Index"; 

} 
<div id="grid"> 
@Html.ListToTable(Model.Persons) 

</div> 
<div> 
This is the number of rows: @Model.DataTable.Rows.Count (correct) 
</div> 


    @using (Html.BeginForm()) 
    { 
     <input name="sheetName" type="text" /><br /> 
     <input name="fileName" type="text" /><br /> 
     <input type="submit" value="Click to download Excel file..." /> 
    } 

当我尝试提交表单我在ConvertToDataTable方法得到一个错误:

public static DataTable ConvertToDataTable<T>(this List<T> data) 
     { 
      DataTable dt = new DataTable(); 
      PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T)); 
      for (int i = 0; i < props.Count; i++) 
      { 
       PropertyDescriptor prop = props[i]; 
       dt.Columns.Add(prop.Name, prop.PropertyType); 
      } 
      object[] values = new object[props.Count]; 
      //*****error is at the start of the foreach loop 
      foreach (T item in data) 
      { 
       for (int i = 0; i < values.Length; i++) 
       { 
        values[i] = props[i].GetValue(item); 
       } 
       dt.Rows.Add(values); 
      } 
      return dt; 
     } 

控制器:

[HttpGet] 
     public ActionResult Index() 
     { 
      ExcelDownloadView model = new ExcelDownloadView(); 
      model.Persons = Person.GetPersons().ToList(); 
      var dataTable = model.Persons.ConvertToDataTable(); 
      return View(model); 
     } 
     [HttpPost] 
     public ActionResult Index(ExcelDownloadView viewModel) 
     { 
      //DataTable property takes the List<Person> of the view model and turns it into 
      //a datable for use in the following Excel-file-creating function 

      /*--> if nonWorkingVersion is commented out, the program programs with a NullReferenceException*/ 
      //DataTable nonWorkingVersion = viewModel.DataTable; 
      //if a re-seed the DataTable, everything works fine 
      DataTable dt = Person.GetPersons().ToList().ConvertToDataTable(); 

      using (ExcelPackage pck = new ExcelPackage()) 
      { 
       //Create the worksheet 
       ExcelWorksheet ws = pck.Workbook.Worksheets.Add(viewModel.SheetName); 

       //Load the datatable into the sheet, starting from cell A1. Print the column names on row 1 

       ws.Cells["A1"].LoadFromDataTable(dt, true); 
       //Format the header for column 1-3 
       using (ExcelRange rng = ws.Cells["A1:C1"]) 
       { 
        rng.Style.Font.Bold = true; 
        rng.Style.Fill.PatternType = ExcelFillStyle.Solid;      //Set Pattern for the background to Solid 
        rng.Style.Fill.BackgroundColor.SetColor(Color.FromArgb(79, 129, 189)); //Set color to dark blue 
        rng.Style.Font.Color.SetColor(Color.White); 
       } 

       //Example how to Format Column 1 as numeric 
       using (ExcelRange col = ws.Cells[2, 1, 2 + dt.Rows.Count, 1]) 
       { 
        col.Style.Numberformat.Format = "#,##0.00"; 
        col.Style.HorizontalAlignment = ExcelHorizontalAlignment.Right; 
       } 

       //Write it back to the client 

       Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; 
       Response.AddHeader("content-disposition", "attachment; filename=" + viewModel.FileName); 
       Response.BinaryWrite(pck.GetAsByteArray()); 
      } 
      return View(viewModel); 
     } 

在GET版本的Index方法中,数据在那里并且是正确的。为什么我的POST版本中的数据没有正确显示?如果我修改视图并删除对Persons属性的引用,将会弹出一个诊断对话框,我可以下载我想要的文件。为什么POST版本不能从GET版本接收人员的数据?

回答

1

首先要意识到这些操作是针对两个单独的请求调用的。首先在用户导航到页面时调用,第二次在用户看到页面,填写表单并提交时调用。

接下来是在ASP.NET MVC中你没有状态的事实。您所拥有的唯一信息是发布表单客户端。所以,即使在前一个请求中创建了一些对象,但这个对象与当前请求无关。在你的表单中有两个输入 - 这些是你请求的部分。

正确的方法来处理这是你已经实现。这就是说,如果您在请求期间需要查询某个数据库 - 通常您需要在每次请求时执行此操作。

+0

几乎我所想的,但不确定。我不知道是否使用静态方法来帮助初始化数据是问题的一部分;它知道它不会让我省时。谢谢。 – wootscootinboogie