jqgrid + EF + MVC:是否可以使用始终相同的控制器操作在Excel中导出?

时间:2012-02-17 18:52:05

标签: asp.net-mvc asp.net-mvc-3 excel jqgrid export

我正在使用 jqgrid(标准)和EF 4 + MVC3 。我想实现excel导出,如果可能的话,使用相同的动作控制器来填充网格。 我想知道是否有可能/合理地传递一个额外的参数,例如。你建议我使用哪种方法? 我问这个问题是因为我还在接近实施excel导出,如果可能的话,我想优化/重用代码。

要生成excel,我希望使用Stephen Walther博士的this library,它有三种类型的输出,并允许定义标题。如果您发现它对我的目的有效,请告诉我。

关于jqgrid代码,我找到了Oleg的this interesting answer,但我不明白是否可以应用于我的需求。

不幸的是,到目前为止我只发现了使用EF MVC进行excel导出的部分解决方案,但没有解决方案或完整的示例......

这是包含我的jqgrid

的_Index局部视图
  <table id="mygrid"></table>
  <div id="pager2"></div>

  jQuery("#mygrid").jqGrid({
url:'controller/jqIndex',
datatype: "json",
colNames:['id','field1', ...],
colModel:[
    {name:'id',index:'id', width:55},
    {name:'field1',index:'field1', width:90},
            ...
],
rowNum:10,
rowList:[10,20,30],
pager: '#pager2',
sortname: 'id',
viewrecords: true,
sortorder: "desc",
caption:"modal jquery + jqgrid test"}); 
jQuery("#list2").jqGrid('navGrid','#pager2',{edit:false,add:false,del:false});

//TODO
???
...some code to call the controller action with the `excel` parameter set `true`

CONTROLLER(基于OLEG'S IMPLEMENTATION

     public ActionResult jqIndex(string sidx, string sord, int page, int rows, bool _search, string filters, bool excel) // note the excel parameter <<
       {
        var context = new TManagerContext();
        var objectContext = context.ObjectContext();

        var set = objectContext.CreateObjectSet<Ticket>();
        var serializer = new JavaScriptSerializer();

        Filters f = (!_search || string.IsNullOrEmpty(filters)) ? null : serializer.Deserialize<Filters>(filters);
        ObjectQuery<Ticket> filteredQuery = (f == null ? (set) : f.FilterObjectSet(set));

        filteredQuery.MergeOption = MergeOption.NoTracking; // we don't want to update the data


        int totalRecords = filteredQuery.Count();

        var pagedQuery = filteredQuery.Skip("it." + sidx + " " + sord, "@skip",
                                    new ObjectParameter("skip", (page - 1) * rows))
                             .Top("@limit", new ObjectParameter("limit", rows));

        int pageIndex = Convert.ToInt32(page) - 1;
        int pageSize = rows;

        int totalPages = (int)Math.Ceiling((float)totalRecords / (float)pageSize);

        var queryDetails = (from e in pagedQuery
                            select new
                            {
                                e.TicketID,
                                e.field1,
                                ...
                            }).ToList();

        var result = new
        {
            total = totalPages,
            page = page,
            records = totalRecords,
            rows = (from e in queryDetails
                    select new
                    {
                        id = e.TicketID,
                        cell = new string[]
                        {
                            e.field1,
                            ...
                        }

                    }).ToArray()
        };

         if (excel) {
            ExportExcel(result); // if possible, pass filter parameters too, column order, etc...
         }

        return Json(result, JsonRequestBehavior.AllowGet);
    }

如果问题可能很愚蠢,请抱歉。我只是一个(爱好者)初学者。

感谢您的宝贵帮助! 最诚挚的问候

1 个答案:

答案 0 :(得分:2)

拉里 - 一些评论。

  1. 你不应该在控制器中做那么多逻辑。全部移动 那个业务逻辑到另一个类/服务。然后你的行动 方法只是几行。一个简单的例子

  2. public JsonResult jqIndex(string sidx, string sord, int page, int rows, 
                              bool _search, string filters){
            return JSON(this.GridQueryService.GetJQGrid(sidx,sord,page,rows,_search,filters), JsosnRequestBehavior.AllowGet);
            }
    

    2.我知道你不想重复代码(第1点有帮助),但这里有很多参数和东西,不适用于Excel(页面,行)。

    3.Passing布尔参数来改变函数如何快速变得混乱。让我们假设你现在需要将更多/更少的数据传递给Excel文件,现在你已经遍布整个地方嵌套条件,单元测试就会变得很糟糕。

    4.一个excel动作方法应该有一个FileResult返回类型,而不是一个     JSON结果(我猜他们都是行动结果,但是这会使你的意图在你的代码中更清晰。你的定义应该像


    public FileResult GetExcelFile(string sidx, string sord, bool _search, 
                                   string filters){
                  //do stuff to return Excel
            }
    

    如果您在第一点创建服务,使得您有两种方法返回不同的项目,但共享一个共同的查询/搜索基础功能,那么您在遵循单一责任原则时确实处于干燥状态。这个服务的一个例子可能是(非常粗略的例子,应该给你一些思考的东西):

    public class GridQueryService{
       public YourViewModel GetJQGrid(sidx, page, row, _search, filters){
          //Get the base data 
          var myData = this.GetGridData(sidx, _search, filters);
          //Create your view model and return it back to controller
    } 
       public StreamWriter GetExcelFIle(sidx, _search, filters){
          //Get the base data 
          var myData = this.GetGridData(sidx, _search, filters);
          //Create your Excel file and return it to the controller
    }
    
        private ObjectQuery<Ticket> GetGridData(string sidx, bool _search, string filters){
         //do your data grabbing here - you never return the raw data back to anything outside
         //of this service, so it should be ok to make private
    }
    
    }