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

发布于 2025-01-07 06:03:26 字数 3786 浏览 1 评论 0原文

我正在使用jqgrid(标准)和 EF 4 + MVC3。我想实现 Excel 导出,如果可能的话,使用用于填充网格的相同操作控制器。 例如,我想知道传递附加参数是否可能/符合逻辑。您会建议我哪种方法? 我问这个问题是因为我仍在接近实现 Excel 导出,并且如果可能的话,我想优化/重用代码。

要生成 Excel,我想使用 此库 由 Dr Stephen Walther 提供,它具有三种类型的输出并允许定义标题也是。如果您认为它对我的目的有效,请告诉我。

关于jqgrid代码,我发现了Oleg的这个有趣的答案,但我不知道是否可以应用于我的需求。

不幸的是,到目前为止我只找到了使用 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`

控制器(基于 OLEG 的实现)

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

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

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

I am using jqgrid (standard) with EF 4 + MVC3. I'd like to implement excel export and if possible using the same action controller used to populate the grid.
I wonder if is it possible / logical to pass an additional parameter, for example. Which method you would suggest me?
I ask this question because I am still approaching to implement excel export and I'd like to optimize / re-use code, if possible.

To generate excel, I'd like to use this library by Dr Stephen Walther, which has three types of output and allows to define headers too. Please tell me if you find it valid for my purpose.

About the jqgrid code, I found this interesting answer by Oleg, but I do not understand if could be applied to my needs.

Unfortunately, by now I only found parts of solutions for excel export with EF MVC, but no solution or complete examples...

Here's the _Index partial view containing my jqgrid

  <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 (BASED ON 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);
    }

Please sorry if the question could be silly, I am just a (enthusiast) beginner.

Thanks for your precious help!
Best Regards

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

街道布景 2025-01-14 06:03:26

拉里 - 一些评论。

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

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.传递布尔参数来改变事物的功能可能会很快变得混乱。假设您现在需要向 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
}

}

Larry - A few comments.

  1. You shouldn't be doing that much logic in your controller. Move all
    of that business logic to another class/service. Then your action
    method would be just a few lines. A quick example

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.I know you don't want to repeat code (which point 1 helps) but there are many parameters and things here that simply do not apply to Excel (page, rows).

3.Passing boolean parameters to change how things function can get messy fast. Lets assume that you now need to pass more/less data to the Excel file, now you have nested conditions all over the place and Unit Testing would just be crappy.

4.An excel action method will should have a FileResult return type, not a
JSON result (I guess they are all action results, but this makes your intention all the more clear in your code. Your definition should be something like


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

If you create your Service in point one in such a way that you have two methods that return different items, but share a common query/search base function, then you are really staying Dry while following the Single Responsibility Principle. An example of this service might be (very rough example, should give you some things to think about):

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
}

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文