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.
我正在使用jqgrid(标准)和EF 4 + MVC3。我想实现excel导出,如果可能的话,使用用于填充网格的相同操作控制器。我想知道是否可能/逻辑地传递一个额外的参数,例如。你建议我采用哪种方法?我问这个问题是因为我还在接近实现excel导出,如果可能的话,我想优化/重用代码。
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.
为了生成excel,我想使用Stephen Walther博士的这个库,它有三种类型的输出,并允许定义header。如果你认为它对我的目的有效,请告诉我。
About the jqgrid code, I found this interesting answer by Oleg, but I do not understand if could be applied to my needs.
关于jqgrid代码,我在Oleg中找到了这个有趣的答案,但是我不明白是否可以应用于我的需要。
Unfortunately, by now I only found parts of solutions for excel export with EF MVC, but no solution or complete examples...
不幸的是,到目前为止,我只找到了部分使用EF MVC的excel导出解决方案,但没有解决方案或完整的示例……
Here's the _Index partial view containing my jqgrid
这是包含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 (BASED ON OLEG'S IMPLEMENTATION)
控制器(基于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);
}
Please sorry if the question could be silly, I am just a (enthusiast) beginner.
如果这个问题很愚蠢,请见谅,我只是一个初学者。
Thanks for your precious help! Best Regards
谢谢你的帮助!致以最亲切的问候
1 个解决方案
#1
2
Larry - A few comments.
赖瑞-有一些评论。
- 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).
2。我知道您不希望重复代码(这一点是有帮助的),但是这里有许多参数和东西,它们并不适用于Excel(页、行)。
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.
3所示。传递布尔参数来改变函数的运行方式会很快变得混乱。假设您现在需要向Excel文件传递更多或更少的数据,现在您到处都是嵌套条件,单元测试可能会很糟糕。
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
4所示。excel操作方法应该有一个FileResult返回类型,而不是JSON结果(我猜它们都是操作结果,但这使您的意图在代码中更加清晰。你的定义应该是这样的
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
}
}
#1
2
Larry - A few comments.
赖瑞-有一些评论。
- 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).
2。我知道您不希望重复代码(这一点是有帮助的),但是这里有许多参数和东西,它们并不适用于Excel(页、行)。
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.
3所示。传递布尔参数来改变函数的运行方式会很快变得混乱。假设您现在需要向Excel文件传递更多或更少的数据,现在您到处都是嵌套条件,单元测试可能会很糟糕。
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
4所示。excel操作方法应该有一个FileResult返回类型,而不是JSON结果(我猜它们都是操作结果,但这使您的意图在代码中更加清晰。你的定义应该是这样的
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
}
}