繁体   English   中英

ASP.NET MVC 4 HttpPost ActionResult中的扩展方法

[英]Extension Method in ASP.NET MVC 4 HttpPost ActionResult

我有一个带有一个重载(GET / POST)索引方法的简单HomeController ,该方法可显示HTML表中Person对象列表中的数据,并为用户提供一种形式,用户可以在其中键入工作表名称和文件名并下载结果的Excel文件( EPPlus Excel库 )并下载。 为了封装保存Excel文件所需的信息,我创建了以下视图模型:

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);
        }

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

第一件事是要意识到针对两个单独的请求调用了这些操作。 当用户导航到页面时,第一个被调用,当用户看到页面,填写表单并提交时,第二个被调用。

接下来的事实是,在ASP.NET MVC中您没有状态。 您拥有的唯一信息是一个已发布的表单客户端。 因此,即使在先前的请求上创建了一些对象,该对象也与当前请求无关。 您的表单中有两个输入-这些是您请求中得到的。

解决此问题的正确方法是您已经实现的方法。 也就是说,如果您在请求期间需要一些数据库查询-通常,您需要对每个请求进行查询。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM