jqgrid + EF + MVC: можно ли экспортировать в Excel, используя всегда одно и то же действие контроллера?
Я использую jqgrid (стандартный) с EF 4 + MVC3. Я хотел бы реализовать экспорт Excel и, если возможно, использовать тот же контроллер действий, который использовался для заполнения сетки. Интересно, возможно ли / логично передать дополнительный параметр, например. Какой метод вы мне предложите? Я задаю этот вопрос, потому что я все еще планирую реализовать экспорт в Excel и хотел бы оптимизировать / повторно использовать код, если это возможно.
Чтобы генерировать Excel, я бы хотел использовать эту библиотеку доктора Стивена Вальтера, которая имеет три типа вывода и позволяет также определять заголовки. Пожалуйста, скажите мне, если вы найдете это действительным для моих целей.
Что касается кода jqgrid, я нашел этот интересный ответ Олега, но я не понимаю, можно ли применить его к моим потребностям.
К сожалению, к настоящему времени я нашел только части решений для экспорта в Excel с EF MVC, но не нашел решения или полных примеров...
Вот частичное представление _Index, содержащее мой 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`
КОНТРОЛЛЕР (НА ОСНОВЕ ОСУЩЕСТВЛЕНИЯ ОЛЕГА)
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 ответ
Ларри - Несколько комментариев.
- Вы не должны делать так много логики в вашем контроллере. Переместите всю эту бизнес-логику в другой класс / службу. Тогда ваш метод действия будет состоять из нескольких строк. Быстрый пример
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
}
}